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 47afabe48ba..aecc6027f7f 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2920,9 +2920,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 8ab23adf9bd..98696bdf951 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2410,9 +2410,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; } @@ -7735,9 +7737,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; } @@ -12961,9 +12965,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; } @@ -30605,9 +30611,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; }