diff --git a/Zend/tests/bug65372.phpt b/Zend/tests/bug65372.phpt new file mode 100644 index 00000000000..50fc2dbb1b2 --- /dev/null +++ b/Zend/tests/bug65372.phpt @@ -0,0 +1,40 @@ +--TEST-- +Bug #65372 (Segfault in gc_zval_possible_root when return reference fails) +--FILE-- +Manager = $this; + } + + public static function &GetCurrent() + { + return ChildClass::Get(); + } + + public static function &Get() + { + return parent::Get(); + } +} + +$staff = ChildClass::GetCurrent(); +?> +--EXPECTF-- +Notice: Only variable references should be returned by reference in %sbug65372.php on line 30 diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 6173e8bff9d..ba5f31b1fb0 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2925,9 +2925,11 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY) } else if (EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); if (EG(return_value_ptr_ptr)) { - retval_ptr = *retval_ptr_ptr; - *EG(return_value_ptr_ptr) = retval_ptr; - Z_ADDREF_P(retval_ptr); + zval *ret; + + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, *retval_ptr_ptr); + *EG(return_value_ptr_ptr) = ret; } break; } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 6cec94608a0..135a4caec00 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2417,9 +2417,11 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND } else if (EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); if (EG(return_value_ptr_ptr)) { - retval_ptr = *retval_ptr_ptr; - *EG(return_value_ptr_ptr) = retval_ptr; - Z_ADDREF_P(retval_ptr); + zval *ret; + + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, *retval_ptr_ptr); + *EG(return_value_ptr_ptr) = ret; } break; } @@ -7742,9 +7744,11 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE } else if (EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); if (EG(return_value_ptr_ptr)) { - retval_ptr = *retval_ptr_ptr; - *EG(return_value_ptr_ptr) = retval_ptr; - Z_ADDREF_P(retval_ptr); + zval *ret; + + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, *retval_ptr_ptr); + *EG(return_value_ptr_ptr) = ret; } break; } @@ -12968,9 +12972,11 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE } else if (EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); if (EG(return_value_ptr_ptr)) { - retval_ptr = *retval_ptr_ptr; - *EG(return_value_ptr_ptr) = retval_ptr; - Z_ADDREF_P(retval_ptr); + zval *ret; + + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, *retval_ptr_ptr); + *EG(return_value_ptr_ptr) = ret; } break; } @@ -30624,9 +30630,11 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER } else if (EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); if (EG(return_value_ptr_ptr)) { - retval_ptr = *retval_ptr_ptr; - *EG(return_value_ptr_ptr) = retval_ptr; - Z_ADDREF_P(retval_ptr); + zval *ret; + + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, *retval_ptr_ptr); + *EG(return_value_ptr_ptr) = ret; } break; }