Fix bug #66502: DOM document dangling reference
authorChristoph M. Becker <cmb@php.net>
Thu, 14 Jul 2016 22:57:36 +0000 (00:57 +0200)
committerChristoph M. Becker <cmb@php.net>
Thu, 14 Jul 2016 23:08:08 +0000 (01:08 +0200)
When we decrement the refcount of a node's document, we state that we
won't need it anymore. Therefore we can *always* set the pointer to the
document to NULL, what avoids invalid memory accesses for some edge cases
as demonstrated with the PHPT.

Original patch provided by Sean Heelan.

NEWS
ext/dom/tests/bug66502.phpt [new file with mode: 0644]
ext/libxml/libxml.c

diff --git a/NEWS b/NEWS
index a9ca67ad8c4d64720b2d77a458bfc4e4b7f6f5c9..455e44b8424bbc761a5d7b5476fb093ee0f31b7e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -16,6 +16,9 @@ PHP                                                                        NEWS
   . Fixed bug #66836 (DateTime::createFromFormat 'U' with pre 1970 dates fails
     parsing). (derick)
 
+- DOM:
+  . Fixed bug #66502 (DOM document dangling reference). (Sean Heelan, cmb)
+
 - Filter:
   . Fixed bug #71745 (FILTER_FLAG_NO_RES_RANGE does not cover whole 127.0.0.0/8
     range). (bugs dot php dot net at majkl578 dot cz)
diff --git a/ext/dom/tests/bug66502.phpt b/ext/dom/tests/bug66502.phpt
new file mode 100644 (file)
index 0000000..5b35b41
--- /dev/null
@@ -0,0 +1,20 @@
+--TEST--
+Bug #66502 (DOM document dangling reference)
+--SKIPIF--
+<?php
+if (!extension_loaded('dom')) die('skip requires ext/dom');
+?>
+--FILE--
+<?php
+$dom = new DOMDocument('1.0', 'UTF-8');
+$element = $dom->appendChild(new DOMElement('root'));
+$comment = new DOMComment("Comment 0");
+$comment = $element->appendChild($comment);
+
+$comment->__construct("Comment 1");
+$comment->__construct("Comment 2");
+$comment->__construct("Comment 3");
+echo 'DONE', PHP_EOL;
+?>
+--EXPECT--
+DONE
\ No newline at end of file
index bd0016b79ffb08a1ed9f8d2587d2eb67ae24830a..b252cb6d8170aa950faab97401099066215419b7 100644 (file)
@@ -1272,8 +1272,8 @@ PHP_LIBXML_API int php_libxml_decrement_doc_ref(php_libxml_node_object *object T
                                efree(object->document->doc_props);
                        }
                        efree(object->document);
-                       object->document = NULL;
                }
+               object->document = NULL;
        }
 
        return ret_refcount;