Skip to content

Commit

Permalink
Fix inc/dec of undef var with error handler
Browse files Browse the repository at this point in the history
Set the variable to null after emitting the undef var notice
rather than before. This avoids an assertion failure if the var
is unset by the error handler.

The flip side is that this may cause a leak instead, but that's
the more harmless outcome.

Fixes oss-fuzz #36604.
  • Loading branch information
nikic committed Oct 19, 2021
1 parent 0acfd2d commit 22b6aac
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 14 deletions.
25 changes: 25 additions & 0 deletions Zend/tests/incdec_undef.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
--TEST--
Inc/dec undef var with error handler
--FILE--
<?php
set_error_handler(function($_, $m) {
echo "$m\n";
unset($GLOBALS['x']);
});
var_dump($x--);
unset($x);
var_dump($x++);
unset($x);
var_dump(--$x);
unset($x);
var_dump(++$x);
?>
--EXPECT--
Undefined variable $x
NULL
Undefined variable $x
NULL
Undefined variable $x
NULL
Undefined variable $x
int(1)
8 changes: 4 additions & 4 deletions Zend/zend_vm_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -1470,8 +1470,8 @@ 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_NULL(var_ptr);
ZVAL_UNDEFINED_OP1();
ZVAL_NULL(var_ptr);
}

do {
Expand Down Expand Up @@ -1521,8 +1521,8 @@ 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_NULL(var_ptr);
ZVAL_UNDEFINED_OP1();
ZVAL_NULL(var_ptr);
}

do {
Expand Down Expand Up @@ -1573,8 +1573,8 @@ 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_NULL(var_ptr);
ZVAL_UNDEFINED_OP1();
ZVAL_NULL(var_ptr);
}

do {
Expand Down Expand Up @@ -1621,8 +1621,8 @@ 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_NULL(var_ptr);
ZVAL_UNDEFINED_OP1();
ZVAL_NULL(var_ptr);
}

do {
Expand Down
16 changes: 8 additions & 8 deletions Zend/zend_vm_execute.h
Original file line number Diff line number Diff line change
Expand Up @@ -21156,8 +21156,8 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_inc_help

SAVE_OPLINE();
if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
ZVAL_NULL(var_ptr);
ZVAL_UNDEFINED_OP1();
ZVAL_NULL(var_ptr);
}

do {
Expand Down Expand Up @@ -21225,8 +21225,8 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_dec_help

SAVE_OPLINE();
if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
ZVAL_NULL(var_ptr);
ZVAL_UNDEFINED_OP1();
ZVAL_NULL(var_ptr);
}

do {
Expand Down Expand Up @@ -21295,8 +21295,8 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_inc_hel

SAVE_OPLINE();
if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
ZVAL_NULL(var_ptr);
ZVAL_UNDEFINED_OP1();
ZVAL_NULL(var_ptr);
}

do {
Expand Down Expand Up @@ -21343,8 +21343,8 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_dec_hel

SAVE_OPLINE();
if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
ZVAL_NULL(var_ptr);
ZVAL_UNDEFINED_OP1();
ZVAL_NULL(var_ptr);
}

do {
Expand Down Expand Up @@ -37222,8 +37222,8 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_inc_help

SAVE_OPLINE();
if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
ZVAL_NULL(var_ptr);
ZVAL_UNDEFINED_OP1();
ZVAL_NULL(var_ptr);
}

do {
Expand Down Expand Up @@ -37290,8 +37290,8 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_dec_help

SAVE_OPLINE();
if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
ZVAL_NULL(var_ptr);
ZVAL_UNDEFINED_OP1();
ZVAL_NULL(var_ptr);
}

do {
Expand Down Expand Up @@ -37359,8 +37359,8 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_inc_hel

SAVE_OPLINE();
if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
ZVAL_NULL(var_ptr);
ZVAL_UNDEFINED_OP1();
ZVAL_NULL(var_ptr);
}

do {
Expand Down Expand Up @@ -37406,8 +37406,8 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_dec_hel

SAVE_OPLINE();
if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
ZVAL_NULL(var_ptr);
ZVAL_UNDEFINED_OP1();
ZVAL_NULL(var_ptr);
}

do {
Expand Down
2 changes: 1 addition & 1 deletion ext/opcache/jit/zend_jit_arm64.dasc
Original file line number Diff line number Diff line change
Expand Up @@ -3757,8 +3757,8 @@ static int zend_jit_inc_dec(dasm_State **Dst, const zend_op *opline, uint32_t op
| IF_NOT_ZVAL_TYPE op1_addr, IS_UNDEF, >2, ZREG_TMP1
| // 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
| SET_ZVAL_TYPE_INFO op1_addr, IS_NULL, TMP1w, TMP2
| EXT_CALL zend_jit_undefined_op_helper, REG0
| SET_ZVAL_TYPE_INFO op1_addr, IS_NULL, TMP1w, TMP2
op1_info |= MAY_BE_NULL;
}
|2:
Expand Down
2 changes: 1 addition & 1 deletion ext/opcache/jit/zend_jit_x86.dasc
Original file line number Diff line number Diff line change
Expand Up @@ -4125,8 +4125,8 @@ static int zend_jit_inc_dec(dasm_State **Dst, const zend_op *opline, uint32_t op
| IF_NOT_ZVAL_TYPE op1_addr, IS_UNDEF, >2
| // zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(CV_DEF_OF(EX_VAR_TO_NUM(opline->op1.var))));
| mov FCARG1d, opline->op1.var
| SET_ZVAL_TYPE_INFO op1_addr, IS_NULL
| EXT_CALL zend_jit_undefined_op_helper, r0
| SET_ZVAL_TYPE_INFO op1_addr, IS_NULL
op1_info |= MAY_BE_NULL;
}
|2:
Expand Down

0 comments on commit 22b6aac

Please sign in to comment.