From ce9169e360701ea3b1ab2366171c24d4de5e78e3 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Fri, 2 Aug 2013 18:37:15 +0800 Subject: [PATCH 1/2] Fixed bug Bug #65372 (Segfault in gc_zval_possible_root when return reference fails) --- NEWS | 2 ++ Zend/tests/bug65372.phpt | 40 ++++++++++++++++++++++++++++++++++++++++ Zend/zend_vm_def.h | 8 +++++--- Zend/zend_vm_execute.h | 32 ++++++++++++++++++++------------ 4 files changed, 67 insertions(+), 15 deletions(-) create mode 100644 Zend/tests/bug65372.phpt diff --git a/NEWS b/NEWS index d480e3d669e..02186150b5f 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ PHP NEWS ?? ??? 2013, PHP 5.4.19 - Core. + . Fixed bug #65372 (Segfault in gc_zval_possible_root when return reference + fails). (Laruence) . Fixed bug #65304 (Use of max int in array_sum). (Laruence) . Fixed bug #65291 (get_defined_constants() causes PHP to crash in a very limited case). (Arpad) 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 7346078fb37..83e40b514a4 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2910,9 +2910,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 6e466e40b17..339e34bc40c 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2324,9 +2324,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; } @@ -6743,9 +6745,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; } @@ -11055,9 +11059,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; } @@ -27030,9 +27036,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; } From 6f1a762fab8dc42b0d2190cb3cbf89da8e0903e5 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Fri, 2 Aug 2013 18:39:41 +0800 Subject: [PATCH 2/2] Update NEWS --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index 6fe5c3a763c..82d4ca15729 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ PHP NEWS ?? ??? 2013, PHP 5.5.2 - Core: + . Fixed bug #65372 (Segfault in gc_zval_possible_root when return reference + fails). (Laruence) . Fixed value of FILTER_SANITIZE_FULL_SPECIAL_CHARS constant (previously was erroneously set to FILTER_SANITIZE_SPECIAL_CHARS value). (Andrey avp200681 gmail com).