Skip to content

Commit 2d66840

Browse files
committed
Fix #80663: Recursive SplFixedArray::setSize() may cause double-free
We address the `::setSize(0)` case by setting `array->element = NULL` and `array->size = 0` before we destroy the elements. Co-authored-by: Tyson Andre <[email protected]> Closes GH-7503.
1 parent 2c3dfe5 commit 2d66840

File tree

3 files changed

+32
-8
lines changed

3 files changed

+32
-8
lines changed

NEWS

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,15 @@ PHP NEWS
2020
- PCRE:
2121
. Fixed bug #81424 (PCRE2 10.35 JIT performance regression). (cmb)
2222

23+
- SPL:
24+
. Fixed bug #80663 (Recursive SplFixedArray::setSize() may cause double-free).
25+
(cmb, Nikita, Tyson Andre)
26+
2327
- XML:
2428
. Fixed bug #70962 (XML_OPTION_SKIP_WHITE strips embedded whitespace).
2529
(Aliaksandr Bystry, cmb)
2630

27-
23 Dep 2021, PHP 7.4.24
31+
23 Sep 2021, PHP 7.4.24
2832

2933
- Core:
3034
. Fixed bug #81302 (Stream position after stream filter removed). (cmb)

ext/spl/spl_fixedarray.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,20 @@ static void spl_fixedarray_resize(spl_fixedarray *array, zend_long size) /* {{{
106106

107107
/* clearing the array */
108108
if (size == 0) {
109-
zend_long i;
110-
111-
for (i = 0; i < array->size; i++) {
112-
zval_ptr_dtor(&(array->elements[i]));
113-
}
109+
if (array->elements != NULL) {
110+
zend_long i;
111+
zval *elements = array->elements;
112+
zend_long old_size = array->size;
114113

115-
if (array->elements) {
116-
efree(array->elements);
117114
array->elements = NULL;
115+
array->size = 0;
116+
117+
for (i = 0; i < old_size; i++) {
118+
zval_ptr_dtor(&(elements[i]));
119+
}
120+
121+
efree(elements);
122+
return;
118123
}
119124
} else if (size > array->size) {
120125
array->elements = safe_erealloc(array->elements, size, sizeof(zval), 0);

ext/spl/tests/bug80663.phpt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--TEST--
2+
Bug #80663 (Recursive SplFixedArray::setSize() may cause double-free)
3+
--FILE--
4+
<?php
5+
class InvalidDestructor {
6+
public function __destruct() {
7+
$GLOBALS['obj']->setSize(0);
8+
}
9+
}
10+
11+
$obj = new SplFixedArray(1000);
12+
$obj[0] = new InvalidDestructor();
13+
$obj->setSize(0);
14+
?>
15+
--EXPECT--

0 commit comments

Comments
 (0)