Skip to content

Commit 62bec0e

Browse files
committed
Fixed bug #79784
The fix here is essentially the same as for bug #78598, just for the undefined variable notice, rather than the undefined index one.
1 parent b0014ad commit 62bec0e

File tree

3 files changed

+38
-3
lines changed

3 files changed

+38
-3
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ PHP NEWS
2121
(Nikita)
2222
. Fixed bug #78598 (Changing array during undef index RW error segfaults).
2323
(Nikita)
24+
. Fixed bug #79784 (Use after free if changing array during undef var during
25+
array write fetch). (Nikita)
2426

2527
- Fileinfo:
2628
. Fixed bug #79756 (finfo_file crash (FILEINFO_MIME)). (cmb)

Zend/tests/bug79784.phpt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
Bug #79784: Use after free if changing array during undef var during array write fetch
3+
--FILE--
4+
<?php
5+
set_error_handler(function () {
6+
$GLOBALS['a'] = null;
7+
});
8+
9+
$a[$c] = 'x' ;
10+
var_dump($a);
11+
$a[$c] .= 'x' ;
12+
var_dump($a);
13+
$a[$c][$c] = 'x' ;
14+
var_dump($a);
15+
16+
?>
17+
--EXPECT--
18+
NULL
19+
NULL
20+
NULL

Zend/zend_execute.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2067,12 +2067,25 @@ static ZEND_COLD void zend_binary_assign_op_dim_slow(zval *container, zval *dim
20672067
FREE_OP(free_op_data1);
20682068
}
20692069

2070-
static zend_never_inline zend_uchar slow_index_convert(const zval *dim, zend_value *value EXECUTE_DATA_DC)
2070+
static zend_never_inline zend_uchar slow_index_convert(HashTable *ht, const zval *dim, zend_value *value EXECUTE_DATA_DC)
20712071
{
20722072
switch (Z_TYPE_P(dim)) {
2073-
case IS_UNDEF:
2073+
case IS_UNDEF: {
2074+
/* The array may be destroyed while throwing the notice.
2075+
* Temporarily increase the refcount to detect this situation. */
2076+
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
2077+
GC_ADDREF(ht);
2078+
}
20742079
ZVAL_UNDEFINED_OP2();
2080+
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
2081+
zend_array_destroy(ht);
2082+
return IS_NULL;
2083+
}
2084+
if (EG(exception)) {
2085+
return IS_NULL;
2086+
}
20752087
/* break missing intentionally */
2088+
}
20762089
case IS_NULL:
20772090
value->str = ZSTR_EMPTY_ALLOC();
20782091
return IS_STRING;
@@ -2182,7 +2195,7 @@ static zend_always_inline zval *zend_fetch_dimension_address_inner(HashTable *ht
21822195
goto try_again;
21832196
} else {
21842197
zend_value val;
2185-
zend_uchar t = slow_index_convert(dim, &val EXECUTE_DATA_CC);
2198+
zend_uchar t = slow_index_convert(ht, dim, &val EXECUTE_DATA_CC);
21862199

21872200
if (t == IS_STRING) {
21882201
offset_key = val.str;

0 commit comments

Comments
 (0)