Skip to content

Commit 1b6fae1

Browse files
committed
Thoroughly fix the SWITCH problem. No RETURN handling yet.
1 parent b0c60bd commit 1b6fae1

File tree

4 files changed

+90
-70
lines changed

4 files changed

+90
-70
lines changed

Zend/zend-parser.y

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,11 @@ statement:
161161
| T_FOR
162162
'('
163163
for_expr
164-
';' { do_free(&$3, 0 CLS_CC); $4.u.opline_num = get_next_op_number(CG(active_op_array)); }
164+
';' { do_free(&$3 CLS_CC); $4.u.opline_num = get_next_op_number(CG(active_op_array)); }
165165
for_expr
166166
';' { do_for_cond(&$6, &$7 CLS_CC); }
167167
for_expr
168-
')' { do_free(&$9, 0 CLS_CC); do_for_before_statement(&$4, &$7 CLS_CC); }
168+
')' { do_free(&$9 CLS_CC); do_for_before_statement(&$4, &$7 CLS_CC); }
169169
for_statement { do_for_end(&$7 CLS_CC); }
170170
| T_SWITCH '(' expr ')' { do_switch_cond(&$3 CLS_CC); } switch_case_list { do_switch_end(&$6 CLS_CC); }
171171
| T_BREAK ';' { do_brk_cont(ZEND_BRK, NULL CLS_CC); }
@@ -178,7 +178,7 @@ statement:
178178
| T_STATIC static_var_list
179179
| T_ECHO echo_expr_list ';'
180180
| T_INLINE_HTML { do_echo(&$1 CLS_CC); }
181-
| expr ';' { do_free(&$1, 0 CLS_CC); }
181+
| expr ';' { do_free(&$1 CLS_CC); }
182182
| T_REQUIRE expr ';' { if ($2.op_type==IS_CONST && $2.u.constant.type==IS_STRING) { require_filename($2.u.constant.value.str.val CLS_CC); zval_dtor(&$2.u.constant); } else { do_include_or_eval(ZEND_INCLUDE, &$$, &$2 CLS_CC); } }
183183
| T_UNSET '(' r_cvar ')' ';' { do_unset(&$3 CLS_CC); }
184184
| T_FOREACH '(' expr T_AS { do_foreach_begin(&$1, &$3, &$2, &$4 CLS_CC); } w_cvar foreach_optional_arg ')' { do_foreach_cont(&$6, &$7, &$4 CLS_CC); } foreach_statement { do_foreach_end(&$1, &$2 CLS_CC); }
@@ -358,7 +358,7 @@ echo_expr_list:
358358

359359
for_expr:
360360
/* empty */ { $$.op_type = IS_CONST; $$.u.constant.type = IS_BOOL; $$.u.constant.value.lval = 1; }
361-
| for_expr ',' { do_free(&$1, 0 CLS_CC); } expr { $$ = $4; }
361+
| for_expr ',' { do_free(&$1 CLS_CC); } expr { $$ = $4; }
362362
| expr { $$ = $1; }
363363
;
364364

Zend/zend_compile.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -573,15 +573,15 @@ void do_add_variable(znode *result, znode *op1, znode *op2 CLS_DC)
573573
}
574574

575575

576-
void do_free(znode *op1, int is_used CLS_DC)
576+
void do_free(znode *op1 CLS_DC)
577577
{
578578
if (op1->op_type==IS_TMP_VAR) {
579579
zend_op *opline = get_next_op(CG(active_op_array) CLS_CC);
580580

581581
opline->opcode = ZEND_FREE;
582582
opline->op1 = *op1;
583583
SET_UNUSED(opline->op2);
584-
} else if (!is_used && op1->op_type==IS_VAR) {
584+
} else if (op1->op_type==IS_VAR) {
585585
zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
586586

587587
if (opline->result.op_type == op1->op_type
@@ -1095,7 +1095,10 @@ void do_switch_end(znode *case_list CLS_DC)
10951095
CG(active_op_array)->current_brk_cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].parent;
10961096

10971097
/* emit free for the switch condition*/
1098-
do_free(&switch_entry_ptr->cond, 1 CLS_CC);
1098+
opline = get_next_op(CG(active_op_array) CLS_CC);
1099+
opline->opcode = ZEND_SWITCH_FREE;
1100+
opline->op1 = switch_entry_ptr->cond;
1101+
SET_UNUSED(opline->op2);
10991102
if (switch_entry_ptr->cond.op_type == IS_CONST) {
11001103
zval_dtor(&switch_entry_ptr->cond.u.constant);
11011104
}
@@ -1370,7 +1373,7 @@ void do_end_new_object(znode *class_name, znode *new_token, znode *argument_list
13701373
zval_copy_ctor(&class_name->u.constant);
13711374
}
13721375
do_end_function_call(class_name, &ctor_result, argument_list, 1 CLS_CC);
1373-
do_free(&ctor_result, 0 CLS_CC);
1376+
do_free(&ctor_result CLS_CC);
13741377

13751378
CG(active_op_array)->opcodes[new_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
13761379
}
@@ -1767,7 +1770,7 @@ void do_foreach_cont(znode *value, znode *key, znode *as_token CLS_DC)
17671770
do_assign(&dummy, key, &result_key CLS_CC);
17681771
CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED;
17691772
}
1770-
do_free(as_token, 0 CLS_CC);
1773+
do_free(as_token CLS_CC);
17711774

17721775
do_begin_loop(CLS_C);
17731776
INC_BPC(CG(active_op_array));
@@ -1786,7 +1789,7 @@ void do_foreach_end(znode *foreach_token, znode *open_brackets_token CLS_DC)
17861789

17871790
do_end_loop(foreach_token->u.opline_num CLS_CC);
17881791

1789-
do_free(open_brackets_token, 0 CLS_CC);
1792+
do_free(open_brackets_token CLS_CC);
17901793

17911794
DEC_BPC(CG(active_op_array));
17921795
}

Zend/zend_compile.h

Lines changed: 60 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ void do_post_incdec(znode *result, znode *op1, int op CLS_DC);
250250
void do_begin_variable_parse(CLS_D);
251251
void do_end_variable_parse(int type CLS_DC);
252252

253-
void do_free(znode *op1, int is_used CLS_DC);
253+
void do_free(znode *op1 CLS_DC);
254254

255255
void do_init_string(znode *result CLS_DC);
256256
void do_add_char(znode *result, znode *op1, znode *op2 CLS_DC);
@@ -418,8 +418,8 @@ int zendlex(znode *zendlval CLS_DC);
418418
#define ZEND_ASSIGN 36
419419
#define ZEND_ASSIGN_REF 37
420420

421-
#define ZEND_ECHO 38
422-
#define ZEND_PRINT 39
421+
#define ZEND_ECHO 38
422+
#define ZEND_PRINT 39
423423

424424
#define ZEND_JMP 40
425425
#define ZEND_JMPZ 41
@@ -428,74 +428,75 @@ int zendlex(znode *zendlval CLS_DC);
428428
#define ZEND_JMPZ_EX 44
429429
#define ZEND_JMPNZ_EX 45
430430
#define ZEND_CASE 46
431-
#define ZEND_BRK 47
432-
#define ZEND_CONT 48
433-
#define ZEND_BOOL 49
434-
435-
#define ZEND_INIT_STRING 50
436-
#define ZEND_ADD_CHAR 51
437-
#define ZEND_ADD_STRING 52
438-
#define ZEND_ADD_VAR 53
439-
440-
#define ZEND_BEGIN_SILENCE 54
441-
#define ZEND_END_SILENCE 55
442-
443-
#define ZEND_INIT_FCALL_BY_NAME 56
444-
#define ZEND_DO_FCALL 57
445-
#define ZEND_DO_FCALL_BY_NAME 58
446-
#define ZEND_RETURN 59
447-
448-
#define ZEND_RECV 60
449-
#define ZEND_RECV_INIT 61
431+
#define ZEND_SWITCH_FREE 47
432+
#define ZEND_BRK 48
433+
#define ZEND_CONT 49
434+
#define ZEND_BOOL 50
435+
436+
#define ZEND_INIT_STRING 51
437+
#define ZEND_ADD_CHAR 52
438+
#define ZEND_ADD_STRING 53
439+
#define ZEND_ADD_VAR 54
440+
441+
#define ZEND_BEGIN_SILENCE 55
442+
#define ZEND_END_SILENCE 56
443+
444+
#define ZEND_INIT_FCALL_BY_NAME 57
445+
#define ZEND_DO_FCALL 58
446+
#define ZEND_DO_FCALL_BY_NAME 59
447+
#define ZEND_RETURN 60
448+
449+
#define ZEND_RECV 61
450+
#define ZEND_RECV_INIT 62
450451

451-
#define ZEND_SEND_VAL 62
452-
#define ZEND_SEND_VAR 63
453-
#define ZEND_SEND_REF 64
452+
#define ZEND_SEND_VAL 63
453+
#define ZEND_SEND_VAR 64
454+
#define ZEND_SEND_REF 65
454455

455-
#define ZEND_NEW 65
456-
#define ZEND_JMP_NO_CTOR 66
457-
#define ZEND_FREE 67
456+
#define ZEND_NEW 66
457+
#define ZEND_JMP_NO_CTOR 67
458+
#define ZEND_FREE 68
458459

459-
#define ZEND_INIT_ARRAY 68
460-
#define ZEND_ADD_ARRAY_ELEMENT 69
460+
#define ZEND_INIT_ARRAY 69
461+
#define ZEND_ADD_ARRAY_ELEMENT 70
461462

462-
#define ZEND_INCLUDE_OR_EVAL 70
463+
#define ZEND_INCLUDE_OR_EVAL 71
463464

464-
#define ZEND_UNSET_VAR 71
465-
#define ZEND_UNSET_DIM_OBJ 72
466-
#define ZEND_ISSET_ISEMPTY 73
465+
#define ZEND_UNSET_VAR 72
466+
#define ZEND_UNSET_DIM_OBJ 73
467+
#define ZEND_ISSET_ISEMPTY 74
467468

468-
#define ZEND_FE_RESET 74
469-
#define ZEND_FE_FETCH 75
469+
#define ZEND_FE_RESET 75
470+
#define ZEND_FE_FETCH 76
470471

471-
#define ZEND_EXIT 76
472+
#define ZEND_EXIT 77
472473

473474

474475
/* the following 12 opcodes are 4 groups of 3 opcodes each, and must
475476
* remain in that order!
476477
*/
477-
#define ZEND_FETCH_R 77
478-
#define ZEND_FETCH_DIM_R 78
479-
#define ZEND_FETCH_OBJ_R 79
480-
#define ZEND_FETCH_W 80
481-
#define ZEND_FETCH_DIM_W 81
482-
#define ZEND_FETCH_OBJ_W 82
483-
#define ZEND_FETCH_RW 83
484-
#define ZEND_FETCH_DIM_RW 84
485-
#define ZEND_FETCH_OBJ_RW 85
486-
#define ZEND_FETCH_IS 86
487-
#define ZEND_FETCH_DIM_IS 87
488-
#define ZEND_FETCH_OBJ_IS 88
489-
490-
#define ZEND_FETCH_DIM_TMP_VAR 89
491-
#define ZEND_FETCH_CONSTANT 90
492-
493-
#define ZEND_DECLARE_FUNCTION_OR_CLASS 91
494-
495-
#define ZEND_EXT_STMT 92
496-
#define ZEND_EXT_FCALL_BEGIN 93
497-
#define ZEND_EXT_FCALL_END 94
498-
#define ZEND_EXT_NOP 95
478+
#define ZEND_FETCH_R 78
479+
#define ZEND_FETCH_DIM_R 79
480+
#define ZEND_FETCH_OBJ_R 80
481+
#define ZEND_FETCH_W 81
482+
#define ZEND_FETCH_DIM_W 82
483+
#define ZEND_FETCH_OBJ_W 83
484+
#define ZEND_FETCH_RW 84
485+
#define ZEND_FETCH_DIM_RW 85
486+
#define ZEND_FETCH_OBJ_RW 86
487+
#define ZEND_FETCH_IS 87
488+
#define ZEND_FETCH_DIM_IS 88
489+
#define ZEND_FETCH_OBJ_IS 89
490+
491+
#define ZEND_FETCH_DIM_TMP_VAR 90
492+
#define ZEND_FETCH_CONSTANT 91
493+
494+
#define ZEND_DECLARE_FUNCTION_OR_CLASS 92
495+
496+
#define ZEND_EXT_STMT 93
497+
#define ZEND_EXT_FCALL_BEGIN 94
498+
#define ZEND_EXT_FCALL_END 95
499+
#define ZEND_EXT_NOP 96
499500

500501
/* end of block */
501502

Zend/zend_execute.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1609,13 +1609,29 @@ binary_assign_op_addr: {
16091609
get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R),
16101610
get_zval_ptr(&opline->op2, Ts, &free_op2, BP_VAR_R));
16111611

1612-
FREE_OP(&opline->op1, free_op1);
16131612
FREE_OP(&opline->op2, free_op2);
16141613
if (switch_expr_is_overloaded) {
1614+
/* We only free op1 if this is a string offset,
1615+
* Since if it is a TMP_VAR, it'll be reused by
1616+
* other CASE opcodes (whereas string offsets
1617+
* are allocated at each get_zval_ptr())
1618+
*/
1619+
FREE_OP(&opline->op1, free_op1);
16151620
Ts[opline->op1.u.var].var = NULL;
16161621
}
16171622
}
16181623
break;
1624+
case ZEND_SWITCH_FREE:
1625+
switch (opline->op1.op_type) {
1626+
case IS_VAR:
1627+
get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R);
1628+
FREE_OP(&opline->op1, free_op1);
1629+
break;
1630+
case IS_TMP_VAR:
1631+
zendi_zval_dtor(Ts[opline->op1.u.var].tmp_var);
1632+
break;
1633+
}
1634+
break;
16191635
case ZEND_NEW: {
16201636
zval *tmp = get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R);
16211637
zval class_name;

0 commit comments

Comments
 (0)