]> granicus.if.org Git - php/commitdiff
Fixed bug #49893 (Crash while creating an instance of Zend_Mail_Storage_Pop3)
authorDmitry Stogov <dmitry@php.net>
Tue, 11 May 2010 16:09:43 +0000 (16:09 +0000)
committerDmitry Stogov <dmitry@php.net>
Tue, 11 May 2010 16:09:43 +0000 (16:09 +0000)
NEWS
Zend/tests/bug49893.phpt [new file with mode: 0644]
Zend/zend_objects.c

diff --git a/NEWS b/NEWS
index 2d05102ac63f4ef1cedf3c149092be422bca6f32..797660d3381211423df89cd6a554cf3678a02d08 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -129,6 +129,8 @@ PHP                                                                        NEWS
 - Fixed bug #50383 (Exceptions thrown in __call / __callStatic do not include
   file and line in trace). (Felipe)
 - Fixed bug #50358 (Compile failure compiling ext/phar/util.lo). (Felipe)
+- Fixed bug #49893 (Crash while creating an instance of Zend_Mail_Storage_Pop3).
+  (Dmitry)
 - Fixed bug #49778 (DateInterval::format("%a") is always zero when an interval
   is created from an ISO string). (Derick)
 - Fixed bug #49700 (memory leaks in php_date.c if garbage collector is
diff --git a/Zend/tests/bug49893.phpt b/Zend/tests/bug49893.phpt
new file mode 100644 (file)
index 0000000..b340f7b
--- /dev/null
@@ -0,0 +1,28 @@
+--TEST--
+Bug #49893 (Crash while creating an instance of Zend_Mail_Storage_Pop3)
+--FILE--
+<?php
+class A {
+       function __destruct() {
+               try {
+                       throw new Exception("2");
+               } catch (Exception $e) {
+                       echo $e->getMessage() . "\n";
+               }
+       }
+}
+class B {
+       function __construct() {
+               $this->a = new A();
+               throw new Exception("1");
+       }
+}
+try {
+       $b = new B();
+} catch(Exception $e) {
+       echo $e->getMessage() . "\n";;
+}
+?>
+--EXPECT--
+2
+1
index 8b94e62d8807578e491f681d086956fc8161fde1..a2f1d3287e00704c2091f65d84eaef29ddf81ac1 100644 (file)
@@ -52,6 +52,7 @@ ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handl
        zend_function *destructor = object ? object->ce->destructor : NULL;
 
        if (destructor) {
+               zval *old_exception;
                zval *obj;
                zend_object_store_bucket *obj_bucket;
 
@@ -99,12 +100,25 @@ ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handl
                 * For example, if an exception was thrown in a function and when the function's
                 * local variable destruction results in a destructor being called.
                 */
-               if (EG(exception) && Z_OBJ_HANDLE_P(EG(exception)) == handle) {
-                       zend_error(E_ERROR, "Attempt to destruct pending exception");
+               old_exception = NULL;
+               if (EG(exception)) {
+                       if (Z_OBJ_HANDLE_P(EG(exception)) == handle) {
+                               zend_error(E_ERROR, "Attempt to destruct pending exception");
+                       } else {
+                               old_exception = EG(exception);
+                               Z_ADDREF_P(old_exception);
+                       }
                }
                zend_exception_save(TSRMLS_C);
                zend_call_method_with_0_params(&obj, object->ce, &destructor, ZEND_DESTRUCTOR_FUNC_NAME, NULL);
                zend_exception_restore(TSRMLS_C);
+               if (old_exception) {
+                       if (EG(exception)) {
+                               zval_ptr_dtor(&old_exception);                          
+                       } else {
+                               EG(exception) = old_exception;
+                       }
+               }
                zval_ptr_dtor(&obj);
        }
 }