@@ -1000,32 +1000,41 @@ static int zend_dfa_optimize_jmps(zend_op_array *op_array, zend_ssa *ssa)
10001000 || (opline -> opcode == ZEND_SWITCH_STRING && type == IS_STRING )
10011001 || (opline -> opcode == ZEND_MATCH && (type == IS_LONG || type == IS_STRING ));
10021002
1003- if (!correct_type ) {
1003+ /* Switch statements have a fallback chain for loose comparison. In those
1004+ * cases the SWITCH_* instruction is a NOP. Match does strict comparison and
1005+ * thus jumps to the default branch on mismatched types, so we need to
1006+ * convert MATCH to a jmp. */
1007+ if (!correct_type && opline -> opcode != ZEND_MATCH ) {
10041008 removed_ops ++ ;
10051009 MAKE_NOP (opline );
10061010 opline -> extended_value = 0 ;
10071011 take_successor_ex (ssa , block_num , block , block -> successors [block -> successors_count - 1 ]);
10081012 goto optimize_nop ;
1009- } else {
1013+ }
1014+
1015+ uint32_t target ;
1016+ if (correct_type ) {
10101017 HashTable * jmptable = Z_ARRVAL_P (CT_CONSTANT_EX (op_array , opline -> op2 .constant ));
10111018 zval * jmp_zv = type == IS_LONG
10121019 ? zend_hash_index_find (jmptable , Z_LVAL_P (zv ))
10131020 : zend_hash_find (jmptable , Z_STR_P (zv ));
10141021
1015- uint32_t target ;
10161022 if (jmp_zv ) {
10171023 target = ZEND_OFFSET_TO_OPLINE_NUM (op_array , opline , Z_LVAL_P (jmp_zv ));
10181024 } else {
10191025 target = ZEND_OFFSET_TO_OPLINE_NUM (op_array , opline , opline -> extended_value );
10201026 }
1021- opline -> opcode = ZEND_JMP ;
1022- opline -> extended_value = 0 ;
1023- SET_UNUSED (opline -> op1 );
1024- ZEND_SET_OP_JMP_ADDR (opline , opline -> op1 , op_array -> opcodes + target );
1025- SET_UNUSED (opline -> op2 );
1026- take_successor_ex (ssa , block_num , block , ssa -> cfg .map [target ]);
1027- goto optimize_jmp ;
1027+ } else {
1028+ ZEND_ASSERT (opline -> opcode == ZEND_MATCH );
1029+ target = ZEND_OFFSET_TO_OPLINE_NUM (op_array , opline , opline -> extended_value );
10281030 }
1031+ opline -> opcode = ZEND_JMP ;
1032+ opline -> extended_value = 0 ;
1033+ SET_UNUSED (opline -> op1 );
1034+ ZEND_SET_OP_JMP_ADDR (opline , opline -> op1 , op_array -> opcodes + target );
1035+ SET_UNUSED (opline -> op2 );
1036+ take_successor_ex (ssa , block_num , block , ssa -> cfg .map [target ]);
1037+ goto optimize_jmp ;
10291038 }
10301039 break ;
10311040 case ZEND_NOP :
0 commit comments