Skip to content

inc/dec with undefined vars #11850

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 3 commits into from
Closed

Conversation

Girgias
Copy link
Member

@Girgias Girgias commented Aug 1, 2023

I split the first commit from #11759 into its own PR as it is not an OSS-fuzz fix, and like said it is a pre-existing issue so maybe should be backported.

The rationale is that, considering undefined variables will become Errors at one point, the behaviour of this and what happens now when the warning is converted to an exception should be, IMHO, identical.

However, it seems that a lot of the VM handlers that use ZVAL_UNDEFINED_OP1() do not explicitly check if an exception is thrown from an undefined operand.

Copy link
Member

@dstogov dstogov left a comment

Choose a reason for hiding this comment

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

Please, fix tests and remove or explain comments.

$x++;
} catch (\Exception $e) {
echo $e->getMessage(), PHP_EOL;
if (!isset($x)) { echo("UNDEF\n"); } else { var_dump($x); }
Copy link
Member

Choose a reason for hiding this comment

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

I just realized that isset() doesn't make distinct between UNDEF and NULL, so the test prints UNDEF insted of NULL. It's possible to fix this using the following terrible code.

if (!isset($x) && !@is_null($x)) { echo("UNDEF\n"); } else { var_dump($x); }

Copy link
Member

@iluuu1994 iluuu1994 Aug 2, 2023

Choose a reason for hiding this comment

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

@dstogov I don't think that works, as $x is coerced to NULL, no? It could be possible to just access $x and catch the warning if promoted to an exception with an error handler.

Edit: Ah, we already have the error handler...

@@ -1487,6 +1487,13 @@ ZEND_VM_HELPER(zend_pre_inc_helper, VAR|CV, ANY)
SAVE_OPLINE();
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
ZVAL_UNDEFINED_OP1();
if (UNEXPECTED(EG(exception))) {
/* Smart branch expects result to be set with exceptions */
Copy link
Member

Choose a reason for hiding this comment

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

I didn't understand this comment.
PRE/POST_INC/DEC are never combined with the following JMPZ/NZ into smart branches.

Copy link
Member

@iluuu1994 iluuu1994 Aug 2, 2023

Choose a reason for hiding this comment

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

It's actually about this line:

zval_ptr_dtor_nogc(EX_VAR(throw_op->result.var));

The problem is not related to smart branches. Instead, it's every op but smart branches, that are expected to initialize the result (apart from some others that don't store zvals). If the result is not initialized, we'll free uninitialized value. With opcache, we can get a use-after-free if the zval still contains some old value due to shared VAR slots.

?>
--EXPECT--
Undefined variable $x
NULL
Copy link
Member Author

Choose a reason for hiding this comment

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

Should it actually be NULL or should $x remain undefined?

Copy link
Member

Choose a reason for hiding this comment

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

Should it actually be NULL or should $x remain undefined?

If you didn't define the new behaviour in your RFC it should be the same as in PHP-8.2.

Girgias added 3 commits August 2, 2023 18:54

Verified

This commit was signed with the committer’s verified signature. The key has expired.
Girgias Gina Peter Banyard

Verified

This commit was signed with the committer’s verified signature. The key has expired.
Girgias Gina Peter Banyard

Verified

This commit was signed with the committer’s verified signature. The key has expired.
Girgias Gina Peter Banyard
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.

None yet

3 participants