Skip to content

Commit bc59e79

Browse files
committed
Merge branch 'PHP-8.3'
* PHP-8.3: Restore error handler after running it
2 parents 6fb20cd + 3301d96 commit bc59e79

File tree

5 files changed

+90
-1
lines changed

5 files changed

+90
-1
lines changed

Zend/tests/gh13446_1.phpt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
GH-13446: Exception handler is restored after is has finished
3+
--FILE--
4+
<?php
5+
function exception_handler($ex) {
6+
echo 'Exception caught: ', $ex->getMessage(), "\n";
7+
}
8+
set_exception_handler('exception_handler');
9+
10+
register_shutdown_function(function () {
11+
echo set_exception_handler(null), "\n";
12+
restore_exception_handler();
13+
});
14+
15+
throw new Exception('Test');
16+
?>
17+
--EXPECT--
18+
Exception caught: Test
19+
exception_handler

Zend/tests/gh13446_2.phpt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
GH-13446: Exception handler attempting to free itself
3+
--FILE--
4+
<?php
5+
$x = new \stdClass();
6+
$handler = function ($ex) use (&$handler, $x) {
7+
$handler = null;
8+
var_dump($x);
9+
};
10+
unset($x);
11+
set_exception_handler($handler);
12+
throw new Exception('Unhandled');
13+
?>
14+
--EXPECT--
15+
object(stdClass)#1 (0) {
16+
}

Zend/tests/gh13446_3.phpt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
GH-13446: Exception handler isn't restored if it is previously modified
3+
--FILE--
4+
<?php
5+
function exception_handler_1($ex) {
6+
echo "Handler 1\n";
7+
set_exception_handler('exception_handler_2');
8+
}
9+
10+
function exception_handler_2($ex) {
11+
echo "Handler 2\n";
12+
}
13+
14+
set_exception_handler('exception_handler_1');
15+
16+
register_shutdown_function(function () {
17+
echo set_exception_handler(null), "\n";
18+
restore_exception_handler();
19+
});
20+
21+
throw new Exception();
22+
?>
23+
--EXPECT--
24+
Handler 1
25+
exception_handler_2

Zend/tests/gh13446_4.phpt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
GH-13446: Exception handler isn't restored if stack is empty
3+
--FILE--
4+
<?php
5+
function exception_handler() {
6+
echo "Handler\n";
7+
restore_exception_handler();
8+
restore_exception_handler();
9+
}
10+
set_exception_handler('exception_handler');
11+
12+
register_shutdown_function(function () {
13+
var_dump(set_exception_handler(null));
14+
restore_exception_handler();
15+
});
16+
17+
throw new Exception();
18+
?>
19+
--EXPECT--
20+
Handler
21+
NULL

Zend/zend.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1859,7 +1859,9 @@ ZEND_API ZEND_COLD void zend_user_exception_handler(void) /* {{{ */
18591859
old_exception = EG(exception);
18601860
EG(exception) = NULL;
18611861
ZVAL_OBJ(&params[0], old_exception);
1862+
18621863
ZVAL_COPY_VALUE(&orig_user_exception_handler, &EG(user_exception_handler));
1864+
zend_stack_push(&EG(user_exception_handlers), &orig_user_exception_handler);
18631865
ZVAL_UNDEF(&EG(user_exception_handler));
18641866

18651867
if (call_user_function(CG(function_table), NULL, &orig_user_exception_handler, &retval2, 1, params) == SUCCESS) {
@@ -1873,7 +1875,13 @@ ZEND_API ZEND_COLD void zend_user_exception_handler(void) /* {{{ */
18731875
EG(exception) = old_exception;
18741876
}
18751877

1876-
zval_ptr_dtor(&orig_user_exception_handler);
1878+
if (Z_TYPE(EG(user_exception_handler)) == IS_UNDEF) {
1879+
zval *tmp = zend_stack_top(&EG(user_exception_handlers));
1880+
if (tmp) {
1881+
ZVAL_COPY_VALUE(&EG(user_exception_handler), tmp);
1882+
zend_stack_del_top(&EG(user_exception_handlers));
1883+
}
1884+
}
18771885
} /* }}} */
18781886

18791887
ZEND_API zend_result zend_execute_script(int type, zval *retval, zend_file_handle *file_handle)

0 commit comments

Comments
 (0)