Skip to content

Fix GH-24631: Report delayed OOM when compilation of the main script fails - #24632

Open
lazerg wants to merge 6 commits into
php:PHP-8.4from
lazerg:fix/gh-24631-delayed-oom-compile-fail
Open

lazerg wants to merge 6 commits into
php:PHP-8.4from
lazerg:fix/gh-24631-delayed-oom-compile-fail

Conversation

@lazerg

@lazerg lazerg commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

zend_execute_script() only handled a pending delayed OOM when compilation produced an op_array, so a script that hit memory_limit while compiling and then failed with a parse error reported only the parse error. The OOM is now handled in the failure path too, dropping the pending ParseError so the memory error is the one reported.

Fixes GH-24631

@pentolope

Copy link
Copy Markdown

@lazerg I'd check that sapi/fuzzer/fuzzer-sapi.c is or gets fixed as well; it is the same pattern.

@lazerg

lazerg commented Oct 24, 2026

Copy link
Copy Markdown
Contributor Author

Good catch, fuzzer-sapi.c had the same gap: the delayed OOM was only handled when compilation succeeded. I added the same handling for the failed-compile case in e305af1.

@ndossche ndossche left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is slightly incomplete as zend_eval_stringl and php_lint_script need handling too.

Comment thread sapi/fuzzer/fuzzer-sapi.c Outdated
zend_destroy_static_vars(op_array);
destroy_op_array(op_array);
efree(op_array);
} else if (ZEND_HAS_OOM()) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The zend_clear_exception call is necessary, but depends on the assumption that extensions handle clearing properly. As we now know, fiber and spl did not. The fix for fiber is underway, for spl there's an open PR.
Checking for ZEND_OOM_STATE_PENDING rather than ZEND_HAS_OOM is probably better as a defensive measure (same below)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I switched all the new checks to ZEND_OOM_STATE_PENDING in 631a3b8, so an OOM that was already handled no longer clears an unrelated exception.

@lazerg
lazerg requested a review from bukka as a code owner October 24, 2026 10:47
@lazerg

lazerg commented Oct 24, 2026

Copy link
Copy Markdown
Contributor Author

@ndossche I added the same handling to zend_eval_stringl() and php_lint_script() in 631a3b8, with tests for php -r and php -l. php -l also lost the OOM when the file compiled without errors, so the lint check covers that case too.

@ndossche ndossche left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see my tiny remark and please drop the NEWS change so CI can run

Comment thread main/main.c
retval = SUCCESS;
}
if (EG(delayed_oom).state == ZEND_OOM_STATE_PENDING) {
retval = FAILURE;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need this line

@lazerg lazerg Oct 25, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is needed: zend_handle_delayed_oom() bails out here, so without it php -l on a valid file prints "No syntax errors detected" after the fatal error and oom_compile_failure_lint.phpt fails. I dropped the NEWS change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants