From b5834c12d4cb06b9ba9ae9e2b62eea36862f1ba4 Mon Sep 17 00:00:00 2001
From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
Date: Wed, 11 Sep 2024 19:02:07 +0200
Subject: [PATCH] Fix GH-15837: Segmentation fault in ext/simplexml/simplexml.c
We should check if the iterator data is still valid, because if it
isn't, then the type info is UNDEF, but the pointer value may be
dangling.
Closes GH-15841.
---
NEWS | 4 ++++
ext/simplexml/simplexml.c | 5 +++++
ext/simplexml/tests/gh15837.phpt | 30 ++++++++++++++++++++++++++++++
3 files changed, 39 insertions(+)
create mode 100644 ext/simplexml/tests/gh15837.phpt
diff --git a/NEWS b/NEWS
index b5454bffccd..21ab2923e23 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,10 @@ PHP NEWS
. Fixed regression where signs after the first one were ignored while parsing
a signed integer, with the DateTimeInterface::modify() function. (Derick)
+- SimpleXML:
+ . Fixed bug GH-15837 (Segmentation fault in ext/simplexml/simplexml.c).
+ (nielsdos)
+
- SOAP:
. Fixed bug #62900 (Wrong namespace on xsd import error message). (nielsdos)
diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c
index 6bcb9edcffa..21cd5cdb4c7 100644
--- a/ext/simplexml/simplexml.c
+++ b/ext/simplexml/simplexml.c
@@ -2547,6 +2547,11 @@ static void php_sxe_iterator_current_key(zend_object_iterator *iter, zval *key)
{
php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
zval *curobj = &iterator->sxe->iter.data;
+ if (Z_ISUNDEF_P(curobj)) {
+ ZVAL_NULL(key);
+ return;
+ }
+
php_sxe_object *intern = Z_SXEOBJ_P(curobj);
xmlNodePtr curnode = NULL;
diff --git a/ext/simplexml/tests/gh15837.phpt b/ext/simplexml/tests/gh15837.phpt
new file mode 100644
index 00000000000..302db064ee0
--- /dev/null
+++ b/ext/simplexml/tests/gh15837.phpt
@@ -0,0 +1,30 @@
+--TEST--
+GH-15837 (Segmentation fault in ext/simplexml/simplexml.c)
+--CREDITS--
+YuanchengJiang
+--FILE--
+
+
+
+
+
+
+
+
+EOF;
+$sxe = new SimpleXMLIterator($xml);
+$rit = new RecursiveIteratorIterator($sxe, RecursiveIteratorIterator::LEAVES_ONLY);
+foreach ($rit as $child) {
+ $ancestry = $child->xpath('ancestor-or-self::*');
+ // Exhaust internal iterator
+ foreach ($ancestry as $ancestor) {
+ }
+}
+var_dump($rit->valid());
+var_dump($rit->key());
+?>
+--EXPECT--
+bool(false)
+NULL