Merge branch 'PHP-8.4'

* PHP-8.4:
  Fix weird unpack behaviour in DOM
  Fix GH-17989: mb_output_handler crash with unset http_output_conv_mimetypes
This commit is contained in:
Niels Dossche 2025-03-09 11:21:34 +01:00
commit 33c4ca36e4
No known key found for this signature in database
GPG key ID: B8A8AD166DF0E2E5
6 changed files with 90 additions and 6 deletions

View file

@ -132,7 +132,7 @@ static void php_dom_iterator_current_key(zend_object_iterator *iter, zval *key)
/* Only dtd named node maps, i.e. the ones based on a libxml hash table or attribute collections,
* are keyed by the name because in that case the name is unique. */
if (!objmap->ht && objmap->nodetype != XML_ATTRIBUTE_NODE) {
ZVAL_LONG(key, iter->index);
ZVAL_LONG(key, iterator->index);
} else {
dom_object *intern = Z_DOMOBJ_P(&iterator->curobj);
@ -179,6 +179,8 @@ static void php_dom_iterator_move_forward(zend_object_iterator *iter) /* {{{ */
return;
}
iterator->index++;
dom_object *intern = Z_DOMOBJ_P(&iterator->curobj);
dom_nnodemap_object *objmap = php_dom_iterator_get_nnmap(iterator);
@ -203,7 +205,7 @@ static void php_dom_iterator_move_forward(zend_object_iterator *iter) /* {{{ */
php_dom_mark_cache_tag_up_to_date_from_doc_ref(&iterator->cache_tag, intern->document);
curnode = dom_fetch_first_iteration_item(objmap);
zend_ulong index = 0;
while (curnode != NULL && index++ < iter->index) {
while (curnode != NULL && index++ < iterator->index) {
curnode = curnode->next;
}
} else {
@ -224,15 +226,15 @@ static void php_dom_iterator_move_forward(zend_object_iterator *iter) /* {{{ */
previndex = 0;
curnode = php_dom_first_child_of_container_node(basenode);
} else {
previndex = iter->index - 1;
previndex = iterator->index - 1;
curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->ptr)->node;
}
curnode = dom_get_elements_by_tag_name_ns_raw(
basenode, curnode, objmap->ns, objmap->local, objmap->local_lower, &previndex, iter->index);
basenode, curnode, objmap->ns, objmap->local, objmap->local_lower, &previndex, iterator->index);
}
}
} else {
curnode = php_dom_libxml_hash_iter(objmap, iter->index);
curnode = php_dom_libxml_hash_iter(objmap, iterator->index);
}
}

View file

@ -98,6 +98,9 @@ typedef struct {
zend_object_iterator intern;
zval curobj;
HashPosition pos;
/* intern->index is only updated for FE_* opcodes, not for e.g. unpacking,
* yet we need to track the position of the node relative to the start. */
zend_ulong index;
php_libxml_cache_tag cache_tag;
} php_dom_iterator;

View file

@ -0,0 +1,30 @@
--TEST--
unpacking vs foreach in new DOM
--EXTENSIONS--
dom
--FILE--
<?php
$html = Dom\HTMLDocument::createFromString
(
source: "<h1>Hi</h1><p>hi</p>",
options: LIBXML_NOERROR,
);
foreach ($html->body->childNodes as $node) {
echo $node->localName, "\n";
}
echo "---\n";
foreach ([...$html->body->childNodes] as $node) {
echo $node->localName, "\n";
}
?>
--EXPECT--
h1
p
---
h1
p

View file

@ -0,0 +1,31 @@
--TEST--
Unpacking vs foreach behaviour
--EXTENSIONS--
dom
--FILE--
<?php
$dom = new DOMDocument;
$dom->loadXML('<root><a/><b/></root>');
echo "--- By foreach: ---\n";
foreach ($dom->documentElement->getElementsByTagName('*') as $node) {
var_dump($node->localName);
}
echo "--- By unpacking: ---\n";
$iter = $dom->documentElement->getElementsByTagName('*');
foreach ([...$iter] as $node) {
var_dump($node->localName);
}
?>
--EXPECT--
--- By foreach: ---
string(1) "a"
string(1) "b"
--- By unpacking: ---
string(1) "a"
string(1) "b"

View file

@ -1573,7 +1573,9 @@ PHP_FUNCTION(mb_output_handler)
char *mimetype = NULL;
/* Analyze mime type */
if (SG(sapi_headers).mimetype && _php_mb_match_regex(MBSTRG(http_output_conv_mimetypes), SG(sapi_headers).mimetype, strlen(SG(sapi_headers).mimetype))) {
if (SG(sapi_headers).mimetype
&& MBSTRG(http_output_conv_mimetypes)
&& _php_mb_match_regex(MBSTRG(http_output_conv_mimetypes), SG(sapi_headers).mimetype, strlen(SG(sapi_headers).mimetype))) {
char *s;
if ((s = strchr(SG(sapi_headers).mimetype, ';')) == NULL) {
mimetype = estrdup(SG(sapi_headers).mimetype);

View file

@ -0,0 +1,16 @@
--TEST--
GH-17989 (mb_output_handler crash with unset http_output_conv_mimetypes)
--EXTENSIONS--
mbstring
--INI--
mbstring.http_output_conv_mimetypes=
--FILE--
<?php
echo "set mime type via this echo\n";
ob_start('mb_output_handler');
echo "hi";
ob_flush();
?>
--EXPECT--
set mime type via this echo
hi