Skip to content

Commit 71f2e71

Browse files
committed
Fix phpGH-12231: SimpleXML xpath should warn when returning other return types than node lists
1 parent e954bf6 commit 71f2e71

File tree

4 files changed

+57
-3
lines changed

4 files changed

+57
-3
lines changed

UPGRADING

+5
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ PHP 8.5 UPGRADE NOTES
8282
. A ValueError is now thrown when trying to set a cursor name that is too
8383
long on a PDOStatement resulting from the Firebird driver.
8484

85+
- SimpleXML:
86+
- Passing an XPath expression that returns something other than a node set
87+
to SimpleXMLElement::xpath() will now emit a warning and return false,
88+
instead of silently failing and returning an empty array.
89+
8590
- SPL:
8691
. ArrayObject no longer accepts enums, as modifying the $name or $value
8792
properties can break engine assumptions.

ext/simplexml/simplexml.c

+22
Original file line numberDiff line numberDiff line change
@@ -1215,6 +1215,21 @@ static int sxe_objects_compare(zval *object1, zval *object2) /* {{{ */
12151215
}
12161216
/* }}} */
12171217

1218+
static const char *sxe_get_object_type_name(xmlXPathObjectType type)
1219+
{
1220+
switch (type) {
1221+
case XPATH_BOOLEAN: return "bool";
1222+
case XPATH_NUMBER: return "number";
1223+
case XPATH_STRING: return "string";
1224+
#ifdef LIBXML_XPTR_LOCS_ENABLED
1225+
case XPATH_POINT: return "point";
1226+
case XPATH_RANGE: return "range";
1227+
case XPATH_LOCATIONSET: return "location set";
1228+
#endif
1229+
default: return "undefined";
1230+
}
1231+
}
1232+
12181233
/* {{{ Runs XPath query on the XML data */
12191234
PHP_METHOD(SimpleXMLElement, xpath)
12201235
{
@@ -1271,6 +1286,13 @@ PHP_METHOD(SimpleXMLElement, xpath)
12711286
RETURN_FALSE;
12721287
}
12731288

1289+
if (UNEXPECTED(retval->type != XPATH_NODESET)) {
1290+
php_error_docref(NULL, E_WARNING, "XPath expression must return a node set, %s returned",
1291+
sxe_get_object_type_name(retval->type));
1292+
xmlXPathFreeObject(retval);
1293+
RETURN_FALSE;
1294+
}
1295+
12741296
result = retval->nodesetval;
12751297

12761298
if (result != NULL) {

ext/simplexml/tests/008.phpt

+4-3
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@ array(1) {
3939
}
4040
}
4141
}
42-
array(0) {
43-
}
4442

45-
Warning: SimpleXMLElement::xpath(): Invalid expression in %s on line %d%A
43+
Warning: SimpleXMLElement::xpath(): XPath expression must return a node set, number returned in %s on line %d
44+
bool(false)
45+
46+
Warning: SimpleXMLElement::xpath(): Invalid expression in %s on line %d
4647
bool(false)

ext/simplexml/tests/gh12231.phpt

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
GH-12231 (SimpleXML xpath should warn when returning other return types than node lists)
3+
--EXTENSIONS--
4+
simplexml
5+
--FILE--
6+
<?php
7+
8+
$xml = "<container><foo/><foo/></container>";
9+
$sxe = simplexml_load_string($xml);
10+
11+
var_dump($sxe->xpath("count(//foo)"));
12+
var_dump($sxe->xpath("string(//foo)"));
13+
var_dump($sxe->xpath("boolean(//foo)"));
14+
var_dump(count($sxe->xpath("//foo")));
15+
16+
?>
17+
--EXPECTF--
18+
Warning: SimpleXMLElement::xpath(): XPath expression must return a node set, number returned in %s on line %d
19+
bool(false)
20+
21+
Warning: SimpleXMLElement::xpath(): XPath expression must return a node set, string returned in %s on line %d
22+
bool(false)
23+
24+
Warning: SimpleXMLElement::xpath(): XPath expression must return a node set, bool returned in %s on line %d
25+
bool(false)
26+
int(2)

0 commit comments

Comments
 (0)