Skip to content

Commit b053192

Browse files
authored
Fix #81429: Handle resizing in SplFixedArray::offsetSet (#7487)
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 #7486 (described in https://bugs.php.net/bug.php?id=81429)
1 parent a247138 commit b053192

File tree

2 files changed

+61
-4
lines changed

2 files changed

+61
-4
lines changed

ext/spl/spl_fixedarray.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -389,10 +389,12 @@ 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]));
394-
}
395-
ZVAL_COPY_DEREF(&intern->array.elements[index], value);
392+
/* Fix #81429 */
393+
zval *ptr = &(intern->array.elements[index]);
394+
zval tmp;
395+
ZVAL_COPY_VALUE(&tmp, ptr);
396+
ZVAL_COPY_DEREF(ptr, value);
397+
zval_ptr_dtor(&tmp);
396398
}
397399
}
398400
/* }}} */
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)