Commit 73d71aa8e2f for php
commit 73d71aa8e2f0f141adfa5c8dbdea1d6d8b843e67
Author: lazerg <lazerg2@gmail.com>
Date: Fri Nov 13 06:11:20 2026 +0000
Fix GH-25434: C14NFile() skips namespace relinking on success
For modern DOM, dom_canonicalization() takes the xmlns:* attributes off their
elements before canonicalizing and puts them back at clean_links. On success,
C14NFile() returned early with RETURN_LONG(), so the declarations stayed
detached and the links table leaked. It now sets the return value and falls
through to the cleanup like C14N() does, returning false when
xmlOutputBufferClose() fails.
Close GH-25435
diff --git a/NEWS b/NEWS
index 9fbe37c9d27..a6a04bdbf15 100644
--- a/NEWS
+++ b/NEWS
@@ -39,6 +39,8 @@ PHP NEWS
dom_objects_store_clone_obj when cloning Dom\Notation). (David Carlier)
. Fixed bug GH-25306 (Assertion status == LXB_STATUS_OK in dom_parse_selector
when lexbor allocation fails). (ndossche)
+ . Fixed bug GH-25434 (C14NFile() on a Dom\XMLDocument leaves the document
+ changed and leaks memory). (lazerg)
- GD:
. Fixed use-after-free when drawing with a brush or tile image that was
diff --git a/ext/dom/node.c b/ext/dom/node.c
index 867d166edb4..e982cd6a13b 100644
--- a/ext/dom/node.c
+++ b/ext/dom/node.c
@@ -2331,7 +2331,11 @@ static void dom_canonicalization(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{
bytes = xmlOutputBufferClose(buf);
if (mode == 1 && (ret >= 0)) {
- RETURN_LONG(bytes);
+ if (bytes < 0) {
+ RETVAL_FALSE;
+ } else {
+ RETVAL_LONG(bytes);
+ }
}
}
diff --git a/ext/dom/tests/modern/xml/gh25434.phpt b/ext/dom/tests/modern/xml/gh25434.phpt
new file mode 100644
index 00000000000..22d8e8b3b79
--- /dev/null
+++ b/ext/dom/tests/modern/xml/gh25434.phpt
@@ -0,0 +1,22 @@
+--TEST--
+GH-25434 (C14NFile() on a Dom\XMLDocument leaves the document changed and leaks memory)
+--CREDITS--
+Wonseok Oh (marinelay)
+--EXTENSIONS--
+dom
+--FILE--
+<?php
+$doc = Dom\XMLDocument::createFromString('<root xmlns:p="urn:p"><p:a p:x="1"/></root>');
+var_dump($doc->C14NFile(__DIR__ . '/gh25434.xml'));
+echo file_get_contents(__DIR__ . '/gh25434.xml'), "\n";
+echo $doc->saveXml(), "\n";
+?>
+--CLEAN--
+<?php
+@unlink(__DIR__ . '/gh25434.xml');
+?>
+--EXPECT--
+int(48)
+<root xmlns:p="urn:p"><p:a p:x="1"></p:a></root>
+<?xml version="1.0" encoding="UTF-8"?>
+<root xmlns:p="urn:p"><p:a p:x="1"/></root>