Skip to content

Commit

Permalink
Fix phpGH-14638: null dereference after XML parsing failure.
Browse files Browse the repository at this point in the history
object document is null if the parsing had failed prior to cast to
string.
  • Loading branch information
devnexen committed Jul 1, 2024
1 parent 98cb0be commit 2edf12e
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 24 deletions.
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ PHP NEWS
- Shmop:
. Fixed bug GH-14537 (shmop Windows 11 crashes the process). (nielsdos)

- SimpleXML:
. Fixed bug GH-14638 (null dereference after XML parsing failure).
(David Carlier)

04 Jul 2024, PHP 8.2.21

- Core:
Expand Down
56 changes: 32 additions & 24 deletions ext/simplexml/simplexml.c
Original file line number Diff line number Diff line change
Expand Up @@ -1502,6 +1502,35 @@ static void sxe_add_namespaces(php_sxe_object *sxe, xmlNodePtr node, bool recurs
}
} /* }}} */

static inline void sxe_object_free_iterxpath(php_sxe_object *sxe)
{
if (!Z_ISUNDEF(sxe->iter.data)) {
zval_ptr_dtor(&sxe->iter.data);
ZVAL_UNDEF(&sxe->iter.data);
}

if (sxe->iter.name) {
efree(sxe->iter.name);
sxe->iter.name = NULL;
}
if (sxe->iter.nsprefix) {
efree(sxe->iter.nsprefix);
sxe->iter.nsprefix = NULL;
}
if (!Z_ISUNDEF(sxe->tmp)) {
zval_ptr_dtor(&sxe->tmp);
ZVAL_UNDEF(&sxe->tmp);
}

php_libxml_node_decrement_resource((php_libxml_node_object *)sxe);

if (sxe->xpath) {
xmlXPathFreeContext(sxe->xpath);
sxe->xpath = NULL;
}
}


/* {{{ Return all namespaces in use */
PHP_METHOD(SimpleXMLElement, getNamespaces)
{
Expand Down Expand Up @@ -2156,29 +2185,7 @@ static void sxe_object_free_storage(zend_object *object)

zend_object_std_dtor(&sxe->zo);

if (!Z_ISUNDEF(sxe->iter.data)) {
zval_ptr_dtor(&sxe->iter.data);
ZVAL_UNDEF(&sxe->iter.data);
}

if (sxe->iter.name) {
efree(sxe->iter.name);
sxe->iter.name = NULL;
}
if (sxe->iter.nsprefix) {
efree(sxe->iter.nsprefix);
sxe->iter.nsprefix = NULL;
}
if (!Z_ISUNDEF(sxe->tmp)) {
zval_ptr_dtor(&sxe->tmp);
ZVAL_UNDEF(&sxe->tmp);
}

php_libxml_node_decrement_resource((php_libxml_node_object *)sxe);

if (sxe->xpath) {
xmlXPathFreeContext(sxe->xpath);
}
sxe_object_free_iterxpath(sxe);

if (sxe->properties) {
zend_hash_destroy(sxe->properties);
Expand Down Expand Up @@ -2378,11 +2385,12 @@ PHP_METHOD(SimpleXMLElement, __construct)
PHP_LIBXML_RESTORE_GLOBALS(read_file_or_memory);

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

sxe_object_free_iterxpath(sxe);

sxe->iter.nsprefix = ns_len ? (xmlChar*)estrdup(ns) : NULL;
sxe->iter.isprefix = isprefix;
php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, docp);
Expand Down
25 changes: 25 additions & 0 deletions ext/simplexml/tests/gh14638.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
--TEST--
GH-14638: null pointer dereference on object cast __toString after failed XML parsing
--EXTENSIONS--
simplexml
--CREDITS--
YuanchengJiang
--FILE--
<?php
$xml = '<?xml version="1.0" encoding="utf-8" ?>
<test>
</test>';
$root = simplexml_load_string($xml);
try {
$root->__construct("malformed");
} catch (Exception $e) {
// Intentionally empty
}
echo $root;
?>
--EXPECTF--
Warning: SimpleXMLElement::__construct(): Entity: line 1: parser error : Start tag expected, '<' not found in %s on line %d

Warning: SimpleXMLElement::__construct(): malformed in %s on line %d

Warning: SimpleXMLElement::__construct(): ^ in %s on line %d

0 comments on commit 2edf12e

Please sign in to comment.