mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Merge branch 'PHP-8.2' into PHP-8.3
* PHP-8.2: Fix crash when calling childNodes next() when iterator is exhausted Fix references not handled correctly in C14N Fix crashes when entity declaration is removed while still having entity references
This commit is contained in:
commit
461d890f0a
12 changed files with 248 additions and 7 deletions
6
NEWS
6
NEWS
|
@ -2,6 +2,12 @@ PHP NEWS
|
||||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||
?? ??? ????, PHP 8.3.8
|
?? ??? ????, PHP 8.3.8
|
||||||
|
|
||||||
|
- DOM:
|
||||||
|
. Fix crashes when entity declaration is removed while still having entity
|
||||||
|
references. (nielsdos)
|
||||||
|
. Fix references not handled correctly in C14N. (nielsdos)
|
||||||
|
. Fix crash when calling childNodes next() when iterator is exhausted.
|
||||||
|
(nielsdos)
|
||||||
|
|
||||||
09 May 2024, PHP 8.3.7
|
09 May 2024, PHP 8.3.7
|
||||||
|
|
||||||
|
|
|
@ -148,8 +148,7 @@ static int php_dom_iterator_valid(zend_object_iterator *iter) /* {{{ */
|
||||||
zval *php_dom_iterator_current_data(zend_object_iterator *iter) /* {{{ */
|
zval *php_dom_iterator_current_data(zend_object_iterator *iter) /* {{{ */
|
||||||
{
|
{
|
||||||
php_dom_iterator *iterator = (php_dom_iterator *)iter;
|
php_dom_iterator *iterator = (php_dom_iterator *)iter;
|
||||||
|
return Z_ISUNDEF(iterator->curobj) ? NULL : &iterator->curobj;
|
||||||
return &iterator->curobj;
|
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,11 @@ int dom_entity_actual_encoding_read(dom_object *obj, zval *retval);
|
||||||
int dom_entity_encoding_read(dom_object *obj, zval *retval);
|
int dom_entity_encoding_read(dom_object *obj, zval *retval);
|
||||||
int dom_entity_version_read(dom_object *obj, zval *retval);
|
int dom_entity_version_read(dom_object *obj, zval *retval);
|
||||||
|
|
||||||
|
/* entity reference properties */
|
||||||
|
int dom_entity_reference_child_read(dom_object *obj, zval *retval);
|
||||||
|
int dom_entity_reference_text_content_read(dom_object *obj, zval *retval);
|
||||||
|
int dom_entity_reference_child_nodes_read(dom_object *obj, zval *retval);
|
||||||
|
|
||||||
/* namednodemap properties */
|
/* namednodemap properties */
|
||||||
int dom_namednodemap_length_read(dom_object *obj, zval *retval);
|
int dom_namednodemap_length_read(dom_object *obj, zval *retval);
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "php.h"
|
#include "php.h"
|
||||||
#if defined(HAVE_LIBXML) && defined(HAVE_DOM)
|
#if defined(HAVE_LIBXML) && defined(HAVE_DOM)
|
||||||
#include "php_dom.h"
|
#include "php_dom.h"
|
||||||
|
#include "dom_properties.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* class DOMEntityReference extends DOMNode
|
* class DOMEntityReference extends DOMNode
|
||||||
|
@ -65,4 +66,63 @@ PHP_METHOD(DOMEntityReference, __construct)
|
||||||
}
|
}
|
||||||
/* }}} end DOMEntityReference::__construct */
|
/* }}} end DOMEntityReference::__construct */
|
||||||
|
|
||||||
|
/* The following property handlers are necessary because of special lifetime management with entities and entity
|
||||||
|
* references. The issue is that entity references hold a reference to an entity declaration, but don't
|
||||||
|
* register that reference anywhere. When the entity declaration disappears we have no way of notifying the
|
||||||
|
* entity references. Override the property handlers for the declaration-accessing properties to fix this problem. */
|
||||||
|
|
||||||
|
xmlEntityPtr dom_entity_reference_fetch_and_sync_declaration(xmlNodePtr reference)
|
||||||
|
{
|
||||||
|
xmlEntityPtr entity = xmlGetDocEntity(reference->doc, reference->name);
|
||||||
|
reference->children = (xmlNodePtr) entity;
|
||||||
|
reference->last = (xmlNodePtr) entity;
|
||||||
|
reference->content = entity ? entity->content : NULL;
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dom_entity_reference_child_read(dom_object *obj, zval *retval)
|
||||||
|
{
|
||||||
|
xmlNodePtr nodep = dom_object_get_node(obj);
|
||||||
|
|
||||||
|
if (nodep == NULL) {
|
||||||
|
php_dom_throw_error(INVALID_STATE_ERR, true);
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlEntityPtr entity = dom_entity_reference_fetch_and_sync_declaration(nodep);
|
||||||
|
if (entity == NULL) {
|
||||||
|
ZVAL_NULL(retval);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
php_dom_create_object((xmlNodePtr) entity, retval, obj);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dom_entity_reference_text_content_read(dom_object *obj, zval *retval)
|
||||||
|
{
|
||||||
|
xmlNodePtr nodep = dom_object_get_node(obj);
|
||||||
|
|
||||||
|
if (nodep == NULL) {
|
||||||
|
php_dom_throw_error(INVALID_STATE_ERR, true);
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
dom_entity_reference_fetch_and_sync_declaration(nodep);
|
||||||
|
return dom_node_text_content_read(obj, retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dom_entity_reference_child_nodes_read(dom_object *obj, zval *retval)
|
||||||
|
{
|
||||||
|
xmlNodePtr nodep = dom_object_get_node(obj);
|
||||||
|
|
||||||
|
if (nodep == NULL) {
|
||||||
|
php_dom_throw_error(INVALID_STATE_ERR, true);
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
dom_entity_reference_fetch_and_sync_declaration(nodep);
|
||||||
|
return dom_node_child_nodes_read(obj, retval);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1821,7 +1821,7 @@ static void dom_canonicalization(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{
|
||||||
char *xquery;
|
char *xquery;
|
||||||
|
|
||||||
/* Find "query" key */
|
/* Find "query" key */
|
||||||
tmp = zend_hash_find(ht, ZSTR_KNOWN(ZEND_STR_QUERY));
|
tmp = zend_hash_find_deref(ht, ZSTR_KNOWN(ZEND_STR_QUERY));
|
||||||
if (!tmp) {
|
if (!tmp) {
|
||||||
/* if mode == 0 then $xpath arg is 3, if mode == 1 then $xpath is 4 */
|
/* if mode == 0 then $xpath arg is 3, if mode == 1 then $xpath is 4 */
|
||||||
zend_argument_value_error(3 + mode, "must have a \"query\" key");
|
zend_argument_value_error(3 + mode, "must have a \"query\" key");
|
||||||
|
@ -1837,12 +1837,13 @@ static void dom_canonicalization(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{
|
||||||
ctxp = xmlXPathNewContext(docp);
|
ctxp = xmlXPathNewContext(docp);
|
||||||
ctxp->node = nodep;
|
ctxp->node = nodep;
|
||||||
|
|
||||||
tmp = zend_hash_str_find(ht, "namespaces", sizeof("namespaces")-1);
|
tmp = zend_hash_str_find_deref(ht, "namespaces", sizeof("namespaces")-1);
|
||||||
if (tmp && Z_TYPE_P(tmp) == IS_ARRAY && !HT_IS_PACKED(Z_ARRVAL_P(tmp))) {
|
if (tmp && Z_TYPE_P(tmp) == IS_ARRAY && !HT_IS_PACKED(Z_ARRVAL_P(tmp))) {
|
||||||
zval *tmpns;
|
zval *tmpns;
|
||||||
zend_string *prefix;
|
zend_string *prefix;
|
||||||
|
|
||||||
ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(tmp), prefix, tmpns) {
|
ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(tmp), prefix, tmpns) {
|
||||||
|
ZVAL_DEREF(tmpns);
|
||||||
if (Z_TYPE_P(tmpns) == IS_STRING) {
|
if (Z_TYPE_P(tmpns) == IS_STRING) {
|
||||||
if (prefix) {
|
if (prefix) {
|
||||||
xmlXPathRegisterNs(ctxp, (xmlChar *) ZSTR_VAL(prefix), (xmlChar *) Z_STRVAL_P(tmpns));
|
xmlXPathRegisterNs(ctxp, (xmlChar *) ZSTR_VAL(prefix), (xmlChar *) Z_STRVAL_P(tmpns));
|
||||||
|
|
|
@ -49,6 +49,16 @@ static zend_always_inline void reset_objmap_cache(dom_nnodemap_object *objmap)
|
||||||
objmap->cached_length = -1;
|
objmap->cached_length = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static xmlNodePtr dom_nodelist_iter_start_first_child(xmlNodePtr nodep)
|
||||||
|
{
|
||||||
|
if (nodep->type == XML_ENTITY_REF_NODE) {
|
||||||
|
/* See entityreference.c */
|
||||||
|
dom_entity_reference_fetch_and_sync_declaration(nodep);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodep->children;
|
||||||
|
}
|
||||||
|
|
||||||
int php_dom_get_nodelist_length(dom_object *obj)
|
int php_dom_get_nodelist_length(dom_object *obj)
|
||||||
{
|
{
|
||||||
dom_nnodemap_object *objmap = (dom_nnodemap_object *) obj->ptr;
|
dom_nnodemap_object *objmap = (dom_nnodemap_object *) obj->ptr;
|
||||||
|
@ -83,7 +93,7 @@ int php_dom_get_nodelist_length(dom_object *obj)
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
if (objmap->nodetype == XML_ATTRIBUTE_NODE || objmap->nodetype == XML_ELEMENT_NODE) {
|
if (objmap->nodetype == XML_ATTRIBUTE_NODE || objmap->nodetype == XML_ELEMENT_NODE) {
|
||||||
xmlNodePtr curnode = nodep->children;
|
xmlNodePtr curnode = dom_nodelist_iter_start_first_child(nodep);
|
||||||
if (curnode) {
|
if (curnode) {
|
||||||
count++;
|
count++;
|
||||||
while (curnode->next != NULL) {
|
while (curnode->next != NULL) {
|
||||||
|
@ -185,7 +195,7 @@ void php_dom_nodelist_get_item_into_zval(dom_nnodemap_object *objmap, zend_long
|
||||||
int count = 0;
|
int count = 0;
|
||||||
if (objmap->nodetype == XML_ATTRIBUTE_NODE || objmap->nodetype == XML_ELEMENT_NODE) {
|
if (objmap->nodetype == XML_ATTRIBUTE_NODE || objmap->nodetype == XML_ELEMENT_NODE) {
|
||||||
if (restart) {
|
if (restart) {
|
||||||
nodep = nodep->children;
|
nodep = dom_nodelist_iter_start_first_child(nodep);
|
||||||
}
|
}
|
||||||
while (count < relative_index && nodep != NULL) {
|
while (count < relative_index && nodep != NULL) {
|
||||||
count++;
|
count++;
|
||||||
|
|
|
@ -72,6 +72,7 @@ static HashTable classes;
|
||||||
static HashTable dom_document_prop_handlers;
|
static HashTable dom_document_prop_handlers;
|
||||||
static HashTable dom_documentfragment_prop_handlers;
|
static HashTable dom_documentfragment_prop_handlers;
|
||||||
static HashTable dom_node_prop_handlers;
|
static HashTable dom_node_prop_handlers;
|
||||||
|
static HashTable dom_entity_reference_prop_handlers;
|
||||||
static HashTable dom_nodelist_prop_handlers;
|
static HashTable dom_nodelist_prop_handlers;
|
||||||
static HashTable dom_namednodemap_prop_handlers;
|
static HashTable dom_namednodemap_prop_handlers;
|
||||||
static HashTable dom_characterdata_prop_handlers;
|
static HashTable dom_characterdata_prop_handlers;
|
||||||
|
@ -286,6 +287,14 @@ static void dom_register_prop_handler(HashTable *prop_handler, char *name, size_
|
||||||
zend_string_release_ex(str, 1);
|
zend_string_release_ex(str, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dom_override_prop_handler(HashTable *prop_handler, char *name, size_t name_len, dom_read_t read_func, dom_write_t write_func)
|
||||||
|
{
|
||||||
|
dom_prop_handler hnd;
|
||||||
|
hnd.read_func = read_func;
|
||||||
|
hnd.write_func = write_func;
|
||||||
|
zend_hash_str_update_mem(prop_handler, name, name_len, &hnd, sizeof(dom_prop_handler));
|
||||||
|
}
|
||||||
|
|
||||||
static zval *dom_get_property_ptr_ptr(zend_object *object, zend_string *name, int type, void **cache_slot)
|
static zval *dom_get_property_ptr_ptr(zend_object *object, zend_string *name, int type, void **cache_slot)
|
||||||
{
|
{
|
||||||
dom_object *obj = php_dom_obj_from_obj(object);
|
dom_object *obj = php_dom_obj_from_obj(object);
|
||||||
|
@ -815,7 +824,14 @@ PHP_MINIT_FUNCTION(dom)
|
||||||
|
|
||||||
dom_entityreference_class_entry = register_class_DOMEntityReference(dom_node_class_entry);
|
dom_entityreference_class_entry = register_class_DOMEntityReference(dom_node_class_entry);
|
||||||
dom_entityreference_class_entry->create_object = dom_objects_new;
|
dom_entityreference_class_entry->create_object = dom_objects_new;
|
||||||
zend_hash_add_ptr(&classes, dom_entityreference_class_entry->name, &dom_node_prop_handlers);
|
|
||||||
|
zend_hash_init(&dom_entity_reference_prop_handlers, 0, NULL, dom_dtor_prop_handler, true);
|
||||||
|
zend_hash_merge(&dom_entity_reference_prop_handlers, &dom_node_prop_handlers, dom_copy_prop_handler, false);
|
||||||
|
dom_override_prop_handler(&dom_entity_reference_prop_handlers, "firstChild", sizeof("firstChild")-1, dom_entity_reference_child_read, NULL);
|
||||||
|
dom_override_prop_handler(&dom_entity_reference_prop_handlers, "lastChild", sizeof("lastChild")-1, dom_entity_reference_child_read, NULL);
|
||||||
|
dom_override_prop_handler(&dom_entity_reference_prop_handlers, "textContent", sizeof("textContent")-1, dom_entity_reference_text_content_read, NULL);
|
||||||
|
dom_override_prop_handler(&dom_entity_reference_prop_handlers, "childNodes", sizeof("childNodes")-1, dom_entity_reference_child_nodes_read, NULL);
|
||||||
|
zend_hash_add_ptr(&classes, dom_entityreference_class_entry->name, &dom_entity_reference_prop_handlers);
|
||||||
|
|
||||||
dom_processinginstruction_class_entry = register_class_DOMProcessingInstruction(dom_node_class_entry);
|
dom_processinginstruction_class_entry = register_class_DOMProcessingInstruction(dom_node_class_entry);
|
||||||
dom_processinginstruction_class_entry->create_object = dom_objects_new;
|
dom_processinginstruction_class_entry->create_object = dom_objects_new;
|
||||||
|
@ -878,6 +894,7 @@ PHP_MSHUTDOWN_FUNCTION(dom) /* {{{ */
|
||||||
zend_hash_destroy(&dom_document_prop_handlers);
|
zend_hash_destroy(&dom_document_prop_handlers);
|
||||||
zend_hash_destroy(&dom_documentfragment_prop_handlers);
|
zend_hash_destroy(&dom_documentfragment_prop_handlers);
|
||||||
zend_hash_destroy(&dom_node_prop_handlers);
|
zend_hash_destroy(&dom_node_prop_handlers);
|
||||||
|
zend_hash_destroy(&dom_entity_reference_prop_handlers);
|
||||||
zend_hash_destroy(&dom_namespace_node_prop_handlers);
|
zend_hash_destroy(&dom_namespace_node_prop_handlers);
|
||||||
zend_hash_destroy(&dom_nodelist_prop_handlers);
|
zend_hash_destroy(&dom_nodelist_prop_handlers);
|
||||||
zend_hash_destroy(&dom_namednodemap_prop_handlers);
|
zend_hash_destroy(&dom_namednodemap_prop_handlers);
|
||||||
|
|
|
@ -153,6 +153,7 @@ zend_string *dom_node_get_node_name_attribute_or_element(const xmlNode *nodep);
|
||||||
bool php_dom_is_node_connected(const xmlNode *node);
|
bool php_dom_is_node_connected(const xmlNode *node);
|
||||||
bool php_dom_adopt_node(xmlNodePtr nodep, dom_object *dom_object_new_document, xmlDocPtr new_document);
|
bool php_dom_adopt_node(xmlNodePtr nodep, dom_object *dom_object_new_document, xmlDocPtr new_document);
|
||||||
xmlNsPtr dom_get_ns_resolve_prefix_conflict(xmlNodePtr tree, const char *uri);
|
xmlNsPtr dom_get_ns_resolve_prefix_conflict(xmlNodePtr tree, const char *uri);
|
||||||
|
xmlEntityPtr dom_entity_reference_fetch_and_sync_declaration(xmlNodePtr reference);
|
||||||
|
|
||||||
/* parentnode */
|
/* parentnode */
|
||||||
void dom_parent_node_prepend(dom_object *context, zval *nodes, uint32_t nodesc);
|
void dom_parent_node_prepend(dom_object *context, zval *nodes, uint32_t nodesc);
|
||||||
|
|
41
ext/dom/tests/DOMNode_C14N_references.phpt
Normal file
41
ext/dom/tests/DOMNode_C14N_references.phpt
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
--TEST--
|
||||||
|
Test: Canonicalization - C14N() with references
|
||||||
|
--EXTENSIONS--
|
||||||
|
dom
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
// Adapted from canonicalization.phpt
|
||||||
|
|
||||||
|
$xml = <<<EOXML
|
||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<foo xmlns="http://www.example.com/ns/foo"
|
||||||
|
xmlns:fubar="http://www.example.com/ns/fubar" xmlns:test="urn::test"><contain>
|
||||||
|
<bar><test1 /></bar>
|
||||||
|
<bar><test2 /></bar>
|
||||||
|
<fubar:bar xmlns:fubar="http://www.example.com/ns/fubar"><test3 /></fubar:bar>
|
||||||
|
<fubar:bar><test4 /></fubar:bar>
|
||||||
|
</contain>
|
||||||
|
</foo>
|
||||||
|
EOXML;
|
||||||
|
|
||||||
|
$dom = new DOMDocument();
|
||||||
|
$dom->loadXML($xml);
|
||||||
|
$doc = $dom->documentElement->firstChild;
|
||||||
|
|
||||||
|
$xpath = [
|
||||||
|
'query' => '(//a:contain | //a:bar | .//namespace::*)',
|
||||||
|
'namespaces' => ['a' => 'http://www.example.com/ns/foo'],
|
||||||
|
];
|
||||||
|
$prefixes = ['test'];
|
||||||
|
|
||||||
|
foreach ($xpath['namespaces'] as $k => &$v);
|
||||||
|
unset($v);
|
||||||
|
foreach ($xpath as $k => &$v);
|
||||||
|
unset($v);
|
||||||
|
foreach ($prefixes as $k => &$v);
|
||||||
|
unset($v);
|
||||||
|
|
||||||
|
echo $doc->C14N(true, false, $xpath, $prefixes);
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
<contain xmlns="http://www.example.com/ns/foo"><bar></bar><bar></bar></contain>
|
25
ext/dom/tests/childNodes_current_crash.phpt
Normal file
25
ext/dom/tests/childNodes_current_crash.phpt
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
--TEST--
|
||||||
|
Crash in childNodes iterator current()
|
||||||
|
--EXTENSIONS--
|
||||||
|
dom
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$dom = new DOMDocument;
|
||||||
|
$dom->loadXML('<foo>foo1</foo>');
|
||||||
|
|
||||||
|
$nodes = $dom->documentElement->childNodes;
|
||||||
|
$iter = $nodes->getIterator();
|
||||||
|
|
||||||
|
var_dump($iter->valid());
|
||||||
|
var_dump($iter->current()?->wholeText);
|
||||||
|
$iter->next();
|
||||||
|
var_dump($iter->valid());
|
||||||
|
var_dump($iter->current()?->wholeText);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
bool(true)
|
||||||
|
string(4) "foo1"
|
||||||
|
bool(false)
|
||||||
|
NULL
|
41
ext/dom/tests/entity_reference_stale_01.phpt
Normal file
41
ext/dom/tests/entity_reference_stale_01.phpt
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
--TEST--
|
||||||
|
Entity references with stale entity declaration 01
|
||||||
|
--EXTENSIONS--
|
||||||
|
dom
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$dom = new DOMDocument;
|
||||||
|
$dom->loadXML(<<<XML
|
||||||
|
<!DOCTYPE foo [
|
||||||
|
<!ENTITY foo "bar">
|
||||||
|
]>
|
||||||
|
<foo>&foo;</foo>
|
||||||
|
XML);
|
||||||
|
|
||||||
|
$ref = $dom->documentElement->firstChild;
|
||||||
|
$decl = $ref->firstChild;
|
||||||
|
|
||||||
|
$nodes = $ref->childNodes;
|
||||||
|
$dom->removeChild($dom->doctype);
|
||||||
|
unset($decl);
|
||||||
|
|
||||||
|
var_dump($nodes);
|
||||||
|
var_dump($ref->firstChild);
|
||||||
|
var_dump($ref->lastChild);
|
||||||
|
var_dump($ref->textContent);
|
||||||
|
var_dump($ref->childNodes);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
object(DOMNodeList)#4 (1) {
|
||||||
|
["length"]=>
|
||||||
|
int(0)
|
||||||
|
}
|
||||||
|
NULL
|
||||||
|
NULL
|
||||||
|
string(0) ""
|
||||||
|
object(DOMNodeList)#2 (1) {
|
||||||
|
["length"]=>
|
||||||
|
int(0)
|
||||||
|
}
|
35
ext/dom/tests/entity_reference_stale_02.phpt
Normal file
35
ext/dom/tests/entity_reference_stale_02.phpt
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
--TEST--
|
||||||
|
Entity references with stale entity declaration 02
|
||||||
|
--EXTENSIONS--
|
||||||
|
dom
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$dom = new DOMDocument;
|
||||||
|
$dom->loadXML(<<<XML
|
||||||
|
<!DOCTYPE foo [
|
||||||
|
<!ENTITY foo1 "bar1">
|
||||||
|
<!ENTITY foo2 "bar2">
|
||||||
|
<!ENTITY foo3 "bar3">
|
||||||
|
]>
|
||||||
|
<foo>&foo1;</foo>
|
||||||
|
XML);
|
||||||
|
|
||||||
|
$ref = $dom->documentElement->firstChild;
|
||||||
|
$decl = $ref->firstChild;
|
||||||
|
|
||||||
|
$nodes = $ref->childNodes;
|
||||||
|
$iter = $nodes->getIterator();
|
||||||
|
$iter->next();
|
||||||
|
$dom->removeChild($dom->doctype);
|
||||||
|
unset($decl);
|
||||||
|
|
||||||
|
try {
|
||||||
|
var_dump($iter->current()->publicId);
|
||||||
|
} catch (Error $e) {
|
||||||
|
echo $e->getMessage(), "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
NULL
|
Loading…
Add table
Add a link
Reference in a new issue