From b8a1041fd29c7fa2b29625933021efcc3992a045 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 25 Feb 2024 22:59:20 +0100 Subject: [PATCH] Fix reference access in dimensions for DOMNodeList and DOMNodeMap Closes GH-13511. --- NEWS | 4 ++ ext/dom/php_dom.c | 8 +++ .../DOMNamedNodeMap_string_references.phpt | 64 +++++++++++++++++++ ext/dom/tests/bug67949.phpt | 51 +++++++-------- 4 files changed, 102 insertions(+), 25 deletions(-) create mode 100644 ext/dom/tests/DOMNamedNodeMap_string_references.phpt diff --git a/NEWS b/NEWS index d28d31e1efa..4e95d7e576a 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,10 @@ PHP NEWS - Curl: . Fix failing tests due to string changes in libcurl 8.6.0. (Ayesh) +- DOM: + . Fix reference access in dimensions for DOMNodeList and DOMNodeMap. + (nielsdos) + - Fileinfo: . Fixed bug GH-13344 (finfo::buffer(): Failed identify data 0:(null), backport). (nielsdos) diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c index 6610a504e4f..c86cab99c6c 100644 --- a/ext/dom/php_dom.c +++ b/ext/dom/php_dom.c @@ -1643,6 +1643,8 @@ static zval *dom_nodelist_read_dimension(zend_object *object, zval *offset, int return NULL; } + ZVAL_DEREF(offset); + zend_long lval; if (dom_nodemap_or_nodelist_process_offset_as_named(offset, &lval)) { /* does not support named lookup */ @@ -1656,6 +1658,8 @@ static zval *dom_nodelist_read_dimension(zend_object *object, zval *offset, int static int dom_nodelist_has_dimension(zend_object *object, zval *member, int check_empty) { + ZVAL_DEREF(member); + zend_long offset; if (dom_nodemap_or_nodelist_process_offset_as_named(member, &offset)) { /* does not support named lookup */ @@ -1672,6 +1676,8 @@ static zval *dom_nodemap_read_dimension(zend_object *object, zval *offset, int t return NULL; } + ZVAL_DEREF(offset); + zend_long lval; if (dom_nodemap_or_nodelist_process_offset_as_named(offset, &lval)) { /* exceptional case, switch to named lookup */ @@ -1691,6 +1697,8 @@ static zval *dom_nodemap_read_dimension(zend_object *object, zval *offset, int t static int dom_nodemap_has_dimension(zend_object *object, zval *member, int check_empty) { + ZVAL_DEREF(member); + zend_long offset; if (dom_nodemap_or_nodelist_process_offset_as_named(member, &offset)) { /* exceptional case, switch to named lookup */ diff --git a/ext/dom/tests/DOMNamedNodeMap_string_references.phpt b/ext/dom/tests/DOMNamedNodeMap_string_references.phpt new file mode 100644 index 00000000000..f6a79286b91 --- /dev/null +++ b/ext/dom/tests/DOMNamedNodeMap_string_references.phpt @@ -0,0 +1,64 @@ +--TEST-- +DOMNamedNodeMap string references +--EXTENSIONS-- +dom +--FILE-- +loadXML(''); + +$attributes = $dom->documentElement->attributes; + +var_dump(isset($attributes['href']), $attributes['href']->value); + +var_dump(isset($attributes['foo']), $attributes['foo']->value); + +$str = 'href'; +$ref =& $str; +var_dump(isset($attributes[$ref]), $attributes[$ref]->value); + +$str = 'foo'; +$ref =& $str; +var_dump(isset($attributes[$ref]), $attributes[$ref]->value); + +$str = 'this does not exist'; +$ref =& $str; +var_dump(isset($attributes[$ref]), $attributes[$ref]); + +$str = '0'; +$ref =& $str; +var_dump(isset($attributes[$ref]), $attributes[$ref]->value); + +$str = '1'; +$ref =& $str; +var_dump(isset($attributes[$ref]), $attributes[$ref]->value); + +$int = 0; +$ref =& $int; +var_dump(isset($attributes[$ref]), $attributes[$ref]->value); + +$int = 1; +$ref =& $int; +var_dump(isset($attributes[$ref]), $attributes[$ref]->value); + +?> +--EXPECT-- +bool(true) +string(2) "hi" +bool(true) +string(3) "bar" +bool(true) +string(2) "hi" +bool(true) +string(3) "bar" +bool(false) +NULL +bool(true) +string(2) "hi" +bool(true) +string(3) "bar" +bool(true) +string(2) "hi" +bool(true) +string(3) "bar" diff --git a/ext/dom/tests/bug67949.phpt b/ext/dom/tests/bug67949.phpt index 270beb02b49..f087633bdfe 100644 --- a/ext/dom/tests/bug67949.phpt +++ b/ext/dom/tests/bug67949.phpt @@ -5,6 +5,8 @@ dom --FILE-- data hello world @@ -14,57 +16,56 @@ $doc->loadHTML($html); $nodes = $doc->getElementsByTagName('div'); -echo "testing has_dimension\n"; +echo "--- testing has_dimension ---\n"; var_dump(isset($nodes[0])); var_dump(isset($nodes[1])); var_dump(isset($nodes[-1])); -echo "testing property access\n"; +echo "--- testing property access ---\n"; var_dump($nodes[0]->textContent); var_dump($nodes[1]->textContent); -echo "testing offset not a long\n"; +echo "--- testing offset not a long: array ---\n"; $offset = ['test']; var_dump($offset); var_dump(isset($nodes[$offset]), $nodes[$offset]->textContent); -var_dump($offset); -$something = 'test'; +echo "--- testing offset not a long: Reference to string ---\n"; +$something = 'href'; $offset = &$something; var_dump($offset); var_dump(isset($nodes[$offset]), $nodes[$offset]->textContent); -var_dump($offset); +echo "--- testing offset not a long: string ---\n"; $offset = 'test'; var_dump($offset); var_dump(isset($nodes[$offset]), $nodes[$offset]->textContent); -var_dump($offset); -echo "testing read_dimension with null offset\n"; +echo "--- testing read_dimension with null offset ---\n"; try { var_dump($nodes[][] = 1); } catch (Error $e) { echo $e->getMessage(), "\n"; } -echo "testing attribute access\n"; +echo "--- testing attribute access ---\n"; $anchor = $doc->getElementsByTagName('a')[0]; var_dump($anchor->attributes[0]->name); echo "==DONE==\n"; ?> --EXPECTF-- -testing has_dimension +--- testing has_dimension --- bool(true) bool(false) bool(false) -testing property access +--- testing property access --- string(4) "data" Warning: Attempt to read property "textContent" on null in %s on line %d NULL -testing offset not a long +--- testing offset not a long: array --- array(1) { [0]=> string(4) "test" @@ -73,20 +74,20 @@ array(1) { Warning: Attempt to read property "textContent" on null in %s on line %d bool(false) NULL -array(1) { - [0]=> - string(4) "test" -} +--- testing offset not a long: Reference to string --- +string(4) "href" + +Warning: Attempt to read property "textContent" on null in %s on line %d +bool(false) +NULL +--- testing offset not a long: string --- string(4) "test" -bool(true) -string(4) "data" -string(4) "test" -string(4) "test" -bool(true) -string(4) "data" -string(4) "test" -testing read_dimension with null offset + +Warning: Attempt to read property "textContent" on null in %s on line %d +bool(false) +NULL +--- testing read_dimension with null offset --- Cannot access DOMNodeList without offset -testing attribute access +--- testing attribute access --- string(4) "href" ==DONE==