mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Fix GH-15654: Signed integer overflow in ext/dom/nodelist.c
There's implicit truncation casts from zend_long to int which cause issues because checks are done against the zend_longs. Since the iterator infrastructure uses zend_longs, just convert everything to zend_long. Closes GH-15669.
This commit is contained in:
parent
8ad7d8f1cd
commit
9cb23a3dec
6 changed files with 43 additions and 9 deletions
2
NEWS
2
NEWS
|
@ -20,6 +20,8 @@ PHP NEWS
|
|||
- DOM:
|
||||
. Fixed bug GH-15551 (Segmentation fault (access null pointer) in
|
||||
ext/dom/xml_common.h). (nielsdos)
|
||||
. Fixed bug GH-15654 (Signed integer overflow in ext/dom/nodelist.c).
|
||||
(nielsdos)
|
||||
|
||||
- MySQLnd:
|
||||
. Fixed bug GH-15432 (Heap corruption when querying a vector). (cmb,
|
||||
|
|
|
@ -179,7 +179,7 @@ static void php_dom_iterator_move_forward(zend_object_iterator *iter) /* {{{ */
|
|||
dom_object *intern;
|
||||
dom_object *nnmap;
|
||||
dom_nnodemap_object *objmap;
|
||||
int previndex;
|
||||
zend_long previndex;
|
||||
HashTable *nodeht;
|
||||
zval *entry;
|
||||
bool do_curobj_undef = 1;
|
||||
|
@ -269,7 +269,7 @@ zend_object_iterator *php_dom_get_iterator(zend_class_entry *ce, zval *object, i
|
|||
dom_object *intern;
|
||||
dom_nnodemap_object *objmap;
|
||||
xmlNodePtr curnode=NULL;
|
||||
int curindex = 0;
|
||||
zend_long curindex = 0;
|
||||
HashTable *nodeht;
|
||||
zval *entry;
|
||||
php_dom_iterator *iterator;
|
||||
|
|
|
@ -91,7 +91,7 @@ int php_dom_get_nodelist_length(dom_object *obj)
|
|||
reset_objmap_cache(objmap);
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
zend_long count = 0;
|
||||
if (objmap->nodetype == XML_ATTRIBUTE_NODE || objmap->nodetype == XML_ELEMENT_NODE) {
|
||||
xmlNodePtr curnode = dom_nodelist_iter_start_first_child(nodep);
|
||||
if (curnode) {
|
||||
|
@ -109,7 +109,7 @@ int php_dom_get_nodelist_length(dom_object *obj)
|
|||
nodep = nodep->children;
|
||||
}
|
||||
dom_get_elements_by_tag_name_ns_raw(
|
||||
basep, nodep, (char *) objmap->ns, (char *) objmap->local, &count, INT_MAX - 1 /* because of <= */);
|
||||
basep, nodep, (char *) objmap->ns, (char *) objmap->local, &count, ZEND_LONG_MAX - 1 /* because of <= */);
|
||||
}
|
||||
|
||||
objmap->cached_length = count;
|
||||
|
@ -174,7 +174,7 @@ void php_dom_nodelist_get_item_into_zval(dom_nnodemap_object *objmap, zend_long
|
|||
* TODO: in the future we could extend the logic of the node list such that backwards searches
|
||||
* are also possible. */
|
||||
bool restart = true;
|
||||
int relative_index = index;
|
||||
zend_long relative_index = index;
|
||||
if (index >= objmap->cached_obj_index && objmap->cached_obj && !php_dom_is_cache_tag_stale_from_node(&objmap->cache_tag, nodep)) {
|
||||
xmlNodePtr cached_obj_xml_node = dom_object_get_node(objmap->cached_obj);
|
||||
|
||||
|
@ -192,7 +192,7 @@ void php_dom_nodelist_get_item_into_zval(dom_nnodemap_object *objmap, zend_long
|
|||
nodep = cached_obj_xml_node;
|
||||
}
|
||||
}
|
||||
int count = 0;
|
||||
zend_long count = 0;
|
||||
if (objmap->nodetype == XML_ATTRIBUTE_NODE || objmap->nodetype == XML_ELEMENT_NODE) {
|
||||
if (restart) {
|
||||
nodep = dom_nodelist_iter_start_first_child(nodep);
|
||||
|
|
|
@ -1334,7 +1334,7 @@ bool dom_has_feature(zend_string *feature, zend_string *version)
|
|||
}
|
||||
/* }}} end dom_has_feature */
|
||||
|
||||
xmlNode *dom_get_elements_by_tag_name_ns_raw(xmlNodePtr basep, xmlNodePtr nodep, char *ns, char *local, int *cur, int index) /* {{{ */
|
||||
xmlNode *dom_get_elements_by_tag_name_ns_raw(xmlNodePtr basep, xmlNodePtr nodep, char *ns, char *local, zend_long *cur, zend_long index) /* {{{ */
|
||||
{
|
||||
/* Can happen with detached document */
|
||||
if (UNEXPECTED(nodep == NULL)) {
|
||||
|
|
|
@ -88,7 +88,7 @@ typedef struct _dom_nnodemap_object {
|
|||
xmlChar *ns;
|
||||
php_libxml_cache_tag cache_tag;
|
||||
dom_object *cached_obj;
|
||||
int cached_obj_index;
|
||||
zend_long cached_obj_index;
|
||||
bool free_local : 1;
|
||||
bool free_ns : 1;
|
||||
} dom_nnodemap_object;
|
||||
|
@ -133,7 +133,7 @@ void dom_reconcile_ns(xmlDocPtr doc, xmlNodePtr nodep);
|
|||
void dom_reconcile_ns_list(xmlDocPtr doc, xmlNodePtr nodep, xmlNodePtr last);
|
||||
xmlNsPtr dom_get_nsdecl(xmlNode *node, xmlChar *localName);
|
||||
void dom_normalize (xmlNodePtr nodep);
|
||||
xmlNode *dom_get_elements_by_tag_name_ns_raw(xmlNodePtr basep, xmlNodePtr nodep, char *ns, char *local, int *cur, int index);
|
||||
xmlNode *dom_get_elements_by_tag_name_ns_raw(xmlNodePtr basep, xmlNodePtr nodep, char *ns, char *local, zend_long *cur, zend_long index);
|
||||
void php_dom_create_implementation(zval *retval);
|
||||
int dom_hierarchy(xmlNodePtr parent, xmlNodePtr child);
|
||||
bool dom_has_feature(zend_string *feature, zend_string *version);
|
||||
|
|
32
ext/dom/tests/gh15654.phpt
Normal file
32
ext/dom/tests/gh15654.phpt
Normal file
|
@ -0,0 +1,32 @@
|
|||
--TEST--
|
||||
GH-15654 (Signed integer overflow in ext/dom/nodelist.c)
|
||||
--EXTENSIONS--
|
||||
dom
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (PHP_INT_SIZE != 8) die('skip 64-bit only');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
define("MAX_64Bit", 9223372036854775807);
|
||||
define("MAX_32Bit", 2147483647);
|
||||
define("MIN_64Bit", -9223372036854775807 - 1);
|
||||
define("MIN_32Bit", -2147483647 - 1);
|
||||
$longVals = array(
|
||||
0, MAX_64Bit, MIN_64Bit, MAX_32Bit, MIN_32Bit, MAX_64Bit - MAX_32Bit, MIN_64Bit - MIN_32Bit,
|
||||
);
|
||||
$dom = new DOMDocument;
|
||||
$dom->loadXML('<root><a/><b/><c/></root>');
|
||||
$children = $dom->documentElement->childNodes;
|
||||
foreach ($longVals as $value) {
|
||||
var_dump($children[$value]?->nodeName);
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
string(1) "a"
|
||||
NULL
|
||||
NULL
|
||||
NULL
|
||||
NULL
|
||||
NULL
|
||||
NULL
|
Loading…
Add table
Add a link
Reference in a new issue