Skip to content

Stdlib: html_entity_decode() returns null after htmlspecialchars_decode() in the same unit (ext/standard/html.c) #32064

Description

@PurHur

Category

Stdlib · php-src-strict / html_entity_decode after htmlspecialchars_decode

Problem

html_entity_decode('é', ENT_QUOTES, 'UTF-8') matches Zend when it is the first HTML builtin in the compilation unit. If htmlspecialchars_decode() runs first in the same script, the following html_entity_decode() returns null instead of "é".

Order-reversed control (entity-decode then htmlspecialchars_decode) is green. Isolated html_entity_decode of é,  , é, © is green. This is silent wrong output (rc=0), not a TypeError.

Likely shared HTML-helper / return-slot pollution between htmlspecialchars_decode and html_entity_decode lowering — not missing named-entity tables (those already work in isolation; closed #10763 / #4130 / #11510).

Probed 2026-08-18 @ bf1a18dfa1 — Zend 8.2.32 vs php bin/vm.php / php bin/jit.php.

Repro Zend 8.2.32 VM/JIT
htmlspecialchars_decode('&quot;&amp;&lt;&#039;', ENT_QUOTES) then html_entity_decode('&eacute;', ENT_QUOTES, 'UTF-8') "&<' then "é" "&<' then null
html_entity_decode('&eacute;') first, then htmlspecialchars_decode(...) "é" then "&<' same ✓
html_entity_decode('&eacute;') alone "é" "é" ✓

Related: a later htmlspecialchars("\xC3\xA9") in a unit that already called htmlspecialchars(..., ENT_IGNORE) on invalid bytes also dumped null (same helper-return class; keep this issue focused on the decode pair).

php-src reference

PHP implementation target

  • ext/standard/VmString.php — htmlspecialchars_decode() must not leave a null/empty return slot that the next html_entity_decode() inherits
  • ext/standard/HtmlspecialcharsDecodeJitHelper.php + html-entity-decode JIT helper — distinct ABI/return; do not reuse a one-shot helper return box across the two builtins
  • lib/JIT/ HTML builtin dispatch if the two names fold to one compiled stub
  • No new runtime/*.c

Repro

./script/docker-exec.sh -- bash -lc 'php bin/vm.php test/repro/maintainer_gap_html_entity_decode_after_hs_decode.php'
./script/docker-exec.sh -- bash -lc 'php bin/jit.php test/repro/maintainer_gap_html_entity_decode_after_hs_decode.php'
./script/docker-exec.sh -- bash -lc 'php test/repro/maintainer_gap_html_entity_decode_after_hs_decode.php'  # Zend baseline
<?php
error_reporting(E_ALL);
var_dump(htmlspecialchars_decode('&quot;&amp;&lt;&#039;', ENT_QUOTES));
var_dump(html_entity_decode('&eacute;', ENT_QUOTES, 'UTF-8'));

Done when

  • VM/JIT: after htmlspecialchars_decode(...), html_entity_decode('&eacute;', ENT_QUOTES, 'UTF-8') returns "é" (Zend), not null
  • Reverse order and isolated html_entity_decode unchanged
  • Compliance .phpt under test/compliance/cases/stdlib/ covering both call orders
  • php-src-strict; no php-compiler-strict shortcut

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:vmVirtual machinebugSomething isn't workingimplementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claimphase-4:stdlibPhase 4 – stdlib for web appsstdlib

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions