diff --git a/NEWS b/NEWS index 8971e7d317a3..cd396479e3e2 100644 --- a/NEWS +++ b/NEWS @@ -20,6 +20,9 @@ PHP NEWS - DOM: . Fixed bug GH-22570 (Stack overflow when serializing a deeply nested Dom\XMLDocument). (iliaal) + . Fixed Dom\DtdNamedNodeMap integer dimension access so negative indexes + return NULL and indexes outside the int range throw ValueError instead of + returning the first entity or notation. (Weilin Du) - Exif: . Fixed bug GH-11020 (exif_read_data() emits a spurious "Illegal IFD size" diff --git a/ext/dom/dom_iterators.c b/ext/dom/dom_iterators.c index f97a9ec825d5..7566dd8b61a8 100644 --- a/ext/dom/dom_iterators.c +++ b/ext/dom/dom_iterators.c @@ -79,14 +79,22 @@ void dom_free_notation(xmlEntityPtr entity) /* {{{ */ } /* }}} */ -xmlNodePtr php_dom_libxml_hash_iter(xmlHashTable *ht, int index) +xmlNodePtr php_dom_libxml_hash_iter(xmlHashTable *ht, zend_long index) { int htsize; + if (index < 0) { + return NULL; + } + if (UNEXPECTED(ZEND_LONG_INT_OVFL(index))) { + zend_value_error("must be between 0 and %d", INT_MAX); + return NULL; + } + if ((htsize = xmlHashSize(ht)) > 0 && index < htsize) { nodeIterator iter; iter.cur = 0; - iter.index = index; + iter.index = (int) index; iter.node = NULL; xmlHashScan(ht, itemHashScanner, &iter); return iter.node; diff --git a/ext/dom/php_dom.h b/ext/dom/php_dom.h index 1b19aeee3baa..6f4b5075b659 100644 --- a/ext/dom/php_dom.h +++ b/ext/dom/php_dom.h @@ -127,7 +127,7 @@ bool dom_node_is_read_only(const xmlNode *node); bool dom_node_children_valid(const xmlNode *node); xmlNodePtr create_notation(xmlDtdPtr parent_dtd, const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID); void dom_free_notation(xmlEntityPtr entity); -xmlNode *php_dom_libxml_hash_iter(xmlHashTable *ht, int index); +xmlNode *php_dom_libxml_hash_iter(xmlHashTable *ht, zend_long index); zend_object_iterator *php_dom_get_iterator(zend_class_entry *ce, zval *object, int by_ref); void dom_set_doc_classmap(php_libxml_ref_obj *document, zend_class_entry *basece, zend_class_entry *ce); xmlNodePtr php_dom_create_fake_namespace_decl(xmlNodePtr nodep, xmlNsPtr original, zval *return_value, dom_object *parent_intern); diff --git a/ext/dom/tests/modern/xml/DtdNamedNodeMap_dimension_index_overflow_64.phpt b/ext/dom/tests/modern/xml/DtdNamedNodeMap_dimension_index_overflow_64.phpt new file mode 100644 index 000000000000..cc2d7a06a2ca --- /dev/null +++ b/ext/dom/tests/modern/xml/DtdNamedNodeMap_dimension_index_overflow_64.phpt @@ -0,0 +1,41 @@ +--TEST-- +Dom\DtdNamedNodeMap dimension access handles invalid integer indexes +--EXTENSIONS-- +dom +--SKIPIF-- + +--FILE-- + + +]> + +XML); + +$overflow = 4294967296; + +function dump_access(Closure $callback): void { + try { + var_dump($callback()?->nodeName); + } catch (ValueError $e) { + echo $e->getMessage(), PHP_EOL; + } +} + +dump_access(fn() => $doc->doctype->entities[-1]); +dump_access(fn() => $doc->doctype->entities[$overflow]); + +dump_access(fn() => $doc->doctype->notations[-1]); +dump_access(fn() => $doc->doctype->notations[$overflow]); +?> +--EXPECT-- +NULL +must be between 0 and 2147483647 +NULL +must be between 0 and 2147483647