Skip to content

Commit 33c4ca3

Browse files
committed
Merge branch 'PHP-8.4'
* PHP-8.4: Fix weird unpack behaviour in DOM Fix phpGH-17989: mb_output_handler crash with unset http_output_conv_mimetypes
2 parents 30ce9ac + aa6e58f commit 33c4ca3

File tree

6 files changed

+90
-6
lines changed

6 files changed

+90
-6
lines changed

ext/dom/dom_iterators.c

+7-5
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ static void php_dom_iterator_current_key(zend_object_iterator *iter, zval *key)
132132
/* Only dtd named node maps, i.e. the ones based on a libxml hash table or attribute collections,
133133
* are keyed by the name because in that case the name is unique. */
134134
if (!objmap->ht && objmap->nodetype != XML_ATTRIBUTE_NODE) {
135-
ZVAL_LONG(key, iter->index);
135+
ZVAL_LONG(key, iterator->index);
136136
} else {
137137
dom_object *intern = Z_DOMOBJ_P(&iterator->curobj);
138138

@@ -179,6 +179,8 @@ static void php_dom_iterator_move_forward(zend_object_iterator *iter) /* {{{ */
179179
return;
180180
}
181181

182+
iterator->index++;
183+
182184
dom_object *intern = Z_DOMOBJ_P(&iterator->curobj);
183185
dom_nnodemap_object *objmap = php_dom_iterator_get_nnmap(iterator);
184186

@@ -203,7 +205,7 @@ static void php_dom_iterator_move_forward(zend_object_iterator *iter) /* {{{ */
203205
php_dom_mark_cache_tag_up_to_date_from_doc_ref(&iterator->cache_tag, intern->document);
204206
curnode = dom_fetch_first_iteration_item(objmap);
205207
zend_ulong index = 0;
206-
while (curnode != NULL && index++ < iter->index) {
208+
while (curnode != NULL && index++ < iterator->index) {
207209
curnode = curnode->next;
208210
}
209211
} else {
@@ -224,15 +226,15 @@ static void php_dom_iterator_move_forward(zend_object_iterator *iter) /* {{{ */
224226
previndex = 0;
225227
curnode = php_dom_first_child_of_container_node(basenode);
226228
} else {
227-
previndex = iter->index - 1;
229+
previndex = iterator->index - 1;
228230
curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->ptr)->node;
229231
}
230232
curnode = dom_get_elements_by_tag_name_ns_raw(
231-
basenode, curnode, objmap->ns, objmap->local, objmap->local_lower, &previndex, iter->index);
233+
basenode, curnode, objmap->ns, objmap->local, objmap->local_lower, &previndex, iterator->index);
232234
}
233235
}
234236
} else {
235-
curnode = php_dom_libxml_hash_iter(objmap, iter->index);
237+
curnode = php_dom_libxml_hash_iter(objmap, iterator->index);
236238
}
237239
}
238240

ext/dom/php_dom.h

+3
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ typedef struct {
9898
zend_object_iterator intern;
9999
zval curobj;
100100
HashPosition pos;
101+
/* intern->index is only updated for FE_* opcodes, not for e.g. unpacking,
102+
* yet we need to track the position of the node relative to the start. */
103+
zend_ulong index;
101104
php_libxml_cache_tag cache_tag;
102105
} php_dom_iterator;
103106

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
--TEST--
2+
unpacking vs foreach in new DOM
3+
--EXTENSIONS--
4+
dom
5+
--FILE--
6+
<?php
7+
8+
$html = Dom\HTMLDocument::createFromString
9+
(
10+
source: "<h1>Hi</h1><p>hi</p>",
11+
options: LIBXML_NOERROR,
12+
);
13+
14+
foreach ($html->body->childNodes as $node) {
15+
echo $node->localName, "\n";
16+
}
17+
18+
echo "---\n";
19+
20+
foreach ([...$html->body->childNodes] as $node) {
21+
echo $node->localName, "\n";
22+
}
23+
24+
?>
25+
--EXPECT--
26+
h1
27+
p
28+
---
29+
h1
30+
p
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--TEST--
2+
Unpacking vs foreach behaviour
3+
--EXTENSIONS--
4+
dom
5+
--FILE--
6+
<?php
7+
8+
$dom = new DOMDocument;
9+
$dom->loadXML('<root><a/><b/></root>');
10+
11+
echo "--- By foreach: ---\n";
12+
13+
foreach ($dom->documentElement->getElementsByTagName('*') as $node) {
14+
var_dump($node->localName);
15+
}
16+
17+
echo "--- By unpacking: ---\n";
18+
19+
$iter = $dom->documentElement->getElementsByTagName('*');
20+
foreach ([...$iter] as $node) {
21+
var_dump($node->localName);
22+
}
23+
24+
?>
25+
--EXPECT--
26+
--- By foreach: ---
27+
string(1) "a"
28+
string(1) "b"
29+
--- By unpacking: ---
30+
string(1) "a"
31+
string(1) "b"

ext/mbstring/mbstring.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -1573,7 +1573,9 @@ PHP_FUNCTION(mb_output_handler)
15731573
char *mimetype = NULL;
15741574

15751575
/* Analyze mime type */
1576-
if (SG(sapi_headers).mimetype && _php_mb_match_regex(MBSTRG(http_output_conv_mimetypes), SG(sapi_headers).mimetype, strlen(SG(sapi_headers).mimetype))) {
1576+
if (SG(sapi_headers).mimetype
1577+
&& MBSTRG(http_output_conv_mimetypes)
1578+
&& _php_mb_match_regex(MBSTRG(http_output_conv_mimetypes), SG(sapi_headers).mimetype, strlen(SG(sapi_headers).mimetype))) {
15771579
char *s;
15781580
if ((s = strchr(SG(sapi_headers).mimetype, ';')) == NULL) {
15791581
mimetype = estrdup(SG(sapi_headers).mimetype);

ext/mbstring/tests/gh17989.phpt

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
GH-17989 (mb_output_handler crash with unset http_output_conv_mimetypes)
3+
--EXTENSIONS--
4+
mbstring
5+
--INI--
6+
mbstring.http_output_conv_mimetypes=
7+
--FILE--
8+
<?php
9+
echo "set mime type via this echo\n";
10+
ob_start('mb_output_handler');
11+
echo "hi";
12+
ob_flush();
13+
?>
14+
--EXPECT--
15+
set mime type via this echo
16+
hi

0 commit comments

Comments
 (0)