mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Merge branch 'PHP-8.3'
* PHP-8.3: Fix crashes with entity references and predefined entities Fix crash in adoptNode with attribute references
This commit is contained in:
commit
f420ea84aa
5 changed files with 127 additions and 19 deletions
|
@ -1030,21 +1030,33 @@ PHP_METHOD(DOM_Document, getElementById)
|
||||||
}
|
}
|
||||||
/* }}} end dom_document_get_element_by_id */
|
/* }}} end dom_document_get_element_by_id */
|
||||||
|
|
||||||
static void php_dom_transfer_document_ref(xmlNodePtr node, dom_object *dom_object_document, xmlDocPtr document)
|
static zend_always_inline void php_dom_transfer_document_ref_single_node(xmlNodePtr node, php_libxml_ref_obj *new_document)
|
||||||
{
|
{
|
||||||
if (node->children) {
|
|
||||||
php_dom_transfer_document_ref(node->children, dom_object_document, document);
|
|
||||||
}
|
|
||||||
while (node) {
|
|
||||||
php_libxml_node_ptr *iteration_object_ptr = node->_private;
|
php_libxml_node_ptr *iteration_object_ptr = node->_private;
|
||||||
if (iteration_object_ptr) {
|
if (iteration_object_ptr) {
|
||||||
php_libxml_node_object *iteration_object = iteration_object_ptr->_private;
|
php_libxml_node_object *iteration_object = iteration_object_ptr->_private;
|
||||||
ZEND_ASSERT(iteration_object != NULL);
|
ZEND_ASSERT(iteration_object != NULL);
|
||||||
/* Must increase refcount first because we could be the last reference holder, and the document may be equal. */
|
/* Must increase refcount first because we could be the last reference holder, and the document may be equal. */
|
||||||
dom_object_document->document->refcount++;
|
new_document->refcount++;
|
||||||
php_libxml_decrement_doc_ref(iteration_object);
|
php_libxml_decrement_doc_ref(iteration_object);
|
||||||
iteration_object->document = dom_object_document->document;
|
iteration_object->document = new_document;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void php_dom_transfer_document_ref(xmlNodePtr node, php_libxml_ref_obj *new_document)
|
||||||
|
{
|
||||||
|
if (node->children) {
|
||||||
|
php_dom_transfer_document_ref(node->children, new_document);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (node) {
|
||||||
|
if (node->type == XML_ELEMENT_NODE) {
|
||||||
|
for (xmlAttrPtr attr = node->properties; attr != NULL; attr = attr->next) {
|
||||||
|
php_dom_transfer_document_ref_single_node((xmlNodePtr) attr, new_document);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
php_dom_transfer_document_ref_single_node(node, new_document);
|
||||||
node = node->next;
|
node = node->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1062,7 +1074,7 @@ bool php_dom_adopt_node(xmlNodePtr nodep, dom_object *dom_object_new_document, x
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
php_dom_transfer_document_ref(nodep, dom_object_new_document, new_document);
|
php_dom_transfer_document_ref(nodep, dom_object_new_document->document);
|
||||||
} else {
|
} else {
|
||||||
xmlUnlinkNode(nodep);
|
xmlUnlinkNode(nodep);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
--TEST--
|
||||||
|
DOMDocument::adoptNode() with attribute references
|
||||||
|
--EXTENSIONS--
|
||||||
|
dom
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$dom = new DOMDocument;
|
||||||
|
$root = $dom->appendChild($dom->createElement('root'));
|
||||||
|
$root->setAttributeNS("urn:a", "a:root1", "bar");
|
||||||
|
$root1 = $root->getAttributeNodeNS("urn:a", "root1");
|
||||||
|
echo $dom->saveXML();
|
||||||
|
|
||||||
|
$dom = new DOMDocument;
|
||||||
|
$dom->appendChild($dom->adoptNode($root));
|
||||||
|
foreach ($dom->documentElement->attributes as $attr) {
|
||||||
|
var_dump($attr->namespaceURI, $attr->prefix, $attr->localName, $attr->nodeValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<root xmlns:a="urn:a" a:root1="bar"/>
|
||||||
|
string(5) "urn:a"
|
||||||
|
string(1) "a"
|
||||||
|
string(5) "root1"
|
||||||
|
string(3) "bar"
|
46
ext/dom/tests/DOMEntityReference_predefined_free.phpt
Normal file
46
ext/dom/tests/DOMEntityReference_predefined_free.phpt
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
--TEST--
|
||||||
|
Freeing of a predefined DOMEntityReference
|
||||||
|
--EXTENSIONS--
|
||||||
|
dom
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
$ref = new DOMEntityReference("amp");
|
||||||
|
var_dump($ref);
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
object(DOMEntityReference)#1 (17) {
|
||||||
|
["nodeName"]=>
|
||||||
|
string(3) "amp"
|
||||||
|
["nodeValue"]=>
|
||||||
|
NULL
|
||||||
|
["nodeType"]=>
|
||||||
|
int(5)
|
||||||
|
["parentNode"]=>
|
||||||
|
NULL
|
||||||
|
["parentElement"]=>
|
||||||
|
NULL
|
||||||
|
["childNodes"]=>
|
||||||
|
string(22) "(object value omitted)"
|
||||||
|
["firstChild"]=>
|
||||||
|
string(22) "(object value omitted)"
|
||||||
|
["lastChild"]=>
|
||||||
|
string(22) "(object value omitted)"
|
||||||
|
["previousSibling"]=>
|
||||||
|
NULL
|
||||||
|
["nextSibling"]=>
|
||||||
|
NULL
|
||||||
|
["attributes"]=>
|
||||||
|
NULL
|
||||||
|
["isConnected"]=>
|
||||||
|
bool(false)
|
||||||
|
["namespaceURI"]=>
|
||||||
|
NULL
|
||||||
|
["prefix"]=>
|
||||||
|
string(0) ""
|
||||||
|
["localName"]=>
|
||||||
|
NULL
|
||||||
|
["baseURI"]=>
|
||||||
|
NULL
|
||||||
|
["textContent"]=>
|
||||||
|
string(0) ""
|
||||||
|
}
|
|
@ -9,16 +9,32 @@ $doc->loadXML(<<<'XML'
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<!DOCTYPE books [
|
<!DOCTYPE books [
|
||||||
<!ENTITY test "entity is only for test purposes">
|
<!ENTITY test "entity is only for test purposes">
|
||||||
|
<!ENTITY myimage PUBLIC "-" "mypicture.gif" NDATA GIF>
|
||||||
]>
|
]>
|
||||||
<container/>
|
<container/>
|
||||||
XML);
|
XML);
|
||||||
$entity = $doc->doctype->entities[0];
|
$ref1 = $doc->createEntityReference("test");
|
||||||
var_dump($entity->nodeName, $entity->parentNode->nodeName);
|
$ref2 = $doc->createEntityReference("myimage");
|
||||||
|
$entity1 = $doc->doctype->entities[0];
|
||||||
|
$entity2 = $doc->doctype->entities[1];
|
||||||
|
|
||||||
|
// Entity order depends on addresses
|
||||||
|
if ($entity1->nodeName !== "test") {
|
||||||
|
[$entity1, $entity2] = [$entity2, $entity1];
|
||||||
|
}
|
||||||
|
|
||||||
|
var_dump($entity1->nodeName, $entity1->parentNode->nodeName);
|
||||||
|
var_dump($entity2->nodeName, $entity2->parentNode->nodeName);
|
||||||
$doc->removeChild($doc->doctype);
|
$doc->removeChild($doc->doctype);
|
||||||
var_dump($entity->nodeName, $entity->parentNode);
|
var_dump($entity1->nodeName, $entity1->parentNode);
|
||||||
|
var_dump($entity2->nodeName, $entity2->parentNode);
|
||||||
?>
|
?>
|
||||||
--EXPECT--
|
--EXPECT--
|
||||||
string(4) "test"
|
string(4) "test"
|
||||||
string(5) "books"
|
string(5) "books"
|
||||||
|
string(7) "myimage"
|
||||||
|
string(5) "books"
|
||||||
string(4) "test"
|
string(4) "test"
|
||||||
NULL
|
NULL
|
||||||
|
string(7) "myimage"
|
||||||
|
NULL
|
||||||
|
|
|
@ -207,12 +207,10 @@ static void php_libxml_node_free(xmlNodePtr node)
|
||||||
* dtd is attached to the document. This works around the issue by inspecting the parent directly. */
|
* dtd is attached to the document. This works around the issue by inspecting the parent directly. */
|
||||||
case XML_ENTITY_DECL: {
|
case XML_ENTITY_DECL: {
|
||||||
xmlEntityPtr entity = (xmlEntityPtr) node;
|
xmlEntityPtr entity = (xmlEntityPtr) node;
|
||||||
|
if (entity->etype != XML_INTERNAL_PREDEFINED_ENTITY) {
|
||||||
php_libxml_unlink_entity_decl(entity);
|
php_libxml_unlink_entity_decl(entity);
|
||||||
if (entity->orig != NULL) {
|
xmlFreeEntity(entity);
|
||||||
xmlFree((char *) entity->orig);
|
|
||||||
entity->orig = NULL;
|
|
||||||
}
|
}
|
||||||
xmlFreeNode(node);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case XML_NOTATION_NODE: {
|
case XML_NOTATION_NODE: {
|
||||||
|
@ -1383,6 +1381,15 @@ PHP_LIBXML_API void php_libxml_node_free_resource(xmlNodePtr node)
|
||||||
case XML_DOCUMENT_NODE:
|
case XML_DOCUMENT_NODE:
|
||||||
case XML_HTML_DOCUMENT_NODE:
|
case XML_HTML_DOCUMENT_NODE:
|
||||||
break;
|
break;
|
||||||
|
case XML_ENTITY_REF_NODE:
|
||||||
|
/* Entity reference nodes are special: their children point to entity declarations,
|
||||||
|
* but they don't own the declarations and therefore shouldn't free the children.
|
||||||
|
* Moreover, there can be N>1 reference nodes for a single entity declarations. */
|
||||||
|
php_libxml_unregister_node(node);
|
||||||
|
if (node->parent == NULL) {
|
||||||
|
php_libxml_node_free(node);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (node->parent == NULL || node->type == XML_NAMESPACE_DECL) {
|
if (node->parent == NULL || node->type == XML_NAMESPACE_DECL) {
|
||||||
php_libxml_node_free_list((xmlNodePtr) node->children);
|
php_libxml_node_free_list((xmlNodePtr) node->children);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue