]> granicus.if.org Git - php/commitdiff
- Fix SEND_VAR problem after fetch'ing a variable and not knowing the fetch type
authorAndi Gutmans <andi@php.net>
Wed, 29 Sep 1999 17:18:36 +0000 (17:18 +0000)
committerAndi Gutmans <andi@php.net>
Wed, 29 Sep 1999 17:18:36 +0000 (17:18 +0000)
Zend/zend-parser.y
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute.c

index 5c9f60591c38b2e7dbd3f188ef646a3a460e903a..58d39091fe1d15afe4d9380943bbc36227a7fcd2 100644 (file)
@@ -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); }
index 7863dd65eeb682ccdf04acca02debc481576fcea..16f2da3bf862006dcccb1eee20df7b7b98d77e71 100644 (file)
@@ -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; i<num_references->u.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;
index d26adba0d61a89dc456d0175325e8d7a5b827db6..5d368d22296ac8ba8175deed7764dbb75292196b 100644 (file)
@@ -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
index 542a75c1c539e16a67bf2cd52cdc407fd6b8fca9..604fdb0702ba800674638f53d04fb1cb83e0377b 100644 (file)
@@ -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;
                                }
                                {