summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Toohey <ttoohey@php.net>2017-06-03 00:38:02 +0200
committerNikita Popov <nikita.ppv@gmail.com>2017-06-03 00:40:58 +0200
commitd027bc2addb4f12e0030532933a2c85c07cdb293 (patch)
treeab11b67b886480a5f6b7c76b73177aee5569091a
parent95c4564f939c916538579ef63602a3cd31941c51 (diff)
downloadphp-git-d027bc2addb4f12e0030532933a2c85c07cdb293.tar.gz
Fixed bug #69373
xmlNodeSetContentLen() calls xmlFreeNode() on node->children. This causes problems if there are other references around to those children.
-rw-r--r--NEWS3
-rw-r--r--ext/dom/node.c10
-rw-r--r--ext/dom/tests/bug69373.phpt15
-rw-r--r--ext/libxml/libxml.c2
-rw-r--r--ext/libxml/php_libxml.h1
5 files changed, 30 insertions, 1 deletions
diff --git a/NEWS b/NEWS
index eecf1e50a6..2cb059a5f1 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,9 @@ PHP NEWS
properties). (Laruence)
. Fixed misparsing of abstract unix domain socket names. (Sara)
+- DOM:
+ . Fixed bug #69373 (References to deleted XPath query results). (ttoohey)
+
- Intl:
. Fixed bug #73473 (Stack Buffer Overflow in msgfmt_parse_message). (libnex)
diff --git a/ext/dom/node.c b/ext/dom/node.c
index b4ab9f896a..b4a081ebe9 100644
--- a/ext/dom/node.c
+++ b/ext/dom/node.c
@@ -337,6 +337,8 @@ int dom_node_node_value_write(dom_object *obj, zval *newval)
case XML_ATTRIBUTE_NODE:
if (nodep->children) {
node_list_unlink(nodep->children);
+ php_libxml_node_free_list((xmlNodePtr) nodep->children);
+ nodep->children = NULL;
}
case XML_TEXT_NODE:
case XML_COMMENT_NODE:
@@ -854,6 +856,14 @@ int dom_node_text_content_write(dom_object *obj, zval *newval)
return FAILURE;
}
+ if (nodep->type == XML_ELEMENT_NODE || nodep->type == XML_ATTRIBUTE_NODE) {
+ if (nodep->children) {
+ node_list_unlink(nodep->children);
+ php_libxml_node_free_list((xmlNodePtr) nodep->children);
+ nodep->children = NULL;
+ }
+ }
+
str = zval_get_string(newval);
/* we have to use xmlNodeAddContent() to get the same behavior as with xmlNewText() */
xmlNodeSetContent(nodep, (xmlChar *) "");
diff --git a/ext/dom/tests/bug69373.phpt b/ext/dom/tests/bug69373.phpt
new file mode 100644
index 0000000000..d04ac03983
--- /dev/null
+++ b/ext/dom/tests/bug69373.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Bug #69373 References to deleted XPath query results
+--FILE--
+<?php
+$doc = new DOMDocument();
+for( $i=0; $i<20; $i++ ) {
+ $doc->loadXML("<parent><child /><child /></parent>");
+ $xpath = new DOMXpath($doc);
+ $all = $xpath->query('//*');
+ $doc->firstChild->nodeValue = '';
+}
+echo 'DONE', PHP_EOL;
+?>
+--EXPECT--
+DONE
diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c
index 12f1c2c3d0..a029b9f477 100644
--- a/ext/libxml/libxml.c
+++ b/ext/libxml/libxml.c
@@ -224,7 +224,7 @@ static void php_libxml_node_free(xmlNodePtr node)
}
}
-static void php_libxml_node_free_list(xmlNodePtr node)
+PHP_LIBXML_API void php_libxml_node_free_list(xmlNodePtr node)
{
xmlNodePtr curnode;
diff --git a/ext/libxml/php_libxml.h b/ext/libxml/php_libxml.h
index 88ab22928b..5021a3d43f 100644
--- a/ext/libxml/php_libxml.h
+++ b/ext/libxml/php_libxml.h
@@ -100,6 +100,7 @@ PHP_LIBXML_API int php_libxml_decrement_doc_ref(php_libxml_node_object *object);
PHP_LIBXML_API xmlNodePtr php_libxml_import_node(zval *object);
PHP_LIBXML_API zval *php_libxml_register_export(zend_class_entry *ce, php_libxml_export_node export_function);
/* When an explicit freeing of node and children is required */
+PHP_LIBXML_API void php_libxml_node_free_list(xmlNodePtr node);
PHP_LIBXML_API void php_libxml_node_free_resource(xmlNodePtr node);
/* When object dtor is called as node may still be referenced */
PHP_LIBXML_API void php_libxml_node_decrement_resource(php_libxml_node_object *object);