6262typedef struct _zend_loop_var {
6363 uint8_t opcode ;
6464 uint8_t var_type ;
65- uint32_t var_num ;
66- uint32_t try_catch_offset ;
67- uint32_t opcode_start ;
65+ union {
66+ struct {
67+ uint32_t var_num ;
68+ uint32_t try_catch_offset ;
69+ };
70+ struct {
71+ uint32_t range_start ;
72+ uint32_t range_end ;
73+ };
74+ };
6875} zend_loop_var ;
6976
7077static inline uint32_t zend_alloc_cache_slots (unsigned count ) {
@@ -345,6 +352,8 @@ void zend_oparray_context_begin(zend_oparray_context *prev_context, zend_op_arra
345352 CG (context ).in_jmp_frameless_branch = false;
346353 CG (context ).active_property_info_name = NULL ;
347354 CG (context ).active_property_hook_kind = (zend_property_hook_kind )- 1 ;
355+ CG (context ).in_block_expr = false;
356+ CG (context ).stmt_start = (uint32_t )-1 ;
348357}
349358/* }}} */
350359
@@ -721,10 +730,8 @@ static inline void zend_begin_loop(
721730 brk_cont_element -> parent = parent ;
722731 brk_cont_element -> kind = kind ;
723732
724- uint32_t start = get_next_op_number ();
725- info .opcode_start = start ;
726-
727733 if (loop_var && (loop_var -> op_type & (IS_VAR |IS_TMP_VAR ))) {
734+ uint32_t start = get_next_op_number ();
728735
729736 info .opcode = free_opcode ;
730737 info .var_type = loop_var -> op_type ;
@@ -5612,27 +5619,22 @@ static bool zend_handle_loops_and_finally_ex(zend_long depth, znode *return_valu
56125619 SET_NODE (opline -> op2 , return_value );
56135620 }
56145621 opline -> op1 .num = loop_var -> try_catch_offset ;
5615- if (free_range_opnum != (uint32_t )-1 ) {
5616- zend_op * opline = & CG (active_op_array )-> opcodes [free_range_opnum ];
5617- opline -> op1 .num = loop_var -> opcode_start ;
5618- free_range_opnum = (uint32_t )-1 ;
5619- }
56205622 } else if (loop_var -> opcode == ZEND_DISCARD_EXCEPTION ) {
56215623 zend_op * opline = get_next_op ();
56225624 opline -> opcode = ZEND_DISCARD_EXCEPTION ;
56235625 opline -> op1_type = IS_TMP_VAR ;
56245626 opline -> op1 .var = loop_var -> var_num ;
56255627 } else if (loop_var -> opcode == ZEND_RETURN ) {
56265628 /* Stack separator */
5627- if (free_range_opnum != (uint32_t )-1 ) {
5628- zend_op * opline = & CG (active_op_array )-> opcodes [free_range_opnum ];
5629- opline -> op1 .num = 0 ;
5630- }
56315629 break ;
56325630 } else {
56335631 if (free_range_opnum != (uint32_t )-1 ) {
56345632 zend_op * opline = & CG (active_op_array )-> opcodes [free_range_opnum ];
5635- opline -> op1 .num = loop_var -> opcode_start + 1 ;
5633+ uint32_t new_start = loop_var -> range_start + (loop_var -> opcode != ZEND_NOP ? 1 : 0 );
5634+ /* We only want to shorten the life-time of ranges, but not extend them. */
5635+ if (opline -> op1 .num < new_start ) {
5636+ opline -> op1 .num = new_start ;
5637+ }
56365638 free_range_opnum = (uint32_t )-1 ;
56375639 }
56385640 /* ZEND_FREE_RANGE does not decrease depth. */
@@ -5648,7 +5650,8 @@ static bool zend_handle_loops_and_finally_ex(zend_long depth, znode *return_valu
56485650 opline -> extended_value = ZEND_FREE_ON_RETURN ;
56495651 if (loop_var -> opcode == ZEND_FREE_RANGE ) {
56505652 free_range_opnum = get_next_op_number () - 1 ;
5651- opline -> op2 .var = loop_var -> opcode_start ;
5653+ opline -> op1 .var = loop_var -> range_start ;
5654+ opline -> op2 .var = loop_var -> range_end ;
56525655 }
56535656 }
56545657 }
@@ -6452,8 +6455,8 @@ static void zend_compile_block_expr(znode *result, zend_ast *ast, bool omit_free
64526455 zend_loop_var info = {0 };
64536456 info .opcode = ZEND_FREE_RANGE ;
64546457 info .var_type = IS_UNUSED ;
6455- info .var_num = ( uint32_t ) -1 ;
6456- info .opcode_start = get_next_op_number ();
6458+ info .range_start = CG ( context ). stmt_start ;
6459+ info .range_end = get_next_op_number ();
64576460 zend_stack_push (& CG (loop_var_stack ), & info );
64586461 }
64596462 zend_compile_stmt_list (ast -> child [0 ]);
@@ -6490,8 +6493,8 @@ static void zend_compile_match(znode *result, zend_ast *ast)
64906493 zend_loop_var info = {0 };
64916494 info .opcode = ZEND_FREE_RANGE ;
64926495 info .var_type = IS_UNUSED ;
6493- info .var_num = ( uint32_t ) -1 ;
6494- info .opcode_start = start_opnum ;
6496+ info .range_start = CG ( context ). stmt_start ;
6497+ info .range_end = start_opnum ;
64956498 zend_stack_push (& CG (loop_var_stack ), & info );
64966499 }
64976500
@@ -6719,7 +6722,6 @@ static void zend_compile_try(zend_ast *ast) /* {{{ */
67196722 }
67206723
67216724 try_catch_offset = zend_add_try_element (get_next_op_number ());
6722- uint32_t try_opnum = get_next_op_number ();
67236725
67246726 if (finally_ast ) {
67256727 zend_loop_var fast_call ;
@@ -6733,7 +6735,6 @@ static void zend_compile_try(zend_ast *ast) /* {{{ */
67336735 fast_call .var_type = IS_TMP_VAR ;
67346736 fast_call .var_num = CG (context ).fast_call_var ;
67356737 fast_call .try_catch_offset = try_catch_offset ;
6736- fast_call .opcode_start = try_opnum ;
67376738 zend_stack_push (& CG (loop_var_stack ), & fast_call );
67386739 }
67396740
@@ -11460,6 +11461,9 @@ static void zend_compile_stmt(zend_ast *ast) /* {{{ */
1146011461 zend_do_extended_stmt ();
1146111462 }
1146211463
11464+ uint32_t prev_stmt_start = CG (context ).stmt_start ;
11465+ CG (context ).stmt_start = get_next_op_number ();
11466+
1146311467 switch (ast -> kind ) {
1146411468 case ZEND_AST_STMT_LIST :
1146511469 zend_compile_stmt_list (ast );
@@ -11555,7 +11559,7 @@ static void zend_compile_stmt(zend_ast *ast) /* {{{ */
1155511559 break ;
1155611560 case ZEND_AST_BLOCK_EXPR :
1155711561 zend_compile_block_expr (NULL , ast , /* omit_free_range */ false);
11558- return ;
11562+ break ;
1155911563 default :
1156011564 {
1156111565 znode result ;
@@ -11564,6 +11568,8 @@ static void zend_compile_stmt(zend_ast *ast) /* {{{ */
1156411568 }
1156511569 }
1156611570
11571+ CG (context ).stmt_start = prev_stmt_start ;
11572+
1156711573 if (FC (declarables ).ticks && !zend_is_unticked_stmt (ast )) {
1156811574 zend_emit_tick ();
1156911575 }
0 commit comments