Skip to content

Commit 6d5ae64

Browse files
committed
Fix ASSIGN_DIM to NEXT with rc=1 reference value
The reference wrapper was destroyed while value still pointed into it and was later used to assign the ASSIGN_DIM return value. This could be fixed either by moving the return value assignment earlier, or by working with the value that has been stored in the array. I'm going with the latter here, because that matches what the non-NEXT codepath does via assign_to_variable more closely. Fixes oss-fuzz #36807.
1 parent 70872dd commit 6d5ae64

File tree

3 files changed

+112
-99
lines changed

3 files changed

+112
-99
lines changed

Zend/tests/assign_dim_ref_free.phpt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
--TEST--
2+
Assigning rc=1 reference to next dim
3+
--FILE--
4+
<?php
5+
var_dump($ary[] = [&$x] = $x);
6+
var_dump($x);
7+
?>
8+
--EXPECT--
9+
array(1) {
10+
[0]=>
11+
&NULL
12+
}
13+
NULL

Zend/zend_vm_def.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2527,8 +2527,8 @@ ZEND_VM_C_LABEL(try_assign_dim_array):
25272527
if (OP_DATA_TYPE == IS_CV || OP_DATA_TYPE == IS_VAR) {
25282528
ZVAL_DEREF(value);
25292529
}
2530-
variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value);
2531-
if (UNEXPECTED(variable_ptr == NULL)) {
2530+
value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value);
2531+
if (UNEXPECTED(value == NULL)) {
25322532
zend_cannot_add_element();
25332533
ZEND_VM_C_GOTO(assign_dim_error);
25342534
} else if (OP_DATA_TYPE == IS_CV) {
@@ -2537,7 +2537,7 @@ ZEND_VM_C_LABEL(try_assign_dim_array):
25372537
}
25382538
} else if (OP_DATA_TYPE == IS_VAR) {
25392539
zval *free_op_data = EX_VAR((opline+1)->op1.var);
2540-
if (value != free_op_data) {
2540+
if (Z_ISREF_P(free_op_data)) {
25412541
if (Z_REFCOUNTED_P(value)) {
25422542
Z_ADDREF_P(value);
25432543
}

0 commit comments

Comments
 (0)