mirror of
https://github.com/php/php-src.git
synced 2025-08-15 13:38:49 +02:00
Fix crashes with entity references and predefined entities
Closes GH-13004.
This commit is contained in:
parent
42cbace1ad
commit
120bd364aa
4 changed files with 104 additions and 8 deletions
3
NEWS
3
NEWS
|
@ -15,6 +15,9 @@ PHP NEWS
|
|||
. Fixed bug GH-12996 (Incorrect SCRIPT_NAME with Apache ProxyPassMatch when
|
||||
plus in path). (Jakub Zelenka)
|
||||
|
||||
- LibXML:
|
||||
. Fix crashes with entity references and predefined entities. (nielsdos)
|
||||
|
||||
- Opcache:
|
||||
. Fixed bug GH-13145 (strtok() is not comptime). (ilutov)
|
||||
. Fixed type inference of range(). (ilutov)
|
||||
|
|
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,30 @@ $doc->loadXML(<<<'XML'
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE books [
|
||||
<!ENTITY test "entity is only for test purposes">
|
||||
<!ENTITY myimage PUBLIC "-" "mypicture.gif" NDATA GIF>
|
||||
]>
|
||||
<container/>
|
||||
XML);
|
||||
$entity = $doc->doctype->entities[0];
|
||||
var_dump($entity->nodeName, $entity->parentNode->nodeName);
|
||||
$ref1 = $doc->createEntityReference("test");
|
||||
$ref2 = $doc->createEntityReference("myimage");
|
||||
$entity1 = $doc->doctype->entities[0];
|
||||
$entity2 = $doc->doctype->entities[1];
|
||||
if (strcmp($entity1->nodeName, $entity2->nodeName) < 0) {
|
||||
// Entity ordering depends on the addresses
|
||||
[$entity1, $entity2] = [$entity2, $entity1];
|
||||
}
|
||||
var_dump($entity1->nodeName, $entity1->parentNode->nodeName);
|
||||
var_dump($entity2->nodeName, $entity2->parentNode->nodeName);
|
||||
$doc->removeChild($doc->doctype);
|
||||
var_dump($entity->nodeName, $entity->parentNode);
|
||||
var_dump($entity1->nodeName, $entity1->parentNode);
|
||||
var_dump($entity2->nodeName, $entity2->parentNode);
|
||||
?>
|
||||
--EXPECT--
|
||||
string(4) "test"
|
||||
string(5) "books"
|
||||
string(7) "myimage"
|
||||
string(5) "books"
|
||||
string(4) "test"
|
||||
NULL
|
||||
string(7) "myimage"
|
||||
NULL
|
||||
|
|
|
@ -207,12 +207,36 @@ static void php_libxml_node_free(xmlNodePtr node)
|
|||
* dtd is attached to the document. This works around the issue by inspecting the parent directly. */
|
||||
case XML_ENTITY_DECL: {
|
||||
xmlEntityPtr entity = (xmlEntityPtr) node;
|
||||
if (entity->etype != XML_INTERNAL_PREDEFINED_ENTITY) {
|
||||
php_libxml_unlink_entity_decl(entity);
|
||||
if (entity->orig != NULL) {
|
||||
xmlFree((char *) entity->orig);
|
||||
entity->orig = NULL;
|
||||
#if LIBXML_VERSION >= 21200
|
||||
xmlFreeEntity(entity);
|
||||
#else
|
||||
if (entity->children != NULL && entity->owner && entity == (xmlEntityPtr) entity->children->parent) {
|
||||
xmlFreeNodeList(entity->children);
|
||||
}
|
||||
xmlDictPtr dict = entity->doc != NULL ? entity->doc->dict : NULL;
|
||||
if (dict == NULL || !xmlDictOwns(dict, entity->name)) {
|
||||
xmlFree((xmlChar *) entity->name);
|
||||
}
|
||||
if (dict == NULL || !xmlDictOwns(dict, entity->ExternalID)) {
|
||||
xmlFree((xmlChar *) entity->ExternalID);
|
||||
}
|
||||
if (dict == NULL || !xmlDictOwns(dict, entity->SystemID)) {
|
||||
xmlFree((xmlChar *) entity->SystemID);
|
||||
}
|
||||
if (dict == NULL || !xmlDictOwns(dict, entity->URI)) {
|
||||
xmlFree((xmlChar *) entity->URI);
|
||||
}
|
||||
if (dict == NULL || !xmlDictOwns(dict, entity->content)) {
|
||||
xmlFree(entity->content);
|
||||
}
|
||||
if (dict == NULL || !xmlDictOwns(dict, entity->orig)) {
|
||||
xmlFree(entity->orig);
|
||||
}
|
||||
xmlFree(entity);
|
||||
#endif
|
||||
}
|
||||
xmlFreeNode(node);
|
||||
break;
|
||||
}
|
||||
case XML_NOTATION_NODE: {
|
||||
|
@ -1386,6 +1410,15 @@ PHP_LIBXML_API void php_libxml_node_free_resource(xmlNodePtr node)
|
|||
case XML_DOCUMENT_NODE:
|
||||
case XML_HTML_DOCUMENT_NODE:
|
||||
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 more than one reference node for a single entity declarations. */
|
||||
php_libxml_unregister_node(node);
|
||||
if (node->parent == NULL) {
|
||||
php_libxml_node_free(node);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (node->parent == NULL || node->type == XML_NAMESPACE_DECL) {
|
||||
php_libxml_node_free_list((xmlNodePtr) node->children);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue