Skip to content

Commit 2edf12e

Browse files
committed
Fix GH-14638: null dereference after XML parsing failure.
object document is null if the parsing had failed prior to cast to string.
1 parent 98cb0be commit 2edf12e

File tree

3 files changed

+61
-24
lines changed

3 files changed

+61
-24
lines changed

NEWS

+4
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ PHP NEWS
3131
- Shmop:
3232
. Fixed bug GH-14537 (shmop Windows 11 crashes the process). (nielsdos)
3333

34+
- SimpleXML:
35+
. Fixed bug GH-14638 (null dereference after XML parsing failure).
36+
(David Carlier)
37+
3438
04 Jul 2024, PHP 8.2.21
3539

3640
- Core:

ext/simplexml/simplexml.c

+32-24
Original file line numberDiff line numberDiff line change
@@ -1502,6 +1502,35 @@ static void sxe_add_namespaces(php_sxe_object *sxe, xmlNodePtr node, bool recurs
15021502
}
15031503
} /* }}} */
15041504

1505+
static inline void sxe_object_free_iterxpath(php_sxe_object *sxe)
1506+
{
1507+
if (!Z_ISUNDEF(sxe->iter.data)) {
1508+
zval_ptr_dtor(&sxe->iter.data);
1509+
ZVAL_UNDEF(&sxe->iter.data);
1510+
}
1511+
1512+
if (sxe->iter.name) {
1513+
efree(sxe->iter.name);
1514+
sxe->iter.name = NULL;
1515+
}
1516+
if (sxe->iter.nsprefix) {
1517+
efree(sxe->iter.nsprefix);
1518+
sxe->iter.nsprefix = NULL;
1519+
}
1520+
if (!Z_ISUNDEF(sxe->tmp)) {
1521+
zval_ptr_dtor(&sxe->tmp);
1522+
ZVAL_UNDEF(&sxe->tmp);
1523+
}
1524+
1525+
php_libxml_node_decrement_resource((php_libxml_node_object *)sxe);
1526+
1527+
if (sxe->xpath) {
1528+
xmlXPathFreeContext(sxe->xpath);
1529+
sxe->xpath = NULL;
1530+
}
1531+
}
1532+
1533+
15051534
/* {{{ Return all namespaces in use */
15061535
PHP_METHOD(SimpleXMLElement, getNamespaces)
15071536
{
@@ -2156,29 +2185,7 @@ static void sxe_object_free_storage(zend_object *object)
21562185

21572186
zend_object_std_dtor(&sxe->zo);
21582187

2159-
if (!Z_ISUNDEF(sxe->iter.data)) {
2160-
zval_ptr_dtor(&sxe->iter.data);
2161-
ZVAL_UNDEF(&sxe->iter.data);
2162-
}
2163-
2164-
if (sxe->iter.name) {
2165-
efree(sxe->iter.name);
2166-
sxe->iter.name = NULL;
2167-
}
2168-
if (sxe->iter.nsprefix) {
2169-
efree(sxe->iter.nsprefix);
2170-
sxe->iter.nsprefix = NULL;
2171-
}
2172-
if (!Z_ISUNDEF(sxe->tmp)) {
2173-
zval_ptr_dtor(&sxe->tmp);
2174-
ZVAL_UNDEF(&sxe->tmp);
2175-
}
2176-
2177-
php_libxml_node_decrement_resource((php_libxml_node_object *)sxe);
2178-
2179-
if (sxe->xpath) {
2180-
xmlXPathFreeContext(sxe->xpath);
2181-
}
2188+
sxe_object_free_iterxpath(sxe);
21822189

21832190
if (sxe->properties) {
21842191
zend_hash_destroy(sxe->properties);
@@ -2378,11 +2385,12 @@ PHP_METHOD(SimpleXMLElement, __construct)
23782385
PHP_LIBXML_RESTORE_GLOBALS(read_file_or_memory);
23792386

23802387
if (!docp) {
2381-
((php_libxml_node_object *)sxe)->document = NULL;
23822388
zend_throw_exception(zend_ce_exception, "String could not be parsed as XML", 0);
23832389
RETURN_THROWS();
23842390
}
23852391

2392+
sxe_object_free_iterxpath(sxe);
2393+
23862394
sxe->iter.nsprefix = ns_len ? (xmlChar*)estrdup(ns) : NULL;
23872395
sxe->iter.isprefix = isprefix;
23882396
php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, docp);

ext/simplexml/tests/gh14638.phpt

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
GH-14638: null pointer dereference on object cast __toString after failed XML parsing
3+
--EXTENSIONS--
4+
simplexml
5+
--CREDITS--
6+
YuanchengJiang
7+
--FILE--
8+
<?php
9+
$xml = '<?xml version="1.0" encoding="utf-8" ?>
10+
<test>
11+
</test>';
12+
$root = simplexml_load_string($xml);
13+
try {
14+
$root->__construct("malformed");
15+
} catch (Exception $e) {
16+
// Intentionally empty
17+
}
18+
echo $root;
19+
?>
20+
--EXPECTF--
21+
Warning: SimpleXMLElement::__construct(): Entity: line 1: parser error : Start tag expected, '<' not found in %s on line %d
22+
23+
Warning: SimpleXMLElement::__construct(): malformed in %s on line %d
24+
25+
Warning: SimpleXMLElement::__construct(): ^ in %s on line %d

0 commit comments

Comments
 (0)