Category
stdlib · php-src-strict · ext/dom
Problem
DOMDocument::saveXML() / saveHTML() accept a non-null non-DOMNode first argument on VM/JIT by treating a lone int/float as $options. Zend always types argument #1 as ?DOMNode and TypeErrors.
| Repro |
Zend 8.2+ |
VM/JIT (2026-08-16) |
$doc->saveXML(1) |
TypeError ?DOMNode, int given |
serializes whole document (int→options) |
$doc->saveXML(LIBXML_NOEMPTYTAG) |
same TypeError |
applies LIBXML_NOEMPTYTAG as options |
$doc->saveHTML(1) |
TypeError ?DOMNode, int given |
serializes HTML |
$doc->saveXML(null, LIBXML_NOEMPTYTAG) |
expands empty tags |
same (control) |
$doc->saveXML("x") |
TypeError string |
TypeError (message wording differs) |
Root cause: DomClassMethod::parseSaveNodeAndOptionsArgs() special-cases a single int/float as $options (comment cites #6140; that issue does not justify the coercion).
php-src reference
PHP implementation target
ext/dom/DomClassMethod.php — parseSaveNodeAndOptionsArgs() / saveSerializationOptionalDomNodeArg() — always treat arg1 as ?DOMNode; Zend-shaped TypeError
ext/dom/VmDomJitDispatch.php + DomSaveXMLJitHelper.php — mirror nullable node check for JIT/AOT bridges
Repro
./script/docker-exec.sh -- bash -lc 'php bin/vm.php test/repro/issue_dom_savexml_savehtml_node_typeerror.php'
./script/docker-exec.sh -- bash -lc 'php bin/jit.php test/repro/issue_dom_savexml_savehtml_node_typeerror.php'
Done when
Category
stdlib· php-src-strict · ext/domProblem
DOMDocument::saveXML()/saveHTML()accept a non-null non-DOMNodefirst argument on VM/JIT by treating a loneint/floatas$options. Zend always types argument #1 as?DOMNodeand TypeErrors.$doc->saveXML(1)TypeError?DOMNode, int given$doc->saveXML(LIBXML_NOEMPTYTAG)LIBXML_NOEMPTYTAGas options$doc->saveHTML(1)TypeError?DOMNode, int given$doc->saveXML(null, LIBXML_NOEMPTYTAG)$doc->saveXML("x")Root cause:
DomClassMethod::parseSaveNodeAndOptionsArgs()special-cases a single int/float as$options(comment cites #6140; that issue does not justify the coercion).php-src reference
ext/dom/php_dom.stub.php—saveXML(?DOMNode $node = null, int $options = 0),saveHTML(?DOMNode $node = null)ext/dom/document.c—dom_document_save_xml/save_htmlPHP implementation target
ext/dom/DomClassMethod.php—parseSaveNodeAndOptionsArgs()/saveSerializationOptionalDomNodeArg()— always treat arg1 as?DOMNode; Zend-shaped TypeErrorext/dom/VmDomJitDispatch.php+DomSaveXMLJitHelper.php— mirror nullable node check for JIT/AOT bridgesRepro
Done when
saveXML(1)/saveHTML(1)/saveXML(LIBXML_NOEMPTYTAG)TypeError like Zend (Argument #1 ($node) must be of type ?DOMNode, …)saveXML(null, LIBXML_NOEMPTYTAG)still works.phptundertest/compliance/cases/dom/