Skip to content

Commit 5c12493

Browse files
committed
Fix GH-16292: Segmentation fault in ext/xmlreader/php_xmlreader.c:1282
3 issues: 1) RETURN_NULL() was used via the macro NODE_GET_OBJ(), but the function returns false on failure and cannot return null according to its stub. 2) The struct layout of the different implementors of libxml only guarantees overlap between the node pointer and the document reference, so accessing the std zend_object may not work. 3) DOC_GET_OBJ() wasn't using ZSTR_VAL(). Closes GH-16307.
1 parent 5f58240 commit 5c12493

File tree

4 files changed

+46
-9
lines changed

4 files changed

+46
-9
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? ????, PHP 8.2.26
44

5+
- XMLReader:
6+
. Fixed bug GH-16292 (Segmentation fault in ext/xmlreader/php_xmlreader.c).
7+
(nielsdos)
58

69
24 Oct 2024, PHP 8.2.25
710

ext/dom/xml_common.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,21 +60,23 @@ PHP_DOM_EXPORT xmlNodePtr dom_object_get_node(dom_object *obj);
6060
(const xmlChar *) "http://www.w3.org/2000/xmlns/"
6161

6262
#define NODE_GET_OBJ(__ptr, __id, __prtype, __intern) { \
63-
__intern = Z_LIBXML_NODE_P(__id); \
63+
zval *__zv = (__id); \
64+
__intern = Z_LIBXML_NODE_P(__zv); \
6465
if (__intern->node == NULL || !(__ptr = (__prtype)__intern->node->node)) { \
65-
php_error_docref(NULL, E_WARNING, "Couldn't fetch %s", \
66-
ZSTR_VAL(__intern->std.ce->name));\
67-
RETURN_NULL();\
66+
php_error_docref(NULL, E_WARNING, "Couldn't fetch %s", \
67+
ZSTR_VAL(Z_OBJCE_P(__zv)->name));\
68+
RETURN_NULL();\
6869
} \
6970
}
7071

7172
#define DOC_GET_OBJ(__ptr, __id, __prtype, __intern) { \
72-
__intern = Z_LIBXML_NODE_P(__id); \
73+
zval *__zv = (__id); \
74+
__intern = Z_LIBXML_NODE_P(__zv); \
7375
if (__intern->document != NULL) { \
7476
if (!(__ptr = (__prtype)__intern->document->ptr)) { \
75-
php_error_docref(NULL, E_WARNING, "Couldn't fetch %s", __intern->std.ce->name);\
76-
RETURN_NULL();\
77-
} \
77+
php_error_docref(NULL, E_WARNING, "Couldn't fetch %s", ZSTR_VAL(Z_OBJCE_P(__zv)->name));\
78+
RETURN_NULL();\
79+
} \
7880
} \
7981
}
8082

ext/xmlreader/php_xmlreader.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1122,7 +1122,13 @@ PHP_METHOD(XMLReader, expand)
11221122
}
11231123

11241124
if (basenode != NULL) {
1125-
NODE_GET_OBJ(node, basenode, xmlNodePtr, domobj);
1125+
/* Note: cannot use NODE_GET_OBJ here because of the wrong return type */
1126+
domobj = Z_LIBXML_NODE_P(basenode);
1127+
if (UNEXPECTED(domobj->node == NULL || domobj->node->node == NULL)) {
1128+
php_error_docref(NULL, E_WARNING, "Couldn't fetch %s", ZSTR_VAL(Z_OBJCE_P(basenode)->name));
1129+
RETURN_FALSE;
1130+
}
1131+
node = domobj->node->node;
11261132
docp = node->doc;
11271133
}
11281134

ext/xmlreader/tests/gh16292.phpt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
GH-16292 (Segmentation fault in ext/xmlreader/php_xmlreader.c:1282)
3+
--EXTENSIONS--
4+
dom
5+
xmlreader
6+
--FILE--
7+
<?php
8+
9+
$character_data = new DOMCharacterData();
10+
$xmlstring = '<?xml version="1.0" encoding="UTF-8"?>
11+
<books><book>new book</book></books>';
12+
$reader = new XMLReader();
13+
$reader->XML($xmlstring);
14+
while ($reader->read()) {
15+
if ($reader->localName == "book") {
16+
var_dump($reader->expand($character_data));
17+
}
18+
}
19+
20+
?>
21+
--EXPECTF--
22+
Warning: XMLReader::expand(): Couldn't fetch DOMCharacterData in %s on line %d
23+
bool(false)
24+
25+
Warning: XMLReader::expand(): Couldn't fetch DOMCharacterData in %s on line %d
26+
bool(false)

0 commit comments

Comments
 (0)