diff --git a/ext/dom/dom_iterators.c b/ext/dom/dom_iterators.c index 8c6b3023cca..e292728de27 100644 --- a/ext/dom/dom_iterators.c +++ b/ext/dom/dom_iterators.c @@ -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); } } diff --git a/ext/dom/php_dom.h b/ext/dom/php_dom.h index 1c21d8a64e1..438857305db 100644 --- a/ext/dom/php_dom.h +++ b/ext/dom/php_dom.h @@ -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; diff --git a/ext/dom/tests/modern/common/unpacking_foreach.phpt b/ext/dom/tests/modern/common/unpacking_foreach.phpt new file mode 100644 index 00000000000..b2bb301ccdc --- /dev/null +++ b/ext/dom/tests/modern/common/unpacking_foreach.phpt @@ -0,0 +1,30 @@ +--TEST-- +unpacking vs foreach in new DOM +--EXTENSIONS-- +dom +--FILE-- +Hi

hi

", + 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 diff --git a/ext/dom/tests/unpack_foreach_behaviour.phpt b/ext/dom/tests/unpack_foreach_behaviour.phpt new file mode 100644 index 00000000000..42fe896d9f7 --- /dev/null +++ b/ext/dom/tests/unpack_foreach_behaviour.phpt @@ -0,0 +1,31 @@ +--TEST-- +Unpacking vs foreach behaviour +--EXTENSIONS-- +dom +--FILE-- +loadXML(''); + +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" diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index d38e2193d63..7f0cbaeb346 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -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); diff --git a/ext/mbstring/tests/gh17989.phpt b/ext/mbstring/tests/gh17989.phpt new file mode 100644 index 00000000000..40efd5866c1 --- /dev/null +++ b/ext/mbstring/tests/gh17989.phpt @@ -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-- + +--EXPECT-- +set mime type via this echo +hi