Repository navigation
Conversation
iliaal
left a comment
There was a problem hiding this comment.
phpdbg: in the ZEND_WIN32 block of phpdbg_prompt.c, exception is read before zend_timeout(), which now returns with an UnwindExit set, so that iteration misses it. Checking the timeout before reading EG(exception) avoids that.
zend_timeout() losing ZEND_NORETURN probably wants an UPGRADING.INTERNALS line, since extensions calling it now get control back with an exception set.
| #endif | ||
| if (atomic_load(&EG(timed_out))) { | ||
| zend_timeout(); | ||
| HANDLE_EXCEPTION(); |
There was a problem hiding this comment.
EG(opline_before_exception) here is the opline the interrupt fired before, not one that ran, so ZEND_HANDLE_EXCEPTION dtors its stale result. With while (true) { $s = $a . 'y'; } it frees the string $s still owns, and a shutdown function reading $s hits a UAF under valgrind. zend_handle_delayed_oom() NULLs opline_before_exception for this reason; doing the same after zend_timeout() here clears it. The JIT stub is unaffected thanks to zend_jit_exception_in_interrupt_handler_helper().
| && execute_data->opline->opcode != ZEND_HANDLE_EXCEPTION) { | ||
| EG(opline_before_exception) = EG(current_execute_data)->opline; | ||
| EG(current_execute_data)->opline = EG(exception_op); | ||
| } |
There was a problem hiding this comment.
This duplicates zend_throw_unwind_exit() plus a guard; could the guard move into that helper instead?
| @@ -0,0 +1,16 @@ | |||
| --TEST-- | |||
| @@ -0,0 +1,22 @@ | |||
| --TEST-- | |||
max_execution_timeis handled like this:EG(vm_interrupt)andEG(timed_out)zend_timeout()from a safe point when these flags are setzend_timeout()triggers a fatal error ->zend_bailout()Change the last step so that
zend_timeout()throws anUnwindExitexception instead.