From a98e5c674f268c0e3973bc540cf58f9b5c348a5b Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 27 Jul 2006 10:44:03 +0000 Subject: [PATCH] Fixed bug #38234 (Exception in __clone makes memory leak) --- NEWS | 1 + Zend/tests/bug38234.phpt | 18 ++++++++++++++++++ Zend/zend_vm_def.h | 8 ++++++-- Zend/zend_vm_execute.h | 40 ++++++++++++++++++++++++++++++---------- 4 files changed, 55 insertions(+), 12 deletions(-) create mode 100755 Zend/tests/bug38234.phpt diff --git a/NEWS b/NEWS index 3cc557df48..1caa3b766a 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,7 @@ PHP NEWS . Fixed bug #37564 (AES privacy encryption not possible due to net-snmp 5.2 compatibility issue). (Patch: scott dot moynes+php at gmail dot com) +- Fixed bug #38234 (Exception in __clone makes memory leak). (Dmitry, Nuno) - Fixed bug #38220 (Crash on some object operations). (Dmitry) - Fixed bug #38217 (ReflectionClass::newInstanceArgs() tries to allocate too much memory). (Tony) diff --git a/Zend/tests/bug38234.phpt b/Zend/tests/bug38234.phpt new file mode 100755 index 0000000000..a81a3aadcc --- /dev/null +++ b/Zend/tests/bug38234.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug #38234 (Exception in __clone makes memory leak) +--FILE-- + +--EXPECT-- +ok diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 9d79dac650..56c8f27e5b 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2518,7 +2518,11 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMP|VAR|UNUSED|CV, ANY) clone = ce ? ce->clone : NULL; clone_call = Z_OBJ_HT_P(obj)->clone_obj; if (!clone_call) { - zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name); + if (ce) { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name); + } else { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object"); + } EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr); EX_T(opline->result.u.var).var.ptr->refcount++; } @@ -2546,7 +2550,7 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMP|VAR|UNUSED|CV, ANY) Z_TYPE_P(EX_T(opline->result.u.var).var.ptr) = IS_OBJECT; EX_T(opline->result.u.var).var.ptr->refcount=1; EX_T(opline->result.u.var).var.ptr->is_ref=1; - if (!RETURN_VALUE_USED(opline)) { + if (!RETURN_VALUE_USED(opline) || EG(exception)) { zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr); } } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index badd178321..387d0bda45 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1809,7 +1809,11 @@ static int ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) clone = ce ? ce->clone : NULL; clone_call = Z_OBJ_HT_P(obj)->clone_obj; if (!clone_call) { - zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name); + if (ce) { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name); + } else { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object"); + } EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr); EX_T(opline->result.u.var).var.ptr->refcount++; } @@ -1837,7 +1841,7 @@ static int ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) Z_TYPE_P(EX_T(opline->result.u.var).var.ptr) = IS_OBJECT; EX_T(opline->result.u.var).var.ptr->refcount=1; EX_T(opline->result.u.var).var.ptr->is_ref=1; - if (!RETURN_VALUE_USED(opline)) { + if (!RETURN_VALUE_USED(opline) || EG(exception)) { zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr); } } @@ -4323,7 +4327,11 @@ static int ZEND_CLONE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) clone = ce ? ce->clone : NULL; clone_call = Z_OBJ_HT_P(obj)->clone_obj; if (!clone_call) { - zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name); + if (ce) { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name); + } else { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object"); + } EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr); EX_T(opline->result.u.var).var.ptr->refcount++; } @@ -4351,7 +4359,7 @@ static int ZEND_CLONE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) Z_TYPE_P(EX_T(opline->result.u.var).var.ptr) = IS_OBJECT; EX_T(opline->result.u.var).var.ptr->refcount=1; EX_T(opline->result.u.var).var.ptr->is_ref=1; - if (!RETURN_VALUE_USED(opline)) { + if (!RETURN_VALUE_USED(opline) || EG(exception)) { zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr); } } @@ -7419,7 +7427,11 @@ static int ZEND_CLONE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) clone = ce ? ce->clone : NULL; clone_call = Z_OBJ_HT_P(obj)->clone_obj; if (!clone_call) { - zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name); + if (ce) { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name); + } else { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object"); + } EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr); EX_T(opline->result.u.var).var.ptr->refcount++; } @@ -7447,7 +7459,7 @@ static int ZEND_CLONE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) Z_TYPE_P(EX_T(opline->result.u.var).var.ptr) = IS_OBJECT; EX_T(opline->result.u.var).var.ptr->refcount=1; EX_T(opline->result.u.var).var.ptr->is_ref=1; - if (!RETURN_VALUE_USED(opline)) { + if (!RETURN_VALUE_USED(opline) || EG(exception)) { zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr); } } @@ -14496,7 +14508,11 @@ static int ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) clone = ce ? ce->clone : NULL; clone_call = Z_OBJ_HT_P(obj)->clone_obj; if (!clone_call) { - zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name); + if (ce) { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name); + } else { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object"); + } EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr); EX_T(opline->result.u.var).var.ptr->refcount++; } @@ -14524,7 +14540,7 @@ static int ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) Z_TYPE_P(EX_T(opline->result.u.var).var.ptr) = IS_OBJECT; EX_T(opline->result.u.var).var.ptr->refcount=1; EX_T(opline->result.u.var).var.ptr->is_ref=1; - if (!RETURN_VALUE_USED(opline)) { + if (!RETURN_VALUE_USED(opline) || EG(exception)) { zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr); } } @@ -19923,7 +19939,11 @@ static int ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) clone = ce ? ce->clone : NULL; clone_call = Z_OBJ_HT_P(obj)->clone_obj; if (!clone_call) { - zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name); + if (ce) { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name); + } else { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object"); + } EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr); EX_T(opline->result.u.var).var.ptr->refcount++; } @@ -19951,7 +19971,7 @@ static int ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) Z_TYPE_P(EX_T(opline->result.u.var).var.ptr) = IS_OBJECT; EX_T(opline->result.u.var).var.ptr->refcount=1; EX_T(opline->result.u.var).var.ptr->is_ref=1; - if (!RETURN_VALUE_USED(opline)) { + if (!RETURN_VALUE_USED(opline) || EG(exception)) { zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr); } } -- 2.50.1