Commit cb3dc62fd90 for php.net
commit cb3dc62fd90dc2660296d9261c022cd7de52253f
Author: David Carlier <devnexen@gmail.com>
Date: Thu Apr 30 19:17:42 2026 +0100
ext/spl: Fix SplFixedArray::setSize leak when destructor grows during clear.
close GH-21920
diff --git a/NEWS b/NEWS
index 3dbfb272495..35f34920e62 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,10 @@ PHP NEWS
- OpenSSL:
. Fix compatibility issues with OpenSSL 4.0. (jordikroon, Remi)
+- SPL:
+ . Fix SplFixedArray::setSize leak when destructor grows during clear.
+ (David Carlier)
+
- Standard:
. Fixed bug GH-21689 (version_compare() incorrectly handles versions ending
with a dot). (timwolla)
diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c
index 84adbe2233b..8f8108e2f90 100644
--- a/ext/spl/spl_fixedarray.c
+++ b/ext/spl/spl_fixedarray.c
@@ -172,18 +172,18 @@ static void spl_fixedarray_resize(spl_fixedarray *array, zend_long size)
return;
}
- /* first initialization */
- if (array->size == 0) {
- spl_fixedarray_init(array, size);
- return;
- }
-
if (UNEXPECTED(array->cached_resize >= 0)) {
/* We're already resizing, so just remember the desired size.
* The resize will happen later. */
array->cached_resize = size;
return;
}
+ /* first initialization */
+ if (array->size == 0) {
+ spl_fixedarray_init(array, size);
+ return;
+ }
+
array->cached_resize = size;
/* clearing the array */
diff --git a/ext/spl/tests/SplFixedArray_setSize_destruct_grow_during_clear.phpt b/ext/spl/tests/SplFixedArray_setSize_destruct_grow_during_clear.phpt
new file mode 100644
index 00000000000..f0982364afa
--- /dev/null
+++ b/ext/spl/tests/SplFixedArray_setSize_destruct_grow_during_clear.phpt
@@ -0,0 +1,28 @@
+--TEST--
+SplFixedArray::setSize: grow re-entrantly during clear (setSize(0))
+--FILE--
+<?php
+class Reentrant {
+ public ?SplFixedArray $arr = null;
+ public function __destruct() {
+ if ($this->arr !== null) {
+ $this->arr->setSize(5);
+ }
+ }
+}
+
+$arr = new SplFixedArray(2);
+$r = new Reentrant();
+$r->arr = $arr;
+$arr[0] = $r;
+unset($r);
+$arr[1] = "tail";
+
+$arr->setSize(0);
+echo "size: ", $arr->getSize(), "\n";
+$arr[0] = "ok";
+var_dump($arr[0]);
+?>
+--EXPECT--
+size: 5
+string(2) "ok"