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
Assertion ret == SUCCESS in array_map()/array_filter() after delayed out-of-memory #25311
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 4db42ddb741..57fe6f96227 100644
--- a/Zend/zend_execute_API.c+++ b/Zend/zend_execute_API.c@@ -836,9 +836,11 @@ zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_
return FAILURE; /* executor is already inactive */
}
if (ZEND_HAS_OOM()) {
- /* Callers expect SUCCESS || EG(exception), so let's throw right now */+ /* Throws UnwindExit if the OOM is pending. If not pending, acts as if executor is inactive. */
zend_handle_delayed_oom();
- return FAILURE;+ if (!EG(exception)) {+ return FAILURE;+ }
}
if (EG(exception)) {
if (fci_cache) {
@ndossche Looks good. Previously it was possible for zend_handle_delayed_oom() to exit without setting EG(exception), namely via recursion in zend_error_zstr_at(). But we since refactored this code to call zend_throw_unwind_exit() early so that this shouldn't be possible anymore (recursion is still possible, but EG(exception) will already be set). We can keep the if for now just in case, and transform it to ZEND_ASSERT() in master.
Activity
ndossche commentedon Nov 9, 2026
The comment in zend_call_function:
Is wrong. A long time ago the code was changed such that SUCCESS is always returned except when the executor is inactive. Callers depend on this.
This would fix it, but I'd like a second opinion of @arnaud-lb / @iluuu1994
Girgias commentedon Nov 9, 2026
Indeed we expect SUCCESS if an exception is thrown.
iluuu1994 commentedon Nov 9, 2026
@ndossche Looks good. Previously it was possible for
zend_handle_delayed_oom()to exit without settingEG(exception), namely via recursion inzend_error_zstr_at(). But we since refactored this code to callzend_throw_unwind_exit()early so that this shouldn't be possible anymore (recursion is still possible, butEG(exception)will already be set). We can keep theiffor now just in case, and transform it toZEND_ASSERT()inmaster.