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('"&<'', ENT_QUOTES) then html_entity_decode('é', ENT_QUOTES, 'UTF-8') |
"&<' then "é" |
"&<' then null |
html_entity_decode('é') first, then htmlspecialchars_decode(...) |
"é" then "&<' |
same ✓ |
html_entity_decode('é') 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('"&<'', ENT_QUOTES));
var_dump(html_entity_decode('é', ENT_QUOTES, 'UTF-8'));
Done when
Category
Stdlib· php-src-strict /html_entity_decodeafterhtmlspecialchars_decodeProblem
html_entity_decode('é', ENT_QUOTES, 'UTF-8')matches Zend when it is the first HTML builtin in the compilation unit. Ifhtmlspecialchars_decode()runs first in the same script, the followinghtml_entity_decode()returnsnullinstead of"é".Order-reversed control (entity-decode then htmlspecialchars_decode) is green. Isolated
html_entity_decodeofé, ,é,©is green. This is silent wrong output (rc=0), not a TypeError.Likely shared HTML-helper / return-slot pollution between
htmlspecialchars_decodeandhtml_entity_decodelowering — not missing named-entity tables (those already work in isolation; closed #10763 / #4130 / #11510).Probed 2026-08-18 @
bf1a18dfa1— Zend 8.2.32 vsphp bin/vm.php/php bin/jit.php.htmlspecialchars_decode('"&<'', ENT_QUOTES)thenhtml_entity_decode('é', ENT_QUOTES, 'UTF-8')"&<'then"é""&<'thennullhtml_entity_decode('é')first, thenhtmlspecialchars_decode(...)"é"then"&<'html_entity_decode('é')alone"é""é"✓Related: a later
htmlspecialchars("\xC3\xA9")in a unit that already calledhtmlspecialchars(..., ENT_IGNORE)on invalid bytes also dumpednull(same helper-return class; keep this issue focused on the decode pair).php-src reference
ext/standard/html.c—PHP_FUNCTION(html_entity_decode)/PHP_FUNCTION(htmlspecialchars_decode)are separate; no cross-call clobberext/standard/html.stub.php—html_entity_decode(string $string, int $flags = ENT_QUOTES \| ENT_SUBSTITUTE \| ENT_HTML401, ?string $encoding = null): stringPHP implementation target
ext/standard/VmString.php—htmlspecialchars_decode()must not leave a null/empty return slot that the nexthtml_entity_decode()inheritsext/standard/HtmlspecialcharsDecodeJitHelper.php+ html-entity-decode JIT helper — distinct ABI/return; do not reuse a one-shot helper return box across the two builtinslib/JIT/HTML builtin dispatch if the two names fold to one compiled stubruntime/*.cRepro
Done when
htmlspecialchars_decode(...),html_entity_decode('é', ENT_QUOTES, 'UTF-8')returns"é"(Zend), notnullhtml_entity_decodeunchanged.phptundertest/compliance/cases/stdlib/covering both call orders