]> granicus.if.org Git - php/commitdiff
Fixed bug #38234 (Exception in __clone makes memory leak)
authorDmitry Stogov <dmitry@php.net>
Thu, 27 Jul 2006 10:44:19 +0000 (10:44 +0000)
committerDmitry Stogov <dmitry@php.net>
Thu, 27 Jul 2006 10:44:19 +0000 (10:44 +0000)
Zend/tests/bug38234.phpt [new file with mode: 0755]
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/Zend/tests/bug38234.phpt b/Zend/tests/bug38234.phpt
new file mode 100755 (executable)
index 0000000..a81a3aa
--- /dev/null
@@ -0,0 +1,18 @@
+--TEST--
+Bug #38234 (Exception in __clone makes memory leak)
+--FILE--
+<?php
+class Foo {
+       function __clone() {
+               throw new Exception();
+       }
+}
+try {
+       $x = new Foo();
+       $y = clone $x;
+} catch (Exception $e) {
+}
+echo "ok\n";
+?>
+--EXPECT--
+ok
index 235acfa639ef9fc986327aba557c5bd604e89e4b..63b849138572814013f0ffaa09fe3e282dad3f95 100644 (file)
@@ -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);
                }
        }
index e88db4b3f378297f1e0f6d2b72c8c0103b54dacf..7b53e78f6a30cb55fda68538259408edb927bd48 100644 (file)
@@ -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);
                }
        }