Skip to content

Commit b45c947

Browse files
committed
Undefined array key should not match null
1 parent ed0b82d commit b45c947

File tree

7 files changed

+28
-11
lines changed

7 files changed

+28
-11
lines changed

Zend/Optimizer/zend_inference.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2130,7 +2130,7 @@ ZEND_API uint32_t ZEND_FASTCALL zend_array_type_info(const zval *zv)
21302130
}
21312131

21322132

2133-
ZEND_API uint32_t zend_array_element_type(uint32_t t1, uint8_t op_type, bool write, bool insert)
2133+
ZEND_API uint32_t zend_array_element_type(uint32_t t1, uint8_t op_type, bool write, bool insert, bool is)
21342134
{
21352135
uint32_t tmp = 0;
21362136

@@ -2149,7 +2149,7 @@ ZEND_API uint32_t zend_array_element_type(uint32_t t1, uint8_t op_type, bool wri
21492149
if (insert) {
21502150
tmp |= MAY_BE_NULL;
21512151
} else {
2152-
tmp |= MAY_BE_NULL | ((t1 & MAY_BE_ARRAY_OF_ANY) >> MAY_BE_ARRAY_SHIFT);
2152+
tmp |= (is ? MAY_BE_UNDEF : MAY_BE_NULL) | ((t1 & MAY_BE_ARRAY_OF_ANY) >> MAY_BE_ARRAY_SHIFT);
21532153
if (tmp & MAY_BE_ARRAY) {
21542154
tmp |= MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
21552155
}
@@ -2760,7 +2760,7 @@ static zend_always_inline zend_result _zend_update_type_info(
27602760
tmp |= MAY_BE_REF;
27612761
}
27622762
orig = t1;
2763-
t1 = zend_array_element_type(t1, opline->op1_type, 1, 0);
2763+
t1 = zend_array_element_type(t1, opline->op1_type, 1, 0, false);
27642764
t2 = OP1_DATA_INFO();
27652765
} else if (opline->opcode == ZEND_ASSIGN_STATIC_PROP_OP) {
27662766
prop_info = zend_fetch_static_prop_info(script, op_array, ssa, opline);
@@ -3741,12 +3741,13 @@ static zend_always_inline zend_result _zend_update_type_info(
37413741
opline->op1_type,
37423742
opline->opcode != ZEND_FETCH_DIM_R && opline->opcode != ZEND_FETCH_DIM_IS
37433743
&& opline->opcode != ZEND_FETCH_LIST_R,
3744-
opline->op2_type == IS_UNUSED);
3744+
opline->op2_type == IS_UNUSED,
3745+
opline->opcode == ZEND_FETCH_DIM_IS);
37453746
if (opline->opcode == ZEND_FETCH_DIM_FUNC_ARG && (t1 & (MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_RESOURCE))) {
37463747
tmp |= MAY_BE_NULL;
37473748
}
37483749
if (opline->opcode == ZEND_FETCH_DIM_IS && (t1 & MAY_BE_STRING)) {
3749-
tmp |= MAY_BE_NULL;
3750+
tmp |= MAY_BE_UNDEF;
37503751
}
37513752
if ((tmp & (MAY_BE_RC1|MAY_BE_RCN)) == MAY_BE_RCN && opline->result_type == IS_TMP_VAR) {
37523753
/* refcount may be indirectly decremented. Make an exception if the result is used in the next instruction */

Zend/Optimizer/zend_inference.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ ZEND_API void zend_ssa_find_false_dependencies(const zend_op_array *op_array, co
223223
ZEND_API void zend_ssa_find_sccs(const zend_op_array *op_array, zend_ssa *ssa);
224224
ZEND_API zend_result zend_ssa_inference(zend_arena **raena, const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_long optimization_level);
225225

226-
ZEND_API uint32_t zend_array_element_type(uint32_t t1, uint8_t op_type, bool write, bool insert);
226+
ZEND_API uint32_t zend_array_element_type(uint32_t t1, uint8_t op_type, bool write, bool insert, bool is);
227227

228228
ZEND_API bool zend_inference_propagate_range(const zend_op_array *op_array, const zend_ssa *ssa, const zend_op *opline, const zend_ssa_op* ssa_op, int var, zend_ssa_range *tmp);
229229

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
Pattern matching: Undefined index should not match null
3+
--FILE--
4+
<?php
5+
6+
var_dump(['a' => 'a'] is ['b' => null]);
7+
8+
?>
9+
--EXPECT--
10+
bool(false)

Zend/zend_execute.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2825,9 +2825,11 @@ static zend_always_inline zval *zend_fetch_dimension_address_inner(HashTable *ht
28252825
zend_undefined_offset(hval);
28262826
ZEND_FALLTHROUGH;
28272827
case BP_VAR_UNSET:
2828-
case BP_VAR_IS:
28292828
retval = &EG(uninitialized_zval);
28302829
break;
2830+
case BP_VAR_IS:
2831+
retval = &EG(undef_zval);
2832+
break;
28312833
case BP_VAR_RW:
28322834
retval = zend_undefined_offset_write(ht, hval);
28332835
break;
@@ -2851,9 +2853,11 @@ static zend_always_inline zval *zend_fetch_dimension_address_inner(HashTable *ht
28512853
zend_undefined_index(offset_key);
28522854
ZEND_FALLTHROUGH;
28532855
case BP_VAR_UNSET:
2854-
case BP_VAR_IS:
28552856
retval = &EG(uninitialized_zval);
28562857
break;
2858+
case BP_VAR_IS:
2859+
retval = &EG(undef_zval);
2860+
break;
28572861
case BP_VAR_RW:
28582862
retval = zend_undefined_index_write(ht, offset_key);
28592863
break;

Zend/zend_execute_API.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ void init_executor(void) /* {{{ */
131131

132132
ZVAL_NULL(&EG(uninitialized_zval));
133133
ZVAL_ERROR(&EG(error_zval));
134+
ZVAL_UNDEF(&EG(undef_zval));
134135
/* destroys stack frame, therefore makes core dumps worthless */
135136
#if 0&&ZEND_DEBUG
136137
original_sigsegv_handler = signal(SIGSEGV, zend_handle_sigsegv);

Zend/zend_globals.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ struct _zend_compiler_globals {
167167
struct _zend_executor_globals {
168168
zval uninitialized_zval;
169169
zval error_zval;
170+
zval undef_zval;
170171

171172
/* symbol table cache */
172173
zend_array *symtable_cache[SYMTABLE_CACHE_SIZE];

ext/opcache/jit/zend_jit_ir.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13419,7 +13419,7 @@ static int zend_jit_assign_dim(zend_jit_ctx *jit,
1341913419
return 0;
1342013420
}
1342113421
} else {
13422-
uint32_t var_info = zend_array_element_type(op1_info, opline->op1_type, 0, 0);
13422+
uint32_t var_info = zend_array_element_type(op1_info, opline->op1_type, 0, 0, false);
1342313423
zend_jit_addr var_addr;
1342413424
ir_ref ref;
1342513425
ir_refs *found_inputs, *found_values;
@@ -13565,7 +13565,7 @@ static int zend_jit_assign_dim_op(zend_jit_ctx *jit,
1356513565
}
1356613566

1356713567
if (op1_info & MAY_BE_ARRAY) {
13568-
uint32_t var_def_info = zend_array_element_type(op1_def_info, opline->op1_type, 1, 0);
13568+
uint32_t var_def_info = zend_array_element_type(op1_def_info, opline->op1_type, 1, 0, false);
1356913569

1357013570
if (opline->op2_type == IS_UNUSED) {
1357113571
var_info = MAY_BE_NULL;
@@ -13593,7 +13593,7 @@ static int zend_jit_assign_dim_op(zend_jit_ctx *jit,
1359313593
ir_refs_init(found_inputs, 8);
1359413594
ir_refs_init(found_values, 8);
1359513595

13596-
var_info = zend_array_element_type(op1_info, opline->op1_type, 0, 0);
13596+
var_info = zend_array_element_type(op1_info, opline->op1_type, 0, 0, false);
1359713597
if (op1_info & (MAY_BE_ARRAY_OF_REF|MAY_BE_OBJECT)) {
1359813598
var_info |= MAY_BE_REF;
1359913599
}

0 commit comments

Comments
 (0)