diff --git a/Zend/tests/bug49893.phpt b/Zend/tests/bug49893.phpt new file mode 100644 index 00000000000..b340f7bdfdf --- /dev/null +++ b/Zend/tests/bug49893.phpt @@ -0,0 +1,28 @@ +--TEST-- +Bug #49893 (Crash while creating an instance of Zend_Mail_Storage_Pop3) +--FILE-- +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 diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c index 8b94e62d880..a2f1d3287e0 100644 --- a/Zend/zend_objects.c +++ b/Zend/zend_objects.c @@ -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); } }