Skip to content

Commit 22b6aac

Browse files
committed
Fix inc/dec of undef var with error handler
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.
1 parent 0acfd2d commit 22b6aac

File tree

5 files changed

+39
-14
lines changed

5 files changed

+39
-14
lines changed

Zend/tests/incdec_undef.phpt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
Inc/dec undef var with error handler
3+
--FILE--
4+
<?php
5+
set_error_handler(function($_, $m) {
6+
echo "$m\n";
7+
unset($GLOBALS['x']);
8+
});
9+
var_dump($x--);
10+
unset($x);
11+
var_dump($x++);
12+
unset($x);
13+
var_dump(--$x);
14+
unset($x);
15+
var_dump(++$x);
16+
?>
17+
--EXPECT--
18+
Undefined variable $x
19+
NULL
20+
Undefined variable $x
21+
NULL
22+
Undefined variable $x
23+
NULL
24+
Undefined variable $x
25+
int(1)

Zend/zend_vm_def.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1470,8 +1470,8 @@ ZEND_VM_HELPER(zend_pre_inc_helper, VAR|CV, ANY)
14701470

14711471
SAVE_OPLINE();
14721472
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
1473-
ZVAL_NULL(var_ptr);
14741473
ZVAL_UNDEFINED_OP1();
1474+
ZVAL_NULL(var_ptr);
14751475
}
14761476

14771477
do {
@@ -1521,8 +1521,8 @@ ZEND_VM_HELPER(zend_pre_dec_helper, VAR|CV, ANY)
15211521

15221522
SAVE_OPLINE();
15231523
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
1524-
ZVAL_NULL(var_ptr);
15251524
ZVAL_UNDEFINED_OP1();
1525+
ZVAL_NULL(var_ptr);
15261526
}
15271527

15281528
do {
@@ -1573,8 +1573,8 @@ ZEND_VM_HELPER(zend_post_inc_helper, VAR|CV, ANY)
15731573

15741574
SAVE_OPLINE();
15751575
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
1576-
ZVAL_NULL(var_ptr);
15771576
ZVAL_UNDEFINED_OP1();
1577+
ZVAL_NULL(var_ptr);
15781578
}
15791579

15801580
do {
@@ -1621,8 +1621,8 @@ ZEND_VM_HELPER(zend_post_dec_helper, VAR|CV, ANY)
16211621

16221622
SAVE_OPLINE();
16231623
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
1624-
ZVAL_NULL(var_ptr);
16251624
ZVAL_UNDEFINED_OP1();
1625+
ZVAL_NULL(var_ptr);
16261626
}
16271627

16281628
do {

Zend/zend_vm_execute.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21156,8 +21156,8 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_inc_help
2115621156

2115721157
SAVE_OPLINE();
2115821158
if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
21159-
ZVAL_NULL(var_ptr);
2116021159
ZVAL_UNDEFINED_OP1();
21160+
ZVAL_NULL(var_ptr);
2116121161
}
2116221162

2116321163
do {
@@ -21225,8 +21225,8 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_dec_help
2122521225

2122621226
SAVE_OPLINE();
2122721227
if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
21228-
ZVAL_NULL(var_ptr);
2122921228
ZVAL_UNDEFINED_OP1();
21229+
ZVAL_NULL(var_ptr);
2123021230
}
2123121231

2123221232
do {
@@ -21295,8 +21295,8 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_inc_hel
2129521295

2129621296
SAVE_OPLINE();
2129721297
if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
21298-
ZVAL_NULL(var_ptr);
2129921298
ZVAL_UNDEFINED_OP1();
21299+
ZVAL_NULL(var_ptr);
2130021300
}
2130121301

2130221302
do {
@@ -21343,8 +21343,8 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_dec_hel
2134321343

2134421344
SAVE_OPLINE();
2134521345
if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
21346-
ZVAL_NULL(var_ptr);
2134721346
ZVAL_UNDEFINED_OP1();
21347+
ZVAL_NULL(var_ptr);
2134821348
}
2134921349

2135021350
do {
@@ -37222,8 +37222,8 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_inc_help
3722237222

3722337223
SAVE_OPLINE();
3722437224
if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
37225-
ZVAL_NULL(var_ptr);
3722637225
ZVAL_UNDEFINED_OP1();
37226+
ZVAL_NULL(var_ptr);
3722737227
}
3722837228

3722937229
do {
@@ -37290,8 +37290,8 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_dec_help
3729037290

3729137291
SAVE_OPLINE();
3729237292
if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
37293-
ZVAL_NULL(var_ptr);
3729437293
ZVAL_UNDEFINED_OP1();
37294+
ZVAL_NULL(var_ptr);
3729537295
}
3729637296

3729737297
do {
@@ -37359,8 +37359,8 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_inc_hel
3735937359

3736037360
SAVE_OPLINE();
3736137361
if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
37362-
ZVAL_NULL(var_ptr);
3736337362
ZVAL_UNDEFINED_OP1();
37363+
ZVAL_NULL(var_ptr);
3736437364
}
3736537365

3736637366
do {
@@ -37406,8 +37406,8 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_dec_hel
3740637406

3740737407
SAVE_OPLINE();
3740837408
if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
37409-
ZVAL_NULL(var_ptr);
3741037409
ZVAL_UNDEFINED_OP1();
37410+
ZVAL_NULL(var_ptr);
3741137411
}
3741237412

3741337413
do {

ext/opcache/jit/zend_jit_arm64.dasc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3757,8 +3757,8 @@ static int zend_jit_inc_dec(dasm_State **Dst, const zend_op *opline, uint32_t op
37573757
| IF_NOT_ZVAL_TYPE op1_addr, IS_UNDEF, >2, ZREG_TMP1
37583758
| // zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(CV_DEF_OF(EX_VAR_TO_NUM(opline->op1.var))));
37593759
| LOAD_32BIT_VAL FCARG1w, opline->op1.var
3760-
| SET_ZVAL_TYPE_INFO op1_addr, IS_NULL, TMP1w, TMP2
37613760
| EXT_CALL zend_jit_undefined_op_helper, REG0
3761+
| SET_ZVAL_TYPE_INFO op1_addr, IS_NULL, TMP1w, TMP2
37623762
op1_info |= MAY_BE_NULL;
37633763
}
37643764
|2:

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4125,8 +4125,8 @@ static int zend_jit_inc_dec(dasm_State **Dst, const zend_op *opline, uint32_t op
41254125
| IF_NOT_ZVAL_TYPE op1_addr, IS_UNDEF, >2
41264126
| // zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(CV_DEF_OF(EX_VAR_TO_NUM(opline->op1.var))));
41274127
| mov FCARG1d, opline->op1.var
4128-
| SET_ZVAL_TYPE_INFO op1_addr, IS_NULL
41294128
| EXT_CALL zend_jit_undefined_op_helper, r0
4129+
| SET_ZVAL_TYPE_INFO op1_addr, IS_NULL
41304130
op1_info |= MAY_BE_NULL;
41314131
}
41324132
|2:

0 commit comments

Comments
 (0)