]> granicus.if.org Git - php/commitdiff
Fixed bug #29368 (The destructor is called when an exception is thrown from the const...
authorDmitry Stogov <dmitry@zend.com>
Wed, 13 Jul 2016 13:43:47 +0000 (16:43 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 13 Jul 2016 13:43:47 +0000 (16:43 +0300)
NEWS
UPGRADING
Zend/tests/bug29368_1.phpt [new file with mode: 0644]
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/NEWS b/NEWS
index 91bba83d05251606e52e78f44406a4ad45f5bdf5..39261f4d528405054e5642427c4c9442d8502de6 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -18,6 +18,8 @@ PHP                                                                        NEWS
   . Added PHP to SAPI error severity mapping for logs. (Martin Vobruba)
   . Fixed bug #71911 (Unable to set --enable-debug on building extensions by
     phpize on Windows). (Yuji Uchiyama)
+  . Fixed bug #29368 (The destructor is called when an exception is thrown from
+    the constructor). (Dmitry)
 
 - COM:
   . Fixed bug #72569 (DOTNET/COM array parameters broke in PHP7). (Anatol)
index 1759590169db4fbdda749ab209e4dc15c665e1b7..adb4741a5b13f18fe97fab8ec358721798b876a3 100644 (file)
--- a/UPGRADING
+++ b/UPGRADING
@@ -47,6 +47,8 @@ PHP 7.1 UPGRADE NOTES
     syslog error levels. This brings finer differentiation in the error logs
     in contrary to the previous approach where all the errors are loggged with
     the notice level only.
+  . Don't call destructors of incompletely constructed objects, even if they
+    are kept referenced. See bug #29368 and Zend/tests/bug29368_1.phpt.
 
 - JSON:
   . The serialize_precision is used instead of precision when encoding double
diff --git a/Zend/tests/bug29368_1.phpt b/Zend/tests/bug29368_1.phpt
new file mode 100644 (file)
index 0000000..09cf334
--- /dev/null
@@ -0,0 +1,29 @@
+--TEST--
+Bug #29368.1 (The destructor is called when an exception is thrown from the constructor).
+--FILE--
+<?php
+function throwme($arg)
+{
+    throw new Exception;
+}
+
+class foo {
+  function __construct() {
+    echo "Inside constructor\n";
+    throwme($this);
+  }
+
+  function __destruct() {
+    echo "Inside destructor\n";
+  }
+}
+
+try {
+  $bar = new foo;
+} catch(Exception $exc) {
+  echo "Caught exception!\n";
+}
+?>
+--EXPECT--
+Inside constructor
+Caught exception!
index d10bd72e9d1787988851f9e2e92f166c60df9df0..f93e89f39f4bf77e38447f1bda2766b319597253 100644 (file)
@@ -2500,9 +2500,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
                        if (UNEXPECTED(EG(exception) != NULL) && (call_info & ZEND_CALL_CTOR)) {
 #endif
                                GC_REFCOUNT(object)--;
-                               if (GC_REFCOUNT(object) == 1) {
-                                       zend_object_store_ctor_failed(object);
-                               }
+                               zend_object_store_ctor_failed(object);
                        }
                        OBJ_RELEASE(object);
                } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
@@ -2537,9 +2535,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
                        if (UNEXPECTED(EG(exception) != NULL) && (call_info & ZEND_CALL_CTOR)) {
 #endif
                                GC_REFCOUNT(object)--;
-                               if (GC_REFCOUNT(object) == 1) {
-                                       zend_object_store_ctor_failed(object);
-                               }
+                               zend_object_store_ctor_failed(object);
                        }
                        OBJ_RELEASE(object);
                } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
@@ -3803,9 +3799,7 @@ ZEND_VM_C_LABEL(fcall_end):
                if (UNEXPECTED(EG(exception) != NULL) && (ZEND_CALL_INFO(call) & ZEND_CALL_CTOR)) {
 #endif
                        GC_REFCOUNT(object)--;
-                       if (GC_REFCOUNT(object) == 1) {
-                               zend_object_store_ctor_failed(object);
-                       }
+                       zend_object_store_ctor_failed(object);
                }
                OBJ_RELEASE(object);
        }
index 37d8862d3b9b3a551599b670c6bcc640823a9134..8574b2436c9606d48f9ba71a3bccf01853b05516 100644 (file)
@@ -492,9 +492,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_
                        if (UNEXPECTED(EG(exception) != NULL) && (call_info & ZEND_CALL_CTOR)) {
 #endif
                                GC_REFCOUNT(object)--;
-                               if (GC_REFCOUNT(object) == 1) {
-                                       zend_object_store_ctor_failed(object);
-                               }
+                               zend_object_store_ctor_failed(object);
                        }
                        OBJ_RELEASE(object);
                } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
@@ -529,9 +527,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_
                        if (UNEXPECTED(EG(exception) != NULL) && (call_info & ZEND_CALL_CTOR)) {
 #endif
                                GC_REFCOUNT(object)--;
-                               if (GC_REFCOUNT(object) == 1) {
-                                       zend_object_store_ctor_failed(object);
-                               }
+                               zend_object_store_ctor_failed(object);
                        }
                        OBJ_RELEASE(object);
                } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
@@ -1017,9 +1013,7 @@ fcall_end:
                if (UNEXPECTED(EG(exception) != NULL) && (ZEND_CALL_INFO(call) & ZEND_CALL_CTOR)) {
 #endif
                        GC_REFCOUNT(object)--;
-                       if (GC_REFCOUNT(object) == 1) {
-                               zend_object_store_ctor_failed(object);
-                       }
+                       zend_object_store_ctor_failed(object);
                }
                OBJ_RELEASE(object);
        }
@@ -1146,9 +1140,7 @@ fcall_end:
                if (UNEXPECTED(EG(exception) != NULL) && (ZEND_CALL_INFO(call) & ZEND_CALL_CTOR)) {
 #endif
                        GC_REFCOUNT(object)--;
-                       if (GC_REFCOUNT(object) == 1) {
-                               zend_object_store_ctor_failed(object);
-                       }
+                       zend_object_store_ctor_failed(object);
                }
                OBJ_RELEASE(object);
        }