From 1e71620e8f21a41be6d08d04ea688ecae4f6d0ec Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 27 Jul 2006 10:44:19 +0000 Subject: [PATCH] Fixed bug #38234 (Exception in __clone makes memory leak) --- Zend/tests/bug38234.phpt | 18 ++++++++++++++++++ Zend/zend_vm_def.h | 8 ++++++-- Zend/zend_vm_execute.h | 40 ++++++++++++++++++++++++++++++---------- 3 files changed, 54 insertions(+), 12 deletions(-) create mode 100755 Zend/tests/bug38234.phpt 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 235acfa639..63b8491385 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2548,7 +2548,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 %v", ce->name); + if (ce) { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", 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++; } @@ -2576,7 +2580,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 e88db4b3f3..7b53e78f6a 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1759,7 +1759,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 %v", ce->name); + if (ce) { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", 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++; } @@ -1787,7 +1791,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); } } @@ -4341,7 +4345,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 %v", ce->name); + if (ce) { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", 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++; } @@ -4369,7 +4377,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); } } @@ -7520,7 +7528,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 %v", ce->name); + if (ce) { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", 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++; } @@ -7548,7 +7560,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); } } @@ -14888,7 +14900,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 %v", ce->name); + if (ce) { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", 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++; } @@ -14916,7 +14932,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); } } @@ -20531,7 +20547,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 %v", ce->name); + if (ce) { + zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", 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++; } @@ -20559,7 +20579,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