Skip to content

Restore exception handler after running it #13686

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions Zend/tests/gh13446_1.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
--TEST--
GH-13446: Exception handler is restored after is has finished
--FILE--
<?php
function exception_handler($ex) {
echo 'Exception caught: ', $ex->getMessage(), "\n";
}
set_exception_handler('exception_handler');

register_shutdown_function(function () {
echo set_exception_handler(null), "\n";
restore_exception_handler();
});

throw new Exception('Test');
?>
--EXPECT--
Exception caught: Test
exception_handler
16 changes: 16 additions & 0 deletions Zend/tests/gh13446_2.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
--TEST--
GH-13446: Exception handler attempting to free itself
--FILE--
<?php
$x = new \stdClass();
$handler = function ($ex) use (&$handler, $x) {
$handler = null;
var_dump($x);
};
unset($x);
set_exception_handler($handler);
throw new Exception('Unhandled');
?>
--EXPECT--
object(stdClass)#1 (0) {
}
25 changes: 25 additions & 0 deletions Zend/tests/gh13446_3.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
--TEST--
GH-13446: Exception handler isn't restored if it is previously modified
--FILE--
<?php
function exception_handler_1($ex) {
echo "Handler 1\n";
set_exception_handler('exception_handler_2');
}

function exception_handler_2($ex) {
echo "Handler 2\n";
}

set_exception_handler('exception_handler_1');

register_shutdown_function(function () {
echo set_exception_handler(null), "\n";
restore_exception_handler();
});

throw new Exception();
?>
--EXPECT--
Handler 1
exception_handler_2
21 changes: 21 additions & 0 deletions Zend/tests/gh13446_4.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
--TEST--
GH-13446: Exception handler isn't restored if stack is empty
--FILE--
<?php
function exception_handler() {
echo "Handler\n";
restore_exception_handler();
restore_exception_handler();
}
set_exception_handler('exception_handler');

register_shutdown_function(function () {
var_dump(set_exception_handler(null));
restore_exception_handler();
});

throw new Exception();
?>
--EXPECT--
Handler
NULL
10 changes: 9 additions & 1 deletion Zend/zend.c
Original file line number Diff line number Diff line change
Expand Up @@ -1839,7 +1839,9 @@ ZEND_API ZEND_COLD void zend_user_exception_handler(void) /* {{{ */
old_exception = EG(exception);
EG(exception) = NULL;
ZVAL_OBJ(&params[0], old_exception);

ZVAL_COPY_VALUE(&orig_user_exception_handler, &EG(user_exception_handler));
zend_stack_push(&EG(user_exception_handlers), &orig_user_exception_handler);
ZVAL_UNDEF(&EG(user_exception_handler));

if (call_user_function(CG(function_table), NULL, &orig_user_exception_handler, &retval2, 1, params) == SUCCESS) {
Expand All @@ -1853,7 +1855,13 @@ ZEND_API ZEND_COLD void zend_user_exception_handler(void) /* {{{ */
EG(exception) = old_exception;
}

zval_ptr_dtor(&orig_user_exception_handler);
if (Z_TYPE(EG(user_exception_handler)) == IS_UNDEF) {
zval *tmp = zend_stack_top(&EG(user_exception_handlers));
if (tmp) {
ZVAL_COPY_VALUE(&EG(user_exception_handler), tmp);
zend_stack_del_top(&EG(user_exception_handlers));
}
}
} /* }}} */

ZEND_API zend_result zend_execute_scripts(int type, zval *retval, int file_count, ...) /* {{{ */
Expand Down