From 11d0356240ca67399ff52d2151254159f1f92167 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 29 Jan 2020 18:23:51 +0100 Subject: [PATCH] Fix #70078: XSL callbacks with nodes as parameter leak memory The fix for bug #49634 solved a double-free by copying the node with `xmlDocCopyNodeList()`, but the copied node is later freed by calling `xmlFreeNode()` instead of `xmlFreeNodeList()`, thus leaking memory. However, there is no need to treat the node as node list, i.e. to copy also the node's siblings; just creating a recursive copy of the node with `xmlDocCopyNode()` is sufficient, while that also avoids the leak. --- ext/xsl/tests/bug70078.phpt | 51 +++++++++++++++++++++++++++++++++++++ ext/xsl/xsltprocessor.c | 2 +- 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 ext/xsl/tests/bug70078.phpt diff --git a/ext/xsl/tests/bug70078.phpt b/ext/xsl/tests/bug70078.phpt new file mode 100644 index 0000000000000..41e9485a0f074 --- /dev/null +++ b/ext/xsl/tests/bug70078.phpt @@ -0,0 +1,51 @@ +--TEST-- +Bug #70078 (XSL callbacks with nodes as parameter leak memory) +--SKIPIF-- + +--FILE-- +appendChild($dom->createElement('root')); +for ($i = 0; $i <= 100; $i++) { + $level1Node = $rootNode->appendChild($dom->createElement('level1')); + for ($j = 0; $j <= 100; $j++) { + $level2Node = $level1Node->appendChild($dom->createElement('level2')); + for ($k = 0; $k <= 10; $k++) { + $level3Node = $level2Node->appendChild($dom->createElement('level3', 'test')); + } + } +} + +function testPhpFunction($node) { + return 'test2'; +} + +$xslStr = << + + + + + + + + + + + +EOF; + +$xsl = new \DOMDocument(); +$xsl->loadXML($xslStr); +$xslt = new \XSLTProcessor(); +$xslt->registerPHPFunctions('testPhpFunction'); +$xslt->importStyleSheet($xsl); + +echo $xslt->transformToXML($dom); +?> +--EXPECT-- + +test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2 diff --git a/ext/xsl/xsltprocessor.c b/ext/xsl/xsltprocessor.c index accee6c9aceee..182aab68d6607 100644 --- a/ext/xsl/xsltprocessor.c +++ b/ext/xsl/xsltprocessor.c @@ -274,7 +274,7 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t node->parent = nsparent; node->ns = curns; } else { - node = xmlDocCopyNodeList(domintern->document->ptr, node); + node = xmlDocCopyNode(node, domintern->document->ptr, 1); } php_dom_create_object(node, &child, domintern);