Skip to content

Commit 73b7993

Browse files
committed
Merge branch 'PHP-8.3'
* PHP-8.3: Fix GH-15654: Signed integer overflow in ext/dom/nodelist.c
2 parents 166f343 + 9cb23a3 commit 73b7993

File tree

7 files changed

+45
-11
lines changed

7 files changed

+45
-11
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ PHP NEWS
1414
- DOM:
1515
. Fixed bug GH-13988 (Storing DOMElement consume 4 times more memory in
1616
PHP 8.1 than in PHP 8.0). (nielsdos)
17+
. Fixed bug GH-15654 (Signed integer overflow in ext/dom/nodelist.c).
18+
(nielsdos)
1719

1820
- GD:
1921
. Added gdImageClone to bundled libgd. (David Carlier)

ext/dom/dom_iterators.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ static xmlNodePtr dom_fetch_first_iteration_item(dom_nnodemap_object *objmap)
152152
return dom_nodelist_iter_start_first_child(basep);
153153
}
154154
} else {
155-
int curindex = 0;
155+
zend_long curindex = 0;
156156
xmlNodePtr nodep = php_dom_first_child_of_container_node(basep);
157157
return dom_get_elements_by_tag_name_ns_raw(
158158
basep, nodep, objmap->ns, objmap->local, objmap->local_lower, &curindex, 0);
@@ -209,7 +209,7 @@ static void php_dom_iterator_move_forward(zend_object_iterator *iter) /* {{{ */
209209
/* We have a strong reference to the base node via baseobj_zv, this cannot become NULL */
210210
ZEND_ASSERT(basenode != NULL);
211211

212-
int previndex;
212+
zend_long previndex;
213213
if (php_dom_is_cache_tag_stale_from_node(&iterator->cache_tag, basenode)) {
214214
php_dom_mark_cache_tag_up_to_date_from_node(&iterator->cache_tag, basenode);
215215
previndex = 0;

ext/dom/html_collection.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ static dom_named_item dom_html_collection_named_item(zend_string *key, zend_obje
4646
/* 2. Return the first element in the collection for which at least one of the following is true: */
4747
xmlNodePtr basep = dom_object_get_node(objmap->baseobj);
4848
if (basep != NULL) {
49-
int cur = 0;
50-
int next = cur; /* not +1, otherwise we skip the first candidate */
49+
zend_long cur = 0;
50+
zend_long next = cur; /* not +1, otherwise we skip the first candidate */
5151
xmlNodePtr candidate = basep->children;
5252
while (candidate != NULL) {
5353
candidate = dom_get_elements_by_tag_name_ns_raw(basep, candidate, objmap->ns, objmap->local, objmap->local_lower, &cur, next);

ext/dom/nodelist.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ zend_long php_dom_get_nodelist_length(dom_object *obj)
9292
reset_objmap_cache(objmap);
9393
}
9494

95-
int count = 0;
95+
zend_long count = 0;
9696
if (objmap->nodetype == XML_ATTRIBUTE_NODE || objmap->nodetype == XML_ELEMENT_NODE) {
9797
xmlNodePtr curnode = dom_nodelist_iter_start_first_child(nodep);
9898
if (curnode) {
@@ -106,7 +106,7 @@ zend_long php_dom_get_nodelist_length(dom_object *obj)
106106
xmlNodePtr basep = nodep;
107107
nodep = php_dom_first_child_of_container_node(basep);
108108
dom_get_elements_by_tag_name_ns_raw(
109-
basep, nodep, objmap->ns, objmap->local, objmap->local_lower, &count, INT_MAX - 1 /* because of <= */);
109+
basep, nodep, objmap->ns, objmap->local, objmap->local_lower, &count, ZEND_LONG_MAX - 1 /* because of <= */);
110110
}
111111

112112
objmap->cached_length = count;
@@ -159,7 +159,7 @@ void php_dom_nodelist_get_item_into_zval(dom_nnodemap_object *objmap, zend_long
159159
* TODO: in the future we could extend the logic of the node list such that backwards searches
160160
* are also possible. */
161161
bool restart = true;
162-
int relative_index = index;
162+
zend_long relative_index = index;
163163
if (index >= objmap->cached_obj_index && objmap->cached_obj && !php_dom_is_cache_tag_stale_from_node(&objmap->cache_tag, nodep)) {
164164
xmlNodePtr cached_obj_xml_node = dom_object_get_node(objmap->cached_obj);
165165

@@ -177,7 +177,7 @@ void php_dom_nodelist_get_item_into_zval(dom_nnodemap_object *objmap, zend_long
177177
nodep = cached_obj_xml_node;
178178
}
179179
}
180-
int count = 0;
180+
zend_long count = 0;
181181
if (objmap->nodetype == XML_ATTRIBUTE_NODE || objmap->nodetype == XML_ELEMENT_NODE) {
182182
if (restart) {
183183
nodep = dom_nodelist_iter_start_first_child(nodep);

ext/dom/php_dom.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1855,7 +1855,7 @@ static bool dom_match_qualified_name_for_tag_name_equality(const xmlChar *local,
18551855
return dom_match_qualified_name_according_to_spec(local_to_use, nodep);
18561856
}
18571857

1858-
xmlNode *dom_get_elements_by_tag_name_ns_raw(xmlNodePtr basep, xmlNodePtr nodep, xmlChar *ns, xmlChar *local, xmlChar *local_lower, int *cur, int index) /* {{{ */
1858+
xmlNode *dom_get_elements_by_tag_name_ns_raw(xmlNodePtr basep, xmlNodePtr nodep, xmlChar *ns, xmlChar *local, xmlChar *local_lower, zend_long *cur, zend_long index) /* {{{ */
18591859
{
18601860
/* Can happen with detached document */
18611861
if (UNEXPECTED(nodep == NULL)) {

ext/dom/php_dom.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ typedef struct dom_nnodemap_object {
8787
xmlChar *ns;
8888
php_libxml_cache_tag cache_tag;
8989
dom_object *cached_obj;
90-
int cached_obj_index;
90+
zend_long cached_obj_index;
9191
bool free_local : 1;
9292
bool free_ns : 1;
9393
} dom_nnodemap_object;
@@ -143,7 +143,7 @@ void dom_reconcile_ns_list(xmlDocPtr doc, xmlNodePtr nodep, xmlNodePtr last);
143143
xmlNsPtr dom_get_nsdecl(xmlNode *node, xmlChar *localName);
144144
void php_dom_normalize_legacy(xmlNodePtr nodep);
145145
void php_dom_normalize_modern(xmlNodePtr nodep);
146-
xmlNode *dom_get_elements_by_tag_name_ns_raw(xmlNodePtr basep, xmlNodePtr nodep, xmlChar *ns, xmlChar *local, xmlChar *local_lower, int *cur, int index);
146+
xmlNode *dom_get_elements_by_tag_name_ns_raw(xmlNodePtr basep, xmlNodePtr nodep, xmlChar *ns, xmlChar *local, xmlChar *local_lower, zend_long *cur, zend_long index);
147147
void php_dom_create_implementation(zval *retval, bool modern);
148148
int dom_hierarchy(xmlNodePtr parent, xmlNodePtr child);
149149
bool dom_has_feature(zend_string *feature, zend_string *version);

ext/dom/tests/gh15654.phpt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
GH-15654 (Signed integer overflow in ext/dom/nodelist.c)
3+
--EXTENSIONS--
4+
dom
5+
--SKIPIF--
6+
<?php
7+
if (PHP_INT_SIZE != 8) die('skip 64-bit only');
8+
?>
9+
--FILE--
10+
<?php
11+
define("MAX_64Bit", 9223372036854775807);
12+
define("MAX_32Bit", 2147483647);
13+
define("MIN_64Bit", -9223372036854775807 - 1);
14+
define("MIN_32Bit", -2147483647 - 1);
15+
$longVals = array(
16+
0, MAX_64Bit, MIN_64Bit, MAX_32Bit, MIN_32Bit, MAX_64Bit - MAX_32Bit, MIN_64Bit - MIN_32Bit,
17+
);
18+
$dom = new DOMDocument;
19+
$dom->loadXML('<root><a/><b/><c/></root>');
20+
$children = $dom->documentElement->childNodes;
21+
foreach ($longVals as $value) {
22+
var_dump($children[$value]?->nodeName);
23+
}
24+
?>
25+
--EXPECT--
26+
string(1) "a"
27+
NULL
28+
NULL
29+
NULL
30+
NULL
31+
NULL
32+
NULL

0 commit comments

Comments
 (0)