@@ -938,32 +938,41 @@ static int zend_dfa_optimize_jmps(zend_op_array *op_array, zend_ssa *ssa)
938
938
|| (opline -> opcode == ZEND_SWITCH_STRING && type == IS_STRING )
939
939
|| (opline -> opcode == ZEND_MATCH && (type == IS_LONG || type == IS_STRING ));
940
940
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 ) {
942
946
removed_ops ++ ;
943
947
MAKE_NOP (opline );
944
948
opline -> extended_value = 0 ;
945
949
take_successor_ex (ssa , block_num , block , block -> successors [block -> successors_count - 1 ]);
946
950
goto optimize_nop ;
947
- } else {
951
+ }
952
+
953
+ uint32_t target ;
954
+ if (correct_type ) {
948
955
HashTable * jmptable = Z_ARRVAL_P (CT_CONSTANT_EX (op_array , opline -> op2 .constant ));
949
956
zval * jmp_zv = type == IS_LONG
950
957
? zend_hash_index_find (jmptable , Z_LVAL_P (zv ))
951
958
: zend_hash_find (jmptable , Z_STR_P (zv ));
952
959
953
- uint32_t target ;
954
960
if (jmp_zv ) {
955
961
target = ZEND_OFFSET_TO_OPLINE_NUM (op_array , opline , Z_LVAL_P (jmp_zv ));
956
962
} else {
957
963
target = ZEND_OFFSET_TO_OPLINE_NUM (op_array , opline , opline -> extended_value );
958
964
}
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 );
966
968
}
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 ;
967
976
}
968
977
break ;
969
978
case ZEND_NOP :
0 commit comments