]> 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:03 +0000 (10:44 +0000)
committerDmitry Stogov <dmitry@php.net>
Thu, 27 Jul 2006 10:44:03 +0000 (10:44 +0000)
NEWS
Zend/tests/bug38234.phpt [new file with mode: 0755]
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/NEWS b/NEWS
index 3cc557df485d7e1b0a9bd681b4a356ada7a5d0a4..1caa3b766ad55223b833e3e5324f618bf5e87d95 100644 (file)
--- 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 (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 9d79dac650a83acd94a340104c5846859a71ba51..56c8f27e5b3749093465426e4f8f21d14067fab9 100644 (file)
@@ -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);
                }
        }
index badd1783215e52acac8aa74dd52a097ea638f381..387d0bda45f84ee1c6dcfdf6e568782b8585ea34 100644 (file)
@@ -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);
                }
        }