@@ -2030,14 +2030,27 @@ static void handle_type_narrowing(const zend_op_array *op_array, zend_ssa *ssa,
2030
2030
}
2031
2031
}
2032
2032
2033
- uint32_t zend_array_element_type (uint32_t t1 , int write , int insert )
2033
+ uint32_t zend_array_element_type (zend_op * opline , uint32_t t1 )
2034
2034
{
2035
2035
uint32_t tmp = 0 ;
2036
+ int write = (opline -> opcode != ZEND_FETCH_DIM_R
2037
+ && opline -> opcode != ZEND_FETCH_DIM_IS
2038
+ && opline -> opcode != ZEND_FETCH_LIST_R );
2036
2039
2037
2040
if (t1 & MAY_BE_OBJECT ) {
2038
- tmp |= MAY_BE_ANY | MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF ;
2041
+ if (!write ) {
2042
+ /* can't be REF because of ZVAL_COPY_DEREF() usage */
2043
+ tmp |= MAY_BE_ANY | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF ;
2044
+ } else {
2045
+ tmp |= MAY_BE_ANY | MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF ;
2046
+ }
2039
2047
}
2040
2048
if (t1 & MAY_BE_ARRAY ) {
2049
+ int insert = (opline -> opcode == ZEND_FETCH_DIM_W
2050
+ || opline -> opcode == ZEND_FETCH_DIM_RW
2051
+ || opline -> opcode == ZEND_FETCH_DIM_FUNC_ARG
2052
+ || opline -> opcode == ZEND_FETCH_LIST_W )
2053
+ && opline -> op2_type == IS_UNUSED ;
2041
2054
if (insert ) {
2042
2055
tmp |= MAY_BE_NULL ;
2043
2056
} else {
@@ -2046,7 +2059,12 @@ uint32_t zend_array_element_type(uint32_t t1, int write, int insert)
2046
2059
tmp |= MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF ;
2047
2060
}
2048
2061
if (t1 & MAY_BE_ARRAY_OF_REF ) {
2049
- tmp |= MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN ;
2062
+ if (opline -> opcode == ZEND_FETCH_DIM_R ) {
2063
+ /* can't be REF because of ZVAL_COPY_DEREF() usage */
2064
+ tmp |= MAY_BE_RC1 | MAY_BE_RCN ;
2065
+ } else {
2066
+ tmp |= MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN ;
2067
+ }
2050
2068
} else if (tmp & (MAY_BE_STRING |MAY_BE_ARRAY |MAY_BE_OBJECT |MAY_BE_RESOURCE )) {
2051
2069
tmp |= MAY_BE_RC1 | MAY_BE_RCN ;
2052
2070
}
@@ -2467,7 +2485,7 @@ static int zend_update_type_info(const zend_op_array *op_array,
2467
2485
tmp |= MAY_BE_REF ;
2468
2486
}
2469
2487
orig = t1 ;
2470
- t1 = zend_array_element_type (t1 , 1 , 0 );
2488
+ t1 = zend_array_element_type (opline , t1 );
2471
2489
t2 = OP1_DATA_INFO ();
2472
2490
} else {
2473
2491
if (t1 & MAY_BE_REF ) {
@@ -3278,11 +3296,8 @@ static int zend_update_type_info(const zend_op_array *op_array,
3278
3296
COPY_SSA_OBJ_TYPE (ssa_ops [i ].op1_use , ssa_ops [i ].op1_def );
3279
3297
}
3280
3298
/* FETCH_LIST on a string behaves like FETCH_R on null */
3281
- tmp = zend_array_element_type (
3282
- opline -> opcode != ZEND_FETCH_LIST_R ? t1 : ((t1 & ~MAY_BE_STRING ) | MAY_BE_NULL ),
3283
- opline -> opcode != ZEND_FETCH_DIM_R && opline -> opcode != ZEND_FETCH_DIM_IS
3284
- && opline -> opcode != ZEND_FETCH_LIST_R ,
3285
- opline -> op2_type == IS_UNUSED );
3299
+ tmp = zend_array_element_type (opline ,
3300
+ opline -> opcode != ZEND_FETCH_LIST_R ? t1 : ((t1 & ~MAY_BE_STRING ) | MAY_BE_NULL ));
3286
3301
if (opline -> opcode == ZEND_FETCH_DIM_W ||
3287
3302
opline -> opcode == ZEND_FETCH_DIM_RW ||
3288
3303
opline -> opcode == ZEND_FETCH_DIM_FUNC_ARG ||
@@ -3327,6 +3342,7 @@ static int zend_update_type_info(const zend_op_array *op_array,
3327
3342
if (ssa_ops [i ].result_def >= 0 ) {
3328
3343
tmp = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF ;
3329
3344
if (opline -> opcode == ZEND_FETCH_OBJ_R || opline -> opcode == ZEND_FETCH_OBJ_IS ) {
3345
+ /* can't be REF because of ZVAL_COPY_DEREF() usage */
3330
3346
tmp |= MAY_BE_RC1 | MAY_BE_RCN ;
3331
3347
} else {
3332
3348
tmp |= MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ERROR ;
@@ -3431,6 +3447,14 @@ static int zend_update_type_info(const zend_op_array *op_array,
3431
3447
/* Forbidden opcodes */
3432
3448
ZEND_ASSERT (0 );
3433
3449
break ;
3450
+ case ZEND_FETCH_R :
3451
+ case ZEND_FETCH_IS :
3452
+ case ZEND_FETCH_STATIC_PROP_R :
3453
+ case ZEND_FETCH_STATIC_PROP_IS :
3454
+ /* can't be REF because of ZVAL_COPY_DEREF() usage */
3455
+ tmp = MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF ;
3456
+ UPDATE_SSA_TYPE (tmp , ssa_ops [i ].result_def );
3457
+ break ;
3434
3458
default :
3435
3459
unknown_opcode :
3436
3460
if (ssa_ops [i ].op1_def >= 0 ) {
0 commit comments