@@ -938,32 +938,41 @@ static int zend_dfa_optimize_jmps(zend_op_array *op_array, zend_ssa *ssa)
938938 || (opline -> opcode == ZEND_SWITCH_STRING && type == IS_STRING )
939939 || (opline -> opcode == ZEND_MATCH && (type == IS_LONG || type == IS_STRING ));
940940
941- if (!correct_type ) {
941+ /* Switch statements have a fallback chain for loose comparison. In those
942+ * cases the SWITCH_* instruction is a NOP. Match does strict comparison and
943+ * thus jumps to the default branch on mismatched types, so we need to
944+ * convert MATCH to a jmp. */
945+ if (!correct_type && opline -> opcode != ZEND_MATCH ) {
942946 removed_ops ++ ;
943947 MAKE_NOP (opline );
944948 opline -> extended_value = 0 ;
945949 take_successor_ex (ssa , block_num , block , block -> successors [block -> successors_count - 1 ]);
946950 goto optimize_nop ;
947- } else {
951+ }
952+
953+ uint32_t target ;
954+ if (correct_type ) {
948955 HashTable * jmptable = Z_ARRVAL_P (CT_CONSTANT_EX (op_array , opline -> op2 .constant ));
949956 zval * jmp_zv = type == IS_LONG
950957 ? zend_hash_index_find (jmptable , Z_LVAL_P (zv ))
951958 : zend_hash_find (jmptable , Z_STR_P (zv ));
952959
953- uint32_t target ;
954960 if (jmp_zv ) {
955961 target = ZEND_OFFSET_TO_OPLINE_NUM (op_array , opline , Z_LVAL_P (jmp_zv ));
956962 } else {
957963 target = ZEND_OFFSET_TO_OPLINE_NUM (op_array , opline , opline -> extended_value );
958964 }
959- opline -> opcode = ZEND_JMP ;
960- opline -> extended_value = 0 ;
961- SET_UNUSED (opline -> op1 );
962- ZEND_SET_OP_JMP_ADDR (opline , opline -> op1 , op_array -> opcodes + target );
963- SET_UNUSED (opline -> op2 );
964- take_successor_ex (ssa , block_num , block , ssa -> cfg .map [target ]);
965- goto optimize_jmp ;
965+ } else {
966+ ZEND_ASSERT (opline -> opcode == ZEND_MATCH );
967+ target = ZEND_OFFSET_TO_OPLINE_NUM (op_array , opline , opline -> extended_value );
966968 }
969+ opline -> opcode = ZEND_JMP ;
970+ opline -> extended_value = 0 ;
971+ SET_UNUSED (opline -> op1 );
972+ ZEND_SET_OP_JMP_ADDR (opline , opline -> op1 , op_array -> opcodes + target );
973+ SET_UNUSED (opline -> op2 );
974+ take_successor_ex (ssa , block_num , block , ssa -> cfg .map [target ]);
975+ goto optimize_jmp ;
967976 }
968977 break ;
969978 case ZEND_NOP :
0 commit comments