Skip to content

Commit 47a896c

Browse files
committed
Zend: Fix leaks when destructors throw during shutdown
1 parent 769441b commit 47a896c

3 files changed

Lines changed: 34 additions & 2 deletions

File tree

Zend/tests/exceptions/gh22010.phpt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
GH-22010: Exception thrown in destructor during shutdown
3+
--FILE--
4+
<?php
5+
6+
class A
7+
{
8+
public function __destruct()
9+
{
10+
throw new Exception(__METHOD__);
11+
}
12+
}
13+
14+
$a = new A;
15+
16+
?>
17+
--EXPECTF--
18+
Fatal error: Uncaught Exception: A::__destruct in %s:%d
19+
Stack trace:
20+
#0 [internal function]: A->__destruct()
21+
#1 {main}
22+
thrown in %s on line %d

Zend/zend_objects.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,12 @@ ZEND_API void zend_objects_destroy_object(zend_object *object)
168168
}
169169
}
170170

171-
zend_call_known_instance_method_with_0_params(destructor, object, NULL);
171+
zend_try {
172+
zend_call_known_instance_method_with_0_params(destructor, object, NULL);
173+
} zend_catch {
174+
OBJ_RELEASE(object);
175+
zend_bailout();
176+
} zend_end_try();
172177

173178
if (old_exception) {
174179
if (EG(current_execute_data)) {

Zend/zend_objects_API.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,12 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_call_destructors(zend_objects_sto
5252
if (obj->handlers->dtor_obj != zend_objects_destroy_object
5353
|| obj->ce->destructor) {
5454
GC_ADDREF(obj);
55-
obj->handlers->dtor_obj(obj);
55+
zend_try {
56+
obj->handlers->dtor_obj(obj);
57+
} zend_catch {
58+
GC_DELREF(obj);
59+
zend_bailout();
60+
} zend_end_try();
5661
GC_DELREF(obj);
5762
}
5863
}

0 commit comments

Comments
 (0)