Skip to content

Commit bec9f7c

Browse files
committed
Fix #81429: Handle resizing in SplFixedArray::offsetSet
offsetSet did not account for the fact that the array may no longer exist after the field is overwritten. This fixes that. Add test of resizing both to the empty array and a smaller array - there should be no valgrind warnings with a proper fix. Alternate approach to php#7486 (described in https://bugs.php.net/bug.php?id=81429)
1 parent 95a943e commit bec9f7c

File tree

2 files changed

+62
-3
lines changed

2 files changed

+62
-3
lines changed

ext/spl/spl_fixedarray.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -389,10 +389,14 @@ static inline void spl_fixedarray_object_write_dimension_helper(spl_fixedarray_o
389389
zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0);
390390
return;
391391
} else {
392-
if (!Z_ISUNDEF(intern->array.elements[index])) {
393-
zval_ptr_dtor(&(intern->array.elements[index]));
392+
/* Fix #81429 */
393+
zval *const ptr = &(intern->array.elements[index]);
394+
zval tmp;
395+
ZVAL_COPY_VALUE(&tmp, ptr);
396+
ZVAL_COPY_DEREF(ptr, value);
397+
if (!Z_ISUNDEF(tmp)) {
398+
zval_ptr_dtor(&tmp);
394399
}
395-
ZVAL_COPY_DEREF(&intern->array.elements[index], value);
396400
}
397401
}
398402
/* }}} */
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
--TEST--
2+
SplFixedArray::setSize in offsetSet destructor (#81429)
3+
--FILE--
4+
<?php
5+
$values = new SplFixedArray(1);
6+
$values->offsetSet(0, new HasDestructor());
7+
$values->offsetSet(0, false);
8+
echo "Done\n";
9+
10+
class HasDestructor {
11+
public function __destruct() {
12+
global $values;
13+
var_dump($values);
14+
$values->setSize($values->getSize() - 1);
15+
var_dump($values);
16+
}
17+
}
18+
19+
$values->setSize(5);
20+
$values->offsetSet(4, new HasDestructor());
21+
echo "Done\n";
22+
--EXPECT--
23+
object(SplFixedArray)#1 (1) {
24+
[0]=>
25+
bool(false)
26+
}
27+
object(SplFixedArray)#1 (1) {
28+
[0]=>
29+
bool(false)
30+
}
31+
Done
32+
Done
33+
object(SplFixedArray)#1 (5) {
34+
[0]=>
35+
NULL
36+
[1]=>
37+
NULL
38+
[2]=>
39+
NULL
40+
[3]=>
41+
NULL
42+
[4]=>
43+
object(HasDestructor)#2 (0) {
44+
}
45+
}
46+
object(SplFixedArray)#1 (4) {
47+
[0]=>
48+
NULL
49+
[1]=>
50+
NULL
51+
[2]=>
52+
NULL
53+
[3]=>
54+
NULL
55+
}

0 commit comments

Comments
 (0)