diff --git a/ext/dom/node.c b/ext/dom/node.c
index ee14fd158fc..172172c47f0 100644
--- a/ext/dom/node.c
+++ b/ext/dom/node.c
@@ -906,6 +906,7 @@ static void dom_node_insert_before_legacy(zval *return_value, zval *ref, dom_obj
}
if (child->doc == NULL && parentp->doc != NULL) {
+ xmlSetTreeDoc(child, parentp->doc);
dom_set_document_ref_pointers(child, intern->document);
}
@@ -1212,6 +1213,7 @@ static void dom_node_replace_child(INTERNAL_FUNCTION_PARAMETERS, bool modern)
}
if (newchild->doc == NULL && nodep->doc != NULL) {
+ xmlSetTreeDoc(newchild, nodep->doc);
dom_set_document_ref_pointers(newchild, intern->document);
}
@@ -1320,6 +1322,7 @@ static void dom_node_append_child_legacy(zval *return_value, dom_object *intern,
}
if (child->doc == NULL && nodep->doc != NULL) {
+ xmlSetTreeDoc(child, nodep->doc);
dom_set_document_ref_pointers(child, intern->document);
}
diff --git a/ext/dom/tests/gh16777_1.phpt b/ext/dom/tests/gh16777_1.phpt
new file mode 100644
index 00000000000..d821842ace4
--- /dev/null
+++ b/ext/dom/tests/gh16777_1.phpt
@@ -0,0 +1,24 @@
+--TEST--
+GH-16777 (Calling the constructor again on a DOM object after it is in a document causes UAF)
+--EXTENSIONS--
+dom
+--FILE--
+appendChild($text);
+$text->__construct('my new value');
+$doc->appendChild($text);
+echo $doc->saveXML();
+$dom2 = new DOMDocument();
+try {
+ $dom2->appendChild($text);
+} catch (DOMException $e) {
+ echo $e->getMessage(), "\n";
+}
+?>
+--EXPECT--
+
+my value
+my new value
+Wrong Document Error
diff --git a/ext/dom/tests/gh16777_2.phpt b/ext/dom/tests/gh16777_2.phpt
new file mode 100644
index 00000000000..a6f3a59621b
--- /dev/null
+++ b/ext/dom/tests/gh16777_2.phpt
@@ -0,0 +1,27 @@
+--TEST--
+GH-16777 (Calling the constructor again on a DOM object after it is in a document causes UAF)
+--EXTENSIONS--
+dom
+--FILE--
+append($child = new DOMElement('child'));
+$doc = new DOMDocument();
+$doc->appendChild($el);
+$el->__construct('newname');
+$doc->appendChild($el);
+echo $doc->saveXML();
+$dom2 = new DOMDocument();
+try {
+ $dom2->appendChild($el);
+} catch (DOMException $e) {
+ echo $e->getMessage(), "\n";
+}
+var_dump($child->ownerDocument === $doc);
+?>
+--EXPECT--
+
+
+
+Wrong Document Error
+bool(true)
diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c
index 49f3b2b4e67..2e47968e676 100644
--- a/ext/simplexml/simplexml.c
+++ b/ext/simplexml/simplexml.c
@@ -2479,7 +2479,11 @@ static zval *php_sxe_iterator_current_data(zend_object_iterator *iter) /* {{{ */
{
php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
- return &iterator->sxe->iter.data;
+ zval *data = &iterator->sxe->iter.data;
+ if (Z_ISUNDEF_P(data)) {
+ return NULL;
+ }
+ return data;
}
/* }}} */
diff --git a/ext/simplexml/tests/gh16808.phpt b/ext/simplexml/tests/gh16808.phpt
new file mode 100644
index 00000000000..be0bc59fb65
--- /dev/null
+++ b/ext/simplexml/tests/gh16808.phpt
@@ -0,0 +1,12 @@
+--TEST--
+GH-16808 (Segmentation fault in RecursiveIteratorIterator->current() with a xml element input)
+--EXTENSIONS--
+simplexml
+--FILE--
+");
+$test = new RecursiveIteratorIterator($sxe);
+var_dump($test->current());
+?>
+--EXPECT--
+NULL