diff --git a/Zend/tests/bug70262.phpt b/Zend/tests/bug70262.phpt index 42e7fe0c165..7e285e8002f 100644 --- a/Zend/tests/bug70262.phpt +++ b/Zend/tests/bug70262.phpt @@ -2,33 +2,29 @@ Bug #70262 (Accessing array crashes) --FILE-- arguments = $arg; + +$array = array(); +$array[] = 1; // make this not immutable + +$extra = $array; // make the refcount == 2 + +class A { + public function getObj($array) { + $obj = new Stdclass; + $obj->arr = $array; // make the refcount == 3; + return $obj; } } -function & a(&$arg) { - $c = new C($arg); - $arg[] = $c; - return $c; -} +$a = new A; +$a->getObj($array) //use function call to get a refcount == 1 IS_VAR object + ->arr // FETCH_OBJ_W will EXTRACT_ZVAL_PTR because getObj() result a refcount == 1 object (READY_TO_DESTROY) + [0] = "test"; //We will get a refcount == 3 array (not a IS_INDIRCT) in ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER -function c($arr) { - a($arr)->arguments[0] = "bad"; -} - -$arr = array(); -$arr[] = "foo"; -$arr[] = "bar"; -c($arr); -var_dump($arr); +var_dump($array); ?> --EXPECT-- -array(2) { +array(1) { [0]=> - string(3) "foo" - [1]=> - string(3) "bar" + int(1) } diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index c3d8990940c..dbf5c5086d5 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -480,13 +480,8 @@ static zend_always_inline zval *_get_zval_ptr_ptr_var(uint32_t var, const zend_e if (EXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) { *should_free = NULL; ret = Z_INDIRECT_P(ret); - } else if (!Z_REFCOUNTED_P(ret)) { - *should_free = ret; /* immutable array may be converted to regular */ - } else if (Z_REFCOUNT_P(ret) == 1) { - *should_free = ret; } else { - *should_free = NULL; - Z_DELREF_P(ret); + *should_free = ret; /* immutable array may be converted to regular */ } return ret; } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 9ee27d84d07..eceed13bae5 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -7250,11 +7250,11 @@ ZEND_VM_HANDLER(156, ZEND_SEPARATE, VAR, UNUSED) zval *var_ptr; var_ptr = EX_VAR(opline->op1.var); - if (UNEXPECTED(Z_ISREF_P(var_ptr))) { - if (UNEXPECTED(Z_REFCOUNT_P(var_ptr) == 1)) { - ZVAL_UNREF(var_ptr); - } - } else if (Z_COPYABLE_P(var_ptr) && Z_REFCOUNT_P(var_ptr) > 1) { + if (Z_TYPE_P(var_ptr) != IS_OBJECT && + !Z_ISREF_P(var_ptr) && + Z_REFCOUNTED_P(var_ptr) && + Z_REFCOUNT_P(var_ptr) > 1) { + Z_DELREF_P(var_ptr); ZVAL_DUP(EX_VAR(opline->op1.var), var_ptr); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 8dd8881299e..cf1c7a1e8fb 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -19444,11 +19444,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDL zval *var_ptr; var_ptr = EX_VAR(opline->op1.var); - if (UNEXPECTED(Z_ISREF_P(var_ptr))) { - if (UNEXPECTED(Z_REFCOUNT_P(var_ptr) == 1)) { - ZVAL_UNREF(var_ptr); - } - } else if (Z_COPYABLE_P(var_ptr) && Z_REFCOUNT_P(var_ptr) > 1) { + if (Z_TYPE_P(var_ptr) != IS_OBJECT && + !Z_ISREF_P(var_ptr) && + Z_REFCOUNTED_P(var_ptr) && + Z_REFCOUNT_P(var_ptr) > 1) { + Z_DELREF_P(var_ptr); ZVAL_DUP(EX_VAR(opline->op1.var), var_ptr); }