| T_FOR
'('
for_expr
- ';' { do_free(&$3 CLS_CC); $4.u.opline_num = get_next_op_number(CG(active_op_array)); }
+ ';' { do_free(&$3, 0 CLS_CC); $4.u.opline_num = get_next_op_number(CG(active_op_array)); }
for_expr
';' { do_for_cond(&$6, &$7 CLS_CC); }
for_expr
- ')' { do_free(&$9 CLS_CC); do_for_before_statement(&$4, &$7 CLS_CC); }
+ ')' { do_free(&$9, 0 CLS_CC); do_for_before_statement(&$4, &$7 CLS_CC); }
for_statement { do_for_end(&$7 CLS_CC); }
| T_SWITCH '(' expr ')' { do_switch_cond(&$3 CLS_CC); } switch_case_list { do_switch_end(&$6 CLS_CC); }
| T_BREAK ';' { do_brk_cont(ZEND_BRK, NULL CLS_CC); }
| T_STATIC static_var_list
| T_ECHO echo_expr_list ';'
| T_INLINE_HTML { do_echo(&$1 CLS_CC); }
- | expr ';' { do_free(&$1 CLS_CC); }
+ | expr ';' { do_free(&$1, 0 CLS_CC); }
| 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); } }
| T_UNSET '(' r_cvar ')' ';' { do_unset(&$3 CLS_CC); }
| 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); }
for_expr:
/* empty */ { $$.op_type = IS_CONST; $$.u.constant.type = IS_BOOL; $$.u.constant.value.lval = 1; }
- | for_expr ',' { do_free(&$1 CLS_CC); } expr { $$ = $4; }
+ | for_expr ',' { do_free(&$1, 0 CLS_CC); } expr { $$ = $4; }
| expr { $$ = $1; }
;
}
-void do_free(znode *op1 CLS_DC)
+void do_free(znode *op1, int is_used CLS_DC)
{
if (op1->op_type==IS_TMP_VAR) {
zend_op *opline = get_next_op(CG(active_op_array) CLS_CC);
opline->opcode = ZEND_FREE;
opline->op1 = *op1;
SET_UNUSED(opline->op2);
- } else if (op1->op_type==IS_VAR) {
+ } else if (!is_used && op1->op_type==IS_VAR) {
zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
if (opline->result.op_type == op1->op_type
&& opline->result.u.var == op1->u.var) {
opline->result.u.EA.type |= EXT_TYPE_UNUSED;
} else {
-
/* This should be an object instanciation
* Find JMP_NO_CTOR, mark the preceding ASSIGN and the
* proceeding INIT_FCALL_BY_NAME as unused
CG(active_op_array)->current_brk_cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].parent;
/* emit free for the switch condition*/
- do_free(&switch_entry_ptr->cond CLS_CC);
+ do_free(&switch_entry_ptr->cond, 1 CLS_CC);
if (switch_entry_ptr->cond.op_type == IS_CONST) {
zval_dtor(&switch_entry_ptr->cond.u.constant);
}
zval_copy_ctor(&class_name->u.constant);
}
do_end_function_call(class_name, &ctor_result, argument_list, 1 CLS_CC);
- do_free(&ctor_result CLS_CC);
+ do_free(&ctor_result, 0 CLS_CC);
CG(active_op_array)->opcodes[new_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
}
do_assign(&dummy, key, &result_key CLS_CC);
CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED;
}
- do_free(as_token CLS_CC);
+ do_free(as_token, 0 CLS_CC);
do_begin_loop(CLS_C);
INC_BPC(CG(active_op_array));
do_end_loop(foreach_token->u.opline_num CLS_CC);
- do_free(open_brackets_token CLS_CC);
+ do_free(open_brackets_token, 0 CLS_CC);
DEC_BPC(CG(active_op_array));
}
void do_begin_variable_parse(CLS_D);
void do_end_variable_parse(int type CLS_DC);
-void do_free(znode *op1 CLS_DC);
+void do_free(znode *op1, int is_used CLS_DC);
void do_init_string(znode *result CLS_DC);
void do_add_char(znode *result, znode *op1, znode *op2 CLS_DC);
continue;
}
break;
- case ZEND_CASE:
- if (opline->op1.op_type == IS_VAR) {
- PZVAL_LOCK(*Ts[opline->op1.u.var].var);
+ case ZEND_CASE: {
+ int switch_expr_is_overloaded=0;
+
+ if (opline->op1.op_type==IS_VAR) {
+ if (Ts[opline->op1.u.var].var) {
+ PZVAL_LOCK(*Ts[opline->op1.u.var].var);
+ } else {
+ switch_expr_is_overloaded = 1;
+ if (Ts[opline->op1.u.var].EA.type==IS_STRING_OFFSET) {
+ Ts[opline->op1.u.var].EA.str->refcount++;
+ }
+ }
+ }
+ is_equal_function(&Ts[opline->result.u.var].tmp_var,
+ get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R),
+ get_zval_ptr(&opline->op2, Ts, &free_op2, BP_VAR_R));
+
+ FREE_OP(&opline->op1, free_op1);
+ FREE_OP(&opline->op2, free_op2);
+ if (switch_expr_is_overloaded) {
+ Ts[opline->op1.u.var].var = NULL;
+ }
}
- is_equal_function(&Ts[opline->result.u.var].tmp_var,
- get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R),
- get_zval_ptr(&opline->op2, Ts, &free_op2, BP_VAR_R) );
- FREE_OP(&opline->op2, free_op2);
break;
case ZEND_NEW: {
zval *tmp = get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R);
zval tmp_var;
zval **var;
struct {
- zval **var_dummy; /* a dummy */
+ zval tmp_var; /* a dummy */
zval *str;
int offset;