Category
Stdlib · php-src-strict / htmlspecialchars ENT_DISALLOWED
Problem
htmlspecialchars() / htmlentities() with ENT_DISALLOWED must replace C0 controls that are illegal in the chosen document type (HTML5 / HTML 4.01 / XML1) with U+FFFD (\xEF\xBF\xBD). Zend replaces "\x01" and "\x7F". VM/JIT leave the raw control bytes.
Without ENT_DISALLOWED, both sides keep "\x01" (correct). Distinct from open #32063 (ENT_IGNORE on invalid UTF-8 — different flag, different bytes).
VmString::htmlspecialchars() copies non-<>&"' bytes in the default arm and never consults ENT_DISALLOWED.
Probed 2026-08-18 @ ad82044529 — Zend 8.2.32 vs php bin/vm.php / php bin/jit.php.
| Repro |
Zend 8.2.32 |
VM/JIT |
htmlspecialchars("\\x01", ENT_DISALLOWED|ENT_HTML5, 'UTF-8') |
"\\u{FFFD}" (efbfbd) |
"\\x01" |
htmlentities("\\x01", ENT_DISALLOWED|ENT_HTML5, 'UTF-8') |
"\\u{FFFD}" |
"\\x01" |
htmlspecialchars("a\\x01b\\x7Fc", ENT_DISALLOWED|ENT_HTML5, 'UTF-8') |
a + U+FFFD + b + U+FFFD + c |
raw 01 / 7f kept |
htmlspecialchars("\\x01", ENT_HTML5, 'UTF-8') (no DISALLOWED) |
"\\x01" |
"\\x01" ✓ |
php-src reference
PHP implementation target
ext/standard/VmString.php — htmlspecialchars() / htmlentities(): when ENT_DISALLOWED is set, replace disallowed code points with "\u{FFFD}" (do not copy C0/DEL through)
ext/standard/HtmlspecialcharsJitHelper.php — same flags; reuse the PHP implementation
ext/standard/StdlibConstants.php already defines ENT_DISALLOWED = 128
- No new
runtime/*.c
Repro
./script/docker-exec.sh -- bash -lc 'php bin/vm.php test/repro/maintainer_gap_htmlspecialchars_ent_disallowed.php'
./script/docker-exec.sh -- bash -lc 'php bin/jit.php test/repro/maintainer_gap_htmlspecialchars_ent_disallowed.php'
./script/docker-exec.sh -- bash -lc 'php test/repro/maintainer_gap_htmlspecialchars_ent_disallowed.php' # Zend baseline
<?php
error_reporting(E_ALL);
$ctrl = "\x01";
var_dump(bin2hex(htmlspecialchars($ctrl, ENT_DISALLOWED | ENT_HTML5, 'UTF-8')));
var_dump(bin2hex(htmlentities($ctrl, ENT_DISALLOWED | ENT_HTML5, 'UTF-8')));
Done when
Category
Stdlib· php-src-strict /htmlspecialcharsENT_DISALLOWEDProblem
htmlspecialchars()/htmlentities()withENT_DISALLOWEDmust replace C0 controls that are illegal in the chosen document type (HTML5 / HTML 4.01 / XML1) with U+FFFD (\xEF\xBF\xBD). Zend replaces"\x01"and"\x7F". VM/JIT leave the raw control bytes.Without
ENT_DISALLOWED, both sides keep"\x01"(correct). Distinct from open #32063 (ENT_IGNOREon invalid UTF-8 — different flag, different bytes).VmString::htmlspecialchars()copies non-<>&"'bytes in thedefaultarm and never consultsENT_DISALLOWED.Probed 2026-08-18 @
ad82044529— Zend 8.2.32 vsphp bin/vm.php/php bin/jit.php.htmlspecialchars("\\x01", ENT_DISALLOWED|ENT_HTML5, 'UTF-8')"\\u{FFFD}"(efbfbd)"\\x01"htmlentities("\\x01", ENT_DISALLOWED|ENT_HTML5, 'UTF-8')"\\u{FFFD}""\\x01"htmlspecialchars("a\\x01b\\x7Fc", ENT_DISALLOWED|ENT_HTML5, 'UTF-8')a+ U+FFFD +b+ U+FFFD +c01/7fkepthtmlspecialchars("\\x01", ENT_HTML5, 'UTF-8')(no DISALLOWED)"\\x01""\\x01"✓php-src reference
ext/standard/html.c—php_escape_html_entities_ex;ENT_HTML_DISALLOWEDmaps disallowed Unicode scalars (C0 controls, DEL, noncharacters) to U+FFFDext/standard/html.stub.php—$flagsincludesENT_DISALLOWEDPHP implementation target
ext/standard/VmString.php—htmlspecialchars()/htmlentities(): whenENT_DISALLOWEDis set, replace disallowed code points with"\u{FFFD}"(do not copy C0/DELthrough)ext/standard/HtmlspecialcharsJitHelper.php— same flags; reuse the PHP implementationext/standard/StdlibConstants.phpalready definesENT_DISALLOWED = 128runtime/*.cRepro
Done when
ENT_DISALLOWED|ENT_HTML5on"\x01"yields U+FFFD (efbfbd);"a\x01b\x7Fc"replaces both controlshtmlentities(..., ENT_DISALLOWED)matcheshtmlspecialcharsENT_DISALLOWED,"\x01"is unchanged (Zend).phptundertest/compliance/cases/stdlib/