@@ -3246,7 +3246,7 @@ ZEND_VM_COLD_CONST_HANDLER(47, ZEND_JMPNZ_EX, CONST|TMPVAR|CV, JMP_ADDR)
32463246 ZEND_VM_JMP (opline );
32473247}
32483248
3249- ZEND_VM_HANDLER (70 , ZEND_FREE , TMPVAR , ANY )
3249+ ZEND_VM_HANDLER (70 , ZEND_FREE , TMPVAR , LOOP_END )
32503250{
32513251 USE_OPLINE
32523252
@@ -3255,7 +3255,7 @@ ZEND_VM_HANDLER(70, ZEND_FREE, TMPVAR, ANY)
32553255 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION ();
32563256}
32573257
3258- ZEND_VM_HOT_HANDLER (127 , ZEND_FE_FREE , TMPVAR , ANY )
3258+ ZEND_VM_HOT_HANDLER (127 , ZEND_FE_FREE , TMPVAR , LOOP_END )
32593259{
32603260 zval * var ;
32613261 USE_OPLINE
@@ -8185,24 +8185,11 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
81858185 && throw_op -> extended_value & ZEND_FREE_ON_RETURN ) {
81868186 /* exceptions thrown because of loop var destruction on return/break/...
81878187 * are logically thrown at the end of the foreach loop, so adjust the
8188- * throw_op_num.
8188+ * throw_op_num to the final loop variable FREE .
81898189 */
8190- const zend_live_range * range = find_live_range (
8191- & EX (func )-> op_array , throw_op_num , throw_op -> op1 .var );
8192- /* free op1 of the corresponding RETURN */
8193- for (i = throw_op_num ; i < range -> end ; i ++ ) {
8194- if (EX (func )-> op_array .opcodes [i ].opcode == ZEND_FREE
8195- || EX (func )-> op_array .opcodes [i ].opcode == ZEND_FE_FREE ) {
8196- /* pass */
8197- } else {
8198- if (EX (func )-> op_array .opcodes [i ].opcode == ZEND_RETURN
8199- && (EX (func )-> op_array .opcodes [i ].op1_type & (IS_VAR |IS_TMP_VAR ))) {
8200- zval_ptr_dtor (EX_VAR (EX (func )-> op_array .opcodes [i ].op1 .var ));
8201- }
8202- break ;
8203- }
8204- }
8205- throw_op_num = range -> end ;
8190+ uint32_t new_throw_op_num = throw_op_num + throw_op -> op2 .opline_num ;
8191+ cleanup_live_vars (execute_data , throw_op_num , new_throw_op_num );
8192+ throw_op_num = new_throw_op_num ;
82068193 }
82078194
82088195 /* Find the innermost try/catch/finally the exception was thrown in */
0 commit comments