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
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions Zend/tests/in-de-crement/incdec_undefined_vars_exception.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
--TEST--
Inc/dec on undefined variable: warning converted to exception
--FILE--
<?php

set_error_handler(function($severity, $m) {
throw new Exception($m, $severity);
});

unset($x);
try {
$x++;
} catch (\Exception $e) {
echo $e->getMessage(), PHP_EOL;
if (compact('x') == []) { echo("UNDEF\n"); } else { var_dump($x); }
}
unset($x);
try {
$x--;
} catch (\Exception $e) {
echo $e->getMessage(), PHP_EOL;
if (compact('x') == []) { echo("UNDEF\n"); } else { var_dump($x); }
}
unset($x);
try {
++$x;
} catch (\Exception $e) {
echo $e->getMessage(), PHP_EOL;
if (compact('x') == []) { echo("UNDEF\n"); } else { var_dump($x); }
}
unset($x);
try {
--$x;
} catch (\Exception $e) {
echo $e->getMessage(), PHP_EOL;
if (compact('x') == []) { echo("UNDEF\n"); } else { var_dump($x); }
}
unset($x);
?>
--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.

Undefined variable $x
NULL
Undefined variable $x
NULL
Undefined variable $x
NULL
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
--TEST--
Inc/dec on undefined variable: warning converted to exception
--FILE--
<?php

set_error_handler(function($severity, $m) {
throw new Exception($m, $severity);
});

unset($x);
try {
$y = $x++;
} catch (\Exception $e) {
echo $e->getMessage(), PHP_EOL;
if (compact('x') == []) { echo("UNDEF\n"); } else { var_dump($x); }
}
unset($x);
try {
$y = $x--;
} catch (\Exception $e) {
echo $e->getMessage(), PHP_EOL;
if (compact('x') == []) { echo("UNDEF\n"); } else { var_dump($x); }
}
unset($x);
try {
$y = ++$x;
} catch (\Exception $e) {
echo $e->getMessage(), PHP_EOL;
if (compact('x') == []) { echo("UNDEF\n"); } else { var_dump($x); }
}
unset($x);
try {
$y = --$x;
} catch (\Exception $e) {
echo $e->getMessage(), PHP_EOL;
if (compact('x') == []) { echo("UNDEF\n"); } else { var_dump($x); }
}
unset($x);
?>
--EXPECT--
Undefined variable $x
NULL
Undefined variable $x
NULL
Undefined variable $x
NULL
Undefined variable $x
NULL
28 changes: 28 additions & 0 deletions Zend/zend_vm_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -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))) {
/* opcodes are expected to set the result value */
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_NULL(EX_VAR(opline->result.var));
}
HANDLE_EXCEPTION();
}
ZVAL_NULL(var_ptr);
}

Expand Down Expand Up @@ -1538,6 +1545,13 @@ ZEND_VM_HELPER(zend_pre_dec_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))) {
/* opcodes are expected to set the result value */
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_NULL(EX_VAR(opline->result.var));
}
HANDLE_EXCEPTION();
}
ZVAL_NULL(var_ptr);
}

Expand Down Expand Up @@ -1590,6 +1604,13 @@ ZEND_VM_HELPER(zend_post_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))) {
/* opcodes are expected to set the result value */
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_NULL(EX_VAR(opline->result.var));
}
HANDLE_EXCEPTION();
}
ZVAL_NULL(var_ptr);
}

Expand Down Expand Up @@ -1641,6 +1662,13 @@ ZEND_VM_HELPER(zend_post_dec_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))) {
/* opcodes are expected to set the result value */
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_NULL(EX_VAR(opline->result.var));
}
HANDLE_EXCEPTION();
}
ZVAL_NULL(var_ptr);
}

Expand Down
56 changes: 56 additions & 0 deletions Zend/zend_vm_execute.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions ext/opcache/jit/zend_jit_arm64.dasc
Original file line number Diff line number Diff line change
Expand Up @@ -3883,6 +3883,8 @@ static int zend_jit_inc_dec(dasm_State **Dst, const zend_op *opline, uint32_t op
| // zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(CV_DEF_OF(EX_VAR_TO_NUM(opline->op1.var))));
| LOAD_32BIT_VAL FCARG1w, opline->op1.var
| EXT_CALL zend_jit_undefined_op_helper, REG0
| // Check if undefined error was converted to exception and abort
| cbz RETVALx, ->exception_handler_undef
| SET_ZVAL_TYPE_INFO op1_addr, IS_NULL, TMP1w, TMP2
op1_info |= MAY_BE_NULL;
}
Expand Down
3 changes: 3 additions & 0 deletions ext/opcache/jit/zend_jit_x86.dasc
Original file line number Diff line number Diff line change
Expand Up @@ -4264,6 +4264,9 @@ static int zend_jit_inc_dec(dasm_State **Dst, const zend_op *opline, uint32_t op
| mov FCARG1d, opline->op1.var
| EXT_CALL zend_jit_undefined_op_helper, r0
| SET_ZVAL_TYPE_INFO op1_addr, IS_NULL
| // Check if undefined error was converted to exception and abort
| test r0, r0
| jz ->exception_handler_undef
op1_info |= MAY_BE_NULL;
}
|2:
Expand Down