Skip to content

Fix GH-13931: Applying zero offset to null pointer in Zend/zend_opcode.c #13938

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 6 commits into from

Conversation

nielsdos
Copy link
Member

@nielsdos nielsdos commented Apr 10, 2024

In the test cases, the compiler bails out due to a fatal error. The data structures used by the compiler will contain stale values. In particular, for the test case CG(loop_var_stack) will contain data. The next compilation will incorrectly use elements from the previous stack. This causes a segfault in pass2 because wrong instructions will be emitted due to the stale data.
To solve this, we reset part of the compiler data structures. We don't do a full re-initialization via init_compiler() because that will also reset streams and resources.

…code.c

In the test cases, the compiler bails out due to a fatal error.
The data structures used by the compiler will contain stale values.
In particular, for the test case CG(loop_var_stack) will contain data.
The next compilation will incorrectly use elements from the previous
stack.
To solve this, we reset part of the compiler data structures.
We don't do a full re-initialization via init_compiler() because that will
also reset streams and resources.
@nielsdos nielsdos requested a review from dstogov as a code owner April 10, 2024 18:41
@nielsdos nielsdos linked an issue Apr 10, 2024 that may be closed by this pull request
@nielsdos nielsdos requested a review from iluuu1994 as a code owner April 10, 2024 19:12
Zend/zend.c Outdated
* If code is compiled during shutdown, we need to make sure the compiler is reset to a clean state,
* otherwise this will lead to incorrect compilation during shutdown.
* We don't do a full re-initialization via init_compiler() because that will also reset streams and resources. */
shutdown_compiler();
Copy link
Member

Choose a reason for hiding this comment

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

Other calls to shutdown_compiler are wrapped in zend_try, do we need that here? I don't believe so, looking at its implementation. But maybe you can double-check. 🙂

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't really know why other locations surround it in a try, it doesn't seem necessary.
However, if wanted I can do this, it doesn't seem harmful.

Copy link
Member

Choose a reason for hiding this comment

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

I checked again, and none of the frees in shutdown_compiler can throw, because they are either just calls to efree, or free hash tables that contain strings or pointers.

Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure if we call shutdown_function after a fatal error on purpose. This is definitely not safe.
We especially disable destructor calls in php_error_cb().

In any case, I think it's better to move this recovery code into php_error_cb().

Copy link
Member Author

Choose a reason for hiding this comment

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

I have moved the code to php_error_cb.

I'm not sure if we call shutdown_function after a fatal error on purpose. This is definitely not safe.
We especially disable destructor calls in php_error_cb().

Good question, I don't know but I wouldn't be surprised people depend on this.

Copy link
Member

Choose a reason for hiding this comment

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

@dstogov Can you clarify why this would be problematic for shutdown functions? When compiling new files through includes in shutdown, the compile structures are cleaned and newly initialized. Nothing should be referencing the old values either, as the compilation has previously bailed. I might be missing something.

Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure if we call shutdown_function after a fatal error on purpose. This is definitely not safe.
We especially disable destructor calls in php_error_cb().

Good question, I don't know but I wouldn't be surprised people depend on this.

This is right. People depends on every weird feature :(
This error handler may be called after ANY fatal error that stood something in inconsistent state. E.g. after memory overflow.

Copy link
Member

Choose a reason for hiding this comment

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

@dstogov Can you clarify why this would be problematic for shutdown functions? When compiling new files through includes in shutdown, the compile structures are cleaned and newly initialized. Nothing should be referencing the old values either, as the compilation has previously bailed. I might be missing something.

I don't claim your recovery code. Recovery after parse errors should be possible.
I ask you to move this code to a more appropriate place (into php_error_cb(). or even higher).
Also it may make sense to do this only for E_PARSE errors.

Copy link
Member Author

Choose a reason for hiding this comment

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

The error from the test case is an E_COMPILE_ERROR instead of a E_PARSE.
I adjusted the code in php_error_cb to recover the compiler if either of these two happen.

Copy link
Member

@iluuu1994 iluuu1994 left a comment

Choose a reason for hiding this comment

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

LGTM, thank you Niels!

@nielsdos nielsdos closed this in c3acfb1 Apr 15, 2024
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.

Applying zero offset to null pointer in Zend/zend_opcode.c
3 participants