From: Andi Gutmans Date: Fri, 15 Mar 2002 15:09:46 +0000 (+0000) Subject: - Fix issues with $this when using it by itself without indirection such as X-Git-Tag: php-4.3.0dev-ZendEngine2-Preview1~1391 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0ce019f715c26ef20aa768c08540f6c7d53753ff;p=php - Fix issues with $this when using it by itself without indirection such as - $this->foo. --- diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 235fc5cd0d..674aa0c429 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -285,14 +285,7 @@ void fetch_simple_variable_ex(znode *result, znode *varname, int bp, int op TSRM *result = opline_ptr->result; SET_UNUSED(opline_ptr->op2); - if ((opline_ptr->op1.op_type == IS_CONST) && (opline_ptr->op1.u.constant.type == IS_STRING) && - (opline_ptr->op1.u.constant.value.str.len == (sizeof("this")-1)) && - !memcmp(opline_ptr->op1.u.constant.value.str.val, "this", sizeof("this"))) { - opline_ptr->op2.u.EA.type = ZEND_FETCH_THIS; - efree(varname->u.constant.value.str.val); - memset(&opline_ptr->op1, 0, sizeof(znode)); - SET_UNUSED(opline_ptr->op1); - } else if (varname->op_type == IS_CONST && varname->u.constant.type == IS_STRING + if (varname->op_type == IS_CONST && varname->u.constant.type == IS_STRING && zend_hash_exists(CG(auto_globals), varname->u.constant.value.str.val, varname->u.constant.value.str.len+1)) { opline_ptr->op2.u.EA.type = ZEND_FETCH_GLOBAL; } else { @@ -722,6 +715,7 @@ void zend_do_end_variable_parse(int type, int arg_offset TSRMLS_DC) zend_llist *fetch_list_ptr; zend_llist_element *le; zend_op *opline, *opline_ptr; + int num_of_created_opcodes = 0; /* if (zend_variable_buffer_empty(TSRMLS_C) && (type == BP_VAR_W || type == BP_VAR_RW)) { @@ -763,7 +757,17 @@ void zend_do_end_variable_parse(int type, int arg_offset TSRMLS_DC) break; } le = le->next; + num_of_created_opcodes++; + } + + if (num_of_created_opcodes == 1) { + if ((opline_ptr->op1.op_type == IS_CONST) && (opline_ptr->op1.u.constant.type == IS_STRING) && + (opline_ptr->op1.u.constant.value.str.len == (sizeof("this")-1)) && + !memcmp(opline_ptr->op1.u.constant.value.str.val, "this", sizeof("this"))) { + CG(active_op_array)->uses_this = 1; + } } + zend_llist_destroy(fetch_list_ptr); zend_stack_del_top(&CG(bp_stack)); } @@ -2202,7 +2206,10 @@ void zend_do_fetch_property(znode *result, znode *object, znode *property TSRMLS le = fetch_list_ptr->head; opline_ptr = (zend_op *) le->data; - if (opline_ptr->op1.op_type == IS_UNUSED && opline_ptr->op2.u.EA.type == ZEND_FETCH_THIS) { + if ((opline_ptr->op1.op_type == IS_CONST) && (opline_ptr->op1.u.constant.type == IS_STRING) && + (opline_ptr->op1.u.constant.value.str.len == (sizeof("this")-1)) && + !memcmp(opline_ptr->op1.u.constant.value.str.val, "this", sizeof("this"))) { + efree(opline_ptr->op1.u.constant.value.str.val); opline_ptr->op1 = *property; SET_UNUSED(opline_ptr->op2); opline_ptr->op2.u.EA.type = ZEND_FETCH_FROM_THIS; diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 330bad464c..4dc3a17261 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -103,6 +103,7 @@ struct _zend_op_array { zend_bool return_reference; zend_bool done_pass_two; + zend_bool uses_this; char *filename; @@ -589,7 +590,6 @@ int zendlex(znode *zendlval TSRMLS_DC); #define ZEND_FETCH_STATIC 2 #define ZEND_FETCH_STATIC_MEMBER 3 #define ZEND_FETCH_FROM_THIS 4 -#define ZEND_FETCH_THIS 5 /* class fetches */ #define ZEND_FETCH_CLASS_DEFAULT 0 diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 3eba1da4f8..ed3a25bc40 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -635,22 +635,6 @@ static inline HashTable *zend_get_target_symbol_table(zend_op *opline, temp_vari /* HACK!! 'this' should be always zend_object */ return Z_OBJPROP_P(EG(This)); break; - case ZEND_FETCH_THIS: - { - if (!EG(This)) { - zend_error(E_ERROR, "Using $this when not in object context"); - } - /* FIXME: Put this error back. - //if (type == BP_VAR_RW || type == BP_VAR_W) { - // zend_error(E_ERROR, "Can't overwrite $this"); - //} - */ - Ts[opline->result.u.var].var.ptr_ptr = &EG(This); - SELECTIVE_PZVAL_LOCK(EG(This), &opline->result); - AI_USE_PTR(Ts[opline->result.u.var].var); - return NULL; - break; - } EMPTY_SWITCH_DEFAULT_CASE() } return NULL; @@ -1179,6 +1163,13 @@ ZEND_API void execute(zend_op_array *op_array TSRMLS_DC) EX(opline) = op_array->opcodes; } + if (op_array->uses_this && EG(This)) { + EG(This)->refcount++; /* For $this pointer */ + if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), NULL)==FAILURE) { + EG(This)->refcount--; + } + } + EG(opline_ptr) = &EX(opline); EX(function_state).function = (zend_function *) op_array; @@ -2815,42 +2806,27 @@ send_by_ref: unset_object = (EX(opline)->extended_value == ZEND_UNSET_OBJ); - if (EX(opline)->op2.u.EA.type == ZEND_FETCH_THIS) { - if (!EG(This)) { - zend_error(E_WARNING, "Using $this in non-object context"); - } else { - object = &EG(This); - if(unset_object) { - Z_OBJ_HT_PP(object)->delete_obj((*object)); - zval_ptr_dtor(&EG(This)); - EG(This) = NULL; - } else { - zend_error(E_WARNING, "$this cannot be unset"); - } - } - } else { - if (variable->type != IS_STRING) { - tmp = *variable; - zval_copy_ctor(&tmp); - convert_to_string(&tmp); - variable = &tmp; - } + if (variable->type != IS_STRING) { + tmp = *variable; + zval_copy_ctor(&tmp); + convert_to_string(&tmp); + variable = &tmp; + } - if (unset_object) { - if (zend_hash_find(EG(active_symbol_table), variable->value.str.val, variable->value.str.len+1, (void **)&object) == FAILURE) { - zend_error(E_ERROR, "Cannot delete non-existing object"); - } - if (Z_TYPE_PP(object) != IS_OBJECT) { - zend_error(E_ERROR, "Cannot call delete on non-object type"); - } - Z_OBJ_HT_PP(object)->delete_obj((*object)); + if (unset_object) { + if (zend_hash_find(EG(active_symbol_table), variable->value.str.val, variable->value.str.len+1, (void **)&object) == FAILURE) { + zend_error(E_ERROR, "Cannot delete non-existing object"); } + if (Z_TYPE_PP(object) != IS_OBJECT) { + zend_error(E_ERROR, "Cannot call delete on non-object type"); + } + Z_OBJ_HT_PP(object)->delete_obj((*object)); + } - zend_hash_del(EG(active_symbol_table), variable->value.str.val, variable->value.str.len+1); + zend_hash_del(EG(active_symbol_table), variable->value.str.val, variable->value.str.len+1); - if (variable == &tmp) { - zval_dtor(&tmp); - } + if (variable == &tmp) { + zval_dtor(&tmp); } FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); } @@ -3048,28 +3024,19 @@ send_by_ref: zend_bool isset = 1; HashTable *target_symbol_table; - if (EX(opline)->op2.u.EA.type == ZEND_FETCH_THIS) { - if (!EG(This)) { - isset = 0; - } else { - isset = 1; - value = &EG(This); - } - } else { - target_symbol_table = zend_get_target_symbol_table(EX(opline), EX(Ts), BP_VAR_IS TSRMLS_CC); + target_symbol_table = zend_get_target_symbol_table(EX(opline), EX(Ts), BP_VAR_IS TSRMLS_CC); - if (variable->type != IS_STRING) { - tmp = *variable; - zval_copy_ctor(&tmp); - convert_to_string(&tmp); - variable = &tmp; - } - - if (zend_hash_find(target_symbol_table, variable->value.str.val, variable->value.str.len+1, (void **) &value) == FAILURE) { - isset = 0; - } + if (variable->type != IS_STRING) { + tmp = *variable; + zval_copy_ctor(&tmp); + convert_to_string(&tmp); + variable = &tmp; } - + + if (zend_hash_find(target_symbol_table, variable->value.str.val, variable->value.str.len+1, (void **) &value) == FAILURE) { + isset = 0; + } + EX(Ts)[EX(opline)->result.u.var].tmp_var.type = IS_BOOL; switch (EX(opline)->extended_value) { diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index ed10615c83..221dee43ae 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -87,6 +87,8 @@ void init_op_array(zend_op_array *op_array, int type, int initial_ops_size TSRML op_array->return_reference = 0; op_array->done_pass_two = 0; + op_array->uses_this = 0; + op_array->start_op = NULL; zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_ctor_handler, op_array TSRMLS_CC);