From: Andi Gutmans Date: Wed, 29 Sep 1999 17:18:36 +0000 (+0000) Subject: - Fix SEND_VAR problem after fetch'ing a variable and not knowing the fetch type X-Git-Tag: php-4.0b3_RC2~399 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=06d04d15a8c14b90c8a28d9cc8e2000eb51bf277;p=php - Fix SEND_VAR problem after fetch'ing a variable and not knowing the fetch type --- diff --git a/Zend/zend-parser.y b/Zend/zend-parser.y index 5c9f60591c..58d39091fe 100644 --- a/Zend/zend-parser.y +++ b/Zend/zend-parser.y @@ -368,20 +368,20 @@ non_empty_for_expr: expr_without_variable: T_LIST '(' { do_list_init(CLS_C); } assignment_list ')' '=' expr { do_list_end(&$$, &$7 CLS_CC); } - | cvar '=' expr { do_end_variable_parse(BP_VAR_W CLS_CC); do_assign(&$$, &$1, &$3 CLS_CC); } - | cvar '=' '&' w_cvar { do_end_variable_parse(BP_VAR_W CLS_CC); do_assign_ref(&$$, &$1, &$4 CLS_CC); } + | cvar '=' expr { do_end_variable_parse(BP_VAR_W, 0 CLS_CC); do_assign(&$$, &$1, &$3 CLS_CC); } + | cvar '=' '&' w_cvar { do_end_variable_parse(BP_VAR_W, 0 CLS_CC); do_assign_ref(&$$, &$1, &$4 CLS_CC); } | T_NEW class_name { do_extended_fcall_begin(CLS_C); do_begin_new_object(&$1, &$2 CLS_CC); } ctor_arguments { do_end_new_object(&$$, &$2, &$1, &$4 CLS_CC); do_extended_fcall_end(CLS_C);} - | cvar T_PLUS_EQUAL expr { do_end_variable_parse(BP_VAR_RW CLS_CC); do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 CLS_CC); } - | cvar T_MINUS_EQUAL expr { do_end_variable_parse(BP_VAR_RW CLS_CC); do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 CLS_CC); } - | cvar T_MUL_EQUAL expr { do_end_variable_parse(BP_VAR_RW CLS_CC); do_binary_assign_op(ZEND_ASSIGN_MUL, &$$, &$1, &$3 CLS_CC); } - | cvar T_DIV_EQUAL expr { do_end_variable_parse(BP_VAR_RW CLS_CC); do_binary_assign_op(ZEND_ASSIGN_DIV, &$$, &$1, &$3 CLS_CC); } - | cvar T_CONCAT_EQUAL expr { do_end_variable_parse(BP_VAR_RW CLS_CC); do_binary_assign_op(ZEND_ASSIGN_CONCAT, &$$, &$1, &$3 CLS_CC); } - | cvar T_MOD_EQUAL expr { do_end_variable_parse(BP_VAR_RW CLS_CC); do_binary_assign_op(ZEND_ASSIGN_MOD, &$$, &$1, &$3 CLS_CC); } - | cvar T_AND_EQUAL expr { do_end_variable_parse(BP_VAR_RW CLS_CC); do_binary_assign_op(ZEND_ASSIGN_BW_AND, &$$, &$1, &$3 CLS_CC); } - | cvar T_OR_EQUAL expr { do_end_variable_parse(BP_VAR_RW CLS_CC); do_binary_assign_op(ZEND_ASSIGN_BW_OR, &$$, &$1, &$3 CLS_CC); } - | cvar XT_OR_EQUAL expr { do_end_variable_parse(BP_VAR_RW CLS_CC); do_binary_assign_op(ZEND_ASSIGN_BW_XOR, &$$, &$1, &$3 CLS_CC); } - | cvar T_SL_EQUAL expr { do_end_variable_parse(BP_VAR_RW CLS_CC); do_binary_assign_op(ZEND_ASSIGN_SL, &$$, &$1, &$3 CLS_CC); } - | cvar T_SR_EQUAL expr { do_end_variable_parse(BP_VAR_RW CLS_CC); do_binary_assign_op(ZEND_ASSIGN_SR, &$$, &$1, &$3 CLS_CC); } + | cvar T_PLUS_EQUAL expr { do_end_variable_parse(BP_VAR_RW, 0 CLS_CC); do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 CLS_CC); } + | cvar T_MINUS_EQUAL expr { do_end_variable_parse(BP_VAR_RW, 0 CLS_CC); do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 CLS_CC); } + | cvar T_MUL_EQUAL expr { do_end_variable_parse(BP_VAR_RW, 0 CLS_CC); do_binary_assign_op(ZEND_ASSIGN_MUL, &$$, &$1, &$3 CLS_CC); } + | cvar T_DIV_EQUAL expr { do_end_variable_parse(BP_VAR_RW, 0 CLS_CC); do_binary_assign_op(ZEND_ASSIGN_DIV, &$$, &$1, &$3 CLS_CC); } + | cvar T_CONCAT_EQUAL expr { do_end_variable_parse(BP_VAR_RW, 0 CLS_CC); do_binary_assign_op(ZEND_ASSIGN_CONCAT, &$$, &$1, &$3 CLS_CC); } + | cvar T_MOD_EQUAL expr { do_end_variable_parse(BP_VAR_RW, 0 CLS_CC); do_binary_assign_op(ZEND_ASSIGN_MOD, &$$, &$1, &$3 CLS_CC); } + | cvar T_AND_EQUAL expr { do_end_variable_parse(BP_VAR_RW, 0 CLS_CC); do_binary_assign_op(ZEND_ASSIGN_BW_AND, &$$, &$1, &$3 CLS_CC); } + | cvar T_OR_EQUAL expr { do_end_variable_parse(BP_VAR_RW, 0 CLS_CC); do_binary_assign_op(ZEND_ASSIGN_BW_OR, &$$, &$1, &$3 CLS_CC); } + | cvar XT_OR_EQUAL expr { do_end_variable_parse(BP_VAR_RW, 0 CLS_CC); do_binary_assign_op(ZEND_ASSIGN_BW_XOR, &$$, &$1, &$3 CLS_CC); } + | cvar T_SL_EQUAL expr { do_end_variable_parse(BP_VAR_RW, 0 CLS_CC); do_binary_assign_op(ZEND_ASSIGN_SL, &$$, &$1, &$3 CLS_CC); } + | cvar T_SR_EQUAL expr { do_end_variable_parse(BP_VAR_RW, 0 CLS_CC); do_binary_assign_op(ZEND_ASSIGN_SR, &$$, &$1, &$3 CLS_CC); } | rw_cvar T_INC { do_post_incdec(&$$, &$1, ZEND_POST_INC CLS_CC); } | T_INC rw_cvar { do_pre_incdec(&$$, &$2, ZEND_PRE_INC CLS_CC); } | rw_cvar T_DEC { do_post_incdec(&$$, &$1, ZEND_POST_DEC CLS_CC); } @@ -510,17 +510,17 @@ expr: r_cvar: - cvar { do_end_variable_parse(BP_VAR_R CLS_CC); $$ = $1; } + cvar { do_end_variable_parse(BP_VAR_R, 0 CLS_CC); $$ = $1; } ; w_cvar: - cvar { do_end_variable_parse(BP_VAR_W CLS_CC); $$ = $1; } + cvar { do_end_variable_parse(BP_VAR_W, 0 CLS_CC); $$ = $1; } ; rw_cvar: - cvar { do_end_variable_parse(BP_VAR_RW CLS_CC); $$ = $1; } + cvar { do_end_variable_parse(BP_VAR_RW, 0 CLS_CC); $$ = $1; } ; @@ -573,7 +573,7 @@ object_property: scalar_object_property: T_STRING { $$ = $1; } | '{' expr '}' { $$ = $2; } - | cvar_without_objects { do_end_variable_parse(BP_VAR_R CLS_CC); $$ = $1; } + | cvar_without_objects { do_end_variable_parse(BP_VAR_R, 0 CLS_CC); $$ = $1; } ; @@ -615,7 +615,7 @@ non_empty_array_pair_list: encaps_list: - encaps_list encaps_var { do_end_variable_parse(BP_VAR_R CLS_CC); do_add_variable(&$$, &$1, &$2 CLS_CC); } + encaps_list encaps_var { do_end_variable_parse(BP_VAR_R, 0 CLS_CC); do_add_variable(&$$, &$1, &$2 CLS_CC); } | encaps_list T_STRING { do_add_string(&$$, &$1, &$2 CLS_CC); } | encaps_list T_NUM_STRING { do_add_string(&$$, &$1, &$2 CLS_CC); } | encaps_list T_ENCAPSED_AND_WHITESPACE { do_add_string(&$$, &$1, &$2 CLS_CC); } diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 7863dd65ee..16f2da3bf8 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -503,7 +503,7 @@ void do_begin_variable_parse(CLS_D) } -void do_end_variable_parse(int type CLS_DC) +void do_end_variable_parse(int type, int arg_offset CLS_DC) { zend_llist *fetch_list_ptr; zend_llist_element *le; @@ -532,6 +532,11 @@ void do_end_variable_parse(int type CLS_DC) break; case BP_VAR_IS: opline->opcode += 6; /* 3+3 */ + break; + case BP_VAR_FUNC_ARG: + opline->opcode += 9; /* 3+3+3 */ + opline->extended_value = arg_offset; + break; } le = le->next; } @@ -872,13 +877,13 @@ void do_pass_param(znode *param, int op, int offset CLS_DC) switch(op) { case ZEND_SEND_VAR: if (function_ptr) { - do_end_variable_parse(BP_VAR_R CLS_CC); + do_end_variable_parse(BP_VAR_R, 0 CLS_CC); } else { - do_end_variable_parse(BP_VAR_W CLS_CC); + do_end_variable_parse(BP_VAR_FUNC_ARG, offset CLS_CC); } break; case ZEND_SEND_REF: - do_end_variable_parse(BP_VAR_W CLS_CC); + do_end_variable_parse(BP_VAR_W, 0 CLS_CC); break; } } @@ -1820,7 +1825,7 @@ void do_indirect_references(znode *result, znode *num_references, znode *variabl { int i; - do_end_variable_parse(BP_VAR_R CLS_CC); + do_end_variable_parse(BP_VAR_R, 0 CLS_CC); for (i=1; iu.constant.value.lval; i++) { fetch_simple_variable_ex(result, variable, 0, ZEND_FETCH_R CLS_CC); *variable = *result; @@ -1853,7 +1858,7 @@ void do_isset_or_isempty(int type, znode *result, znode *variable CLS_DC) { zend_op *opline; - do_end_variable_parse(BP_VAR_IS CLS_CC); + do_end_variable_parse(BP_VAR_IS, 0 CLS_CC); opline = get_next_op(CG(active_op_array) CLS_CC); opline->opcode = ZEND_ISSET_ISEMPTY; diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index d26adba0d6..5d368d2229 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -250,7 +250,7 @@ void do_pre_incdec(znode *result, znode *op1, int op CLS_DC); void do_post_incdec(znode *result, znode *op1, int op CLS_DC); void do_begin_variable_parse(CLS_D); -void do_end_variable_parse(int type CLS_DC); +void do_end_variable_parse(int type, int arg_offset CLS_DC); void do_free(znode *op1 CLS_DC); @@ -475,7 +475,7 @@ int zendlex(znode *zendlval CLS_DC); #define ZEND_EXIT 77 -/* the following 12 opcodes are 4 groups of 3 opcodes each, and must +/* the following 12 opcodes are 5 groups of 3 opcodes each, and must * remain in that order! */ #define ZEND_FETCH_R 78 @@ -490,16 +490,19 @@ int zendlex(znode *zendlval CLS_DC); #define ZEND_FETCH_IS 87 #define ZEND_FETCH_DIM_IS 88 #define ZEND_FETCH_OBJ_IS 89 +#define ZEND_FETCH_FUNC_ARG 90 +#define ZEND_FETCH_DIM_FUNC_ARG 91 +#define ZEND_FETCH_OBJ_FUNC_ARG 92 -#define ZEND_FETCH_DIM_TMP_VAR 90 -#define ZEND_FETCH_CONSTANT 91 +#define ZEND_FETCH_DIM_TMP_VAR 93 +#define ZEND_FETCH_CONSTANT 94 -#define ZEND_DECLARE_FUNCTION_OR_CLASS 92 +#define ZEND_DECLARE_FUNCTION_OR_CLASS 95 -#define ZEND_EXT_STMT 93 -#define ZEND_EXT_FCALL_BEGIN 94 -#define ZEND_EXT_FCALL_END 95 -#define ZEND_EXT_NOP 96 +#define ZEND_EXT_STMT 96 +#define ZEND_EXT_FCALL_BEGIN 97 +#define ZEND_EXT_FCALL_END 98 +#define ZEND_EXT_NOP 99 /* end of block */ @@ -512,11 +515,12 @@ int zendlex(znode *zendlval CLS_DC); #define ZEND_FETCH_STATIC 2 /* var status for backpatching */ -#define BP_VAR_R 0 -#define BP_VAR_W 1 -#define BP_VAR_RW 2 -#define BP_VAR_IS 3 -#define BP_VAR_NA 4 /* if not applicable */ +#define BP_VAR_R 0 +#define BP_VAR_W 1 +#define BP_VAR_RW 2 +#define BP_VAR_IS 3 +#define BP_VAR_NA 4 /* if not applicable */ +#define BP_VAR_FUNC_ARG 5 #define ZEND_INTERNAL_FUNCTION 1 diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 542a75c1c5..604fdb0702 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -69,6 +69,13 @@ static void zend_extension_fcall_begin_handler(zend_extension *extension, zend_o static void zend_extension_fcall_end_handler(zend_extension *extension, zend_op_array *op_array); +#define ARG_SHOULD_BE_SENT_BY_REF(offset) \ + (function_being_called \ + && function_being_called->common.arg_types \ + && offset<=function_being_called->common.arg_types[0] \ + && function_being_called->common.arg_types[offset]==BYREF_FORCE) + + static inline zval *_get_zval_ptr(znode *node, temp_variable *Ts, int *should_free ELS_DC) { switch(node->op_type) { @@ -1151,6 +1158,16 @@ binary_assign_op_addr: { case ZEND_FETCH_RW: zend_fetch_var_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_RW ELS_CC); break; + case ZEND_FETCH_FUNC_ARG: + if (ARG_SHOULD_BE_SENT_BY_REF(opline->extended_value)) { + /* Behave like FETCH_W */ + zend_fetch_var_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_W ELS_CC); + } else { + /* Behave like FETCH_R */ + zend_fetch_var_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_R ELS_CC); + AI_USE_PTR(Ts[opline->result.u.var].var); + } + break; case ZEND_FETCH_IS: zend_fetch_var_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_IS ELS_CC); break; @@ -1170,6 +1187,16 @@ binary_assign_op_addr: { case ZEND_FETCH_DIM_IS: zend_fetch_dimension_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_IS ELS_CC); break; + case ZEND_FETCH_DIM_FUNC_ARG: + if (ARG_SHOULD_BE_SENT_BY_REF(opline->extended_value)) { + /* Behave like FETCH_DIM_W */ + zend_fetch_dimension_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_W ELS_CC); + } else { + /* Behave like FETCH_DIM_R, except for locking used for list() */ + zend_fetch_dimension_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_R ELS_CC); + AI_USE_PTR(Ts[opline->result.u.var].var); + } + break; case ZEND_FETCH_OBJ_R: zend_fetch_property_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_R ELS_CC); AI_USE_PTR(Ts[opline->result.u.var].var); @@ -1183,6 +1210,15 @@ binary_assign_op_addr: { case ZEND_FETCH_OBJ_IS: zend_fetch_property_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_IS ELS_CC); break; + case ZEND_FETCH_OBJ_FUNC_ARG: + if (ARG_SHOULD_BE_SENT_BY_REF(opline->extended_value)) { + /* Behave like FETCH_OBJ_W */ + zend_fetch_property_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_W ELS_CC); + } else { + zend_fetch_property_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_R ELS_CC); + AI_USE_PTR(Ts[opline->result.u.var].var); + } + break; case ZEND_FETCH_DIM_TMP_VAR: zend_fetch_dimension_address_from_tmp_var(&opline->result, &opline->op1, &opline->op2, Ts ELS_CC); AI_USE_PTR(Ts[opline->result.u.var].var); @@ -1532,10 +1568,7 @@ do_fcall_common: break; case ZEND_SEND_VAL: if (opline->extended_value==ZEND_DO_FCALL_BY_NAME - && function_being_called - && function_being_called->common.arg_types - && opline->op2.u.opline_num<=function_being_called->common.arg_types[0] - && function_being_called->common.arg_types[opline->op2.u.opline_num]==BYREF_FORCE) { + && ARG_SHOULD_BE_SENT_BY_REF(opline->op2.u.opline_num)) { zend_error(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.u.opline_num); } { @@ -1548,10 +1581,7 @@ do_fcall_common: break; case ZEND_SEND_VAR: if (opline->extended_value==ZEND_DO_FCALL_BY_NAME - && function_being_called - && function_being_called->common.arg_types - && opline->op2.u.opline_num<=function_being_called->common.arg_types[0] - && function_being_called->common.arg_types[opline->op2.u.opline_num]==BYREF_FORCE) { + && ARG_SHOULD_BE_SENT_BY_REF(opline->op2.u.opline_num)) { goto send_by_ref; } {