You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
finally block runs twice when a VM interrupt throws as it returns to "return" in the try block #24480
When an interrupt is pending as a finally block finishes after a return in its try block, and the interrupt function throws (an async pcntl signal handler, a request timeout from Excimer, etc.), the finally block runs a second time.
return X; in a try block compiles to FAST_CALL + RETURN, both inside the try range. ZEND_FAST_RET jumps back to the RETURN with ZEND_VM_JMP_EX(), which checks for interrupts after setting opline to the RETURN. The exception is attributed to the try block, so the finally block runs again, and the pending return value is leaked. This is the common case when the interrupt arrives during a user function called from the finally block, because returning from a user function does not check for interrupts in the hybrid VM.
In the CALL VM the interrupt is handled right after the user function returns, at the FAST_RET. That op is finally_end, which counts as outside the try/finally, so the finally block runs once but the return value (and any exception the finally block was delaying) leaks.
Reproduced with the script above on PHP 8.2.32, 8.4.26 and 8.5.7, and in production on 8.3.35. `ZEND_FAST_RET` is unchanged on master, so is expected to apply to PHP 8.6 as well.
Activity
Fix finally block running twice when a VM interrupt throws in FAST_RET