diff --git a/Zend/zend.c b/Zend/zend.c index a494c97dc94..8b58d4b8b0a 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -144,6 +144,13 @@ static void print_hash(zend_write_func_t write_func, HashTable *ht, int indent, indent += PRINT_ZVAL_INDENT; zend_hash_internal_pointer_reset_ex(ht, &iterator); while ((tmp = zend_hash_get_current_data_ex(ht, &iterator)) != NULL) { + if (Z_TYPE_P(tmp) == IS_INDIRECT) { + tmp = Z_INDIRECT_P(tmp); + if (Z_TYPE_P(tmp) == IS_UNDEF) { + zend_hash_move_forward_ex(ht, &iterator); + continue; + } + } for (i = 0; i < indent; i++) { ZEND_PUTS_EX(" "); } diff --git a/Zend/zend_API.c b/Zend/zend_API.c index e9d30811db7..c0bb644ee20 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1230,6 +1230,70 @@ ZEND_API void object_properties_init(zend_object *object, zend_class_entry *clas } /* }}} */ +ZEND_API void object_properties_init_ex(zend_object *object, HashTable *properties) /* {{{ */ +{ + object->properties = properties; + if (object->ce->default_properties_count) { + HashPosition pos; + zval *prop, tmp; + zend_string *key; + ulong num_key; + zend_property_info *property_info; + + for (zend_hash_internal_pointer_reset_ex(properties, &pos); + (prop = zend_hash_get_current_data_ex(properties, &pos)) != NULL && + zend_hash_get_current_key_ex(properties, &key, &num_key, 0, &pos) == HASH_KEY_IS_STRING; + zend_hash_move_forward_ex(properties, &pos)) { + + ZVAL_STR(&tmp, key); + property_info = zend_get_property_info(object->ce, &tmp, 1 TSRMLS_CC); + if (property_info && + (property_info->flags & ZEND_ACC_STATIC) == 0 && + property_info->offset >= 0) { + ZVAL_COPY_VALUE(&object->properties_table[property_info->offset], prop); + ZVAL_INDIRECT(prop, &object->properties_table[property_info->offset]); + } + } + } +} +/* }}} */ + +ZEND_API void object_properties_load(zend_object *object, HashTable *properties) /* {{{ */ +{ + HashPosition pos; + zval *prop, tmp; + zend_string *key; + ulong num_key; + zend_property_info *property_info; + + for (zend_hash_internal_pointer_reset_ex(properties, &pos); + (prop = zend_hash_get_current_data_ex(properties, &pos)) != NULL && + zend_hash_get_current_key_ex(properties, &key, &num_key, 0, &pos) == HASH_KEY_IS_STRING; + zend_hash_move_forward_ex(properties, &pos)) { + + ZVAL_STR(&tmp, key); + property_info = zend_get_property_info(object->ce, &tmp, 1 TSRMLS_CC); + if (property_info && + (property_info->flags & ZEND_ACC_STATIC) == 0 && + property_info->offset >= 0) { + zval_ptr_dtor(&object->properties_table[property_info->offset]); + ZVAL_COPY_VALUE(&object->properties_table[property_info->offset], prop); + zval_add_ref(&object->properties_table[property_info->offset]); + if (object->properties) { + ZVAL_INDIRECT(&tmp, &object->properties_table[property_info->offset]); + prop = zend_hash_update(object->properties, key, &tmp); + } + } else { + if (!object->properties) { + rebuild_object_properties(object); + } + prop = zend_hash_update(object->properties, key, prop); + zval_add_ref(prop); + } + } +} +/* }}} */ + /* This function requires 'properties' to contain all props declared in the * class and all props being public. If only a subset is given or the class * has protected members then you need to merge the properties separately by @@ -1248,8 +1312,7 @@ ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type if (class_type->create_object == NULL) { ZVAL_OBJ(arg, zend_objects_new(class_type TSRMLS_CC)); if (properties) { - Z_OBJ_P(arg)->properties = properties; -//??? Z_OBJ_P(arg)->properties_table = NULL; + object_properties_init_ex(Z_OBJ_P(arg), properties); } else { object_properties_init(Z_OBJ_P(arg), class_type); } diff --git a/Zend/zend_API.h b/Zend/zend_API.h index d759803345e..c05e430e4c5 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -366,6 +366,8 @@ ZEND_API int _object_init(zval *arg ZEND_FILE_LINE_DC TSRMLS_DC); ZEND_API int _object_init_ex(zval *arg, zend_class_entry *ce ZEND_FILE_LINE_DC TSRMLS_DC); ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *ce, HashTable *properties ZEND_FILE_LINE_DC TSRMLS_DC); ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type); +ZEND_API void object_properties_init_ex(zend_object *object, HashTable *properties); +ZEND_API void object_properties_load(zend_object *object, HashTable *properties); ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destroy_ht TSRMLS_DC); @@ -515,13 +517,12 @@ ZEND_API int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci ZEND_API int zend_set_hash_symbol(zval *symbol, const char *name, int name_length, zend_bool is_ref, int num_symbol_tables, ...); -ZEND_API void zend_delete_variable(zend_execute_data *ex, HashTable *ht, zend_string *name TSRMLS_DC); - ZEND_API int zend_delete_global_variable(zend_string *name TSRMLS_DC); -ZEND_API void zend_reset_all_cv(zend_array *symbol_table TSRMLS_DC); - ZEND_API void zend_rebuild_symbol_table(TSRMLS_D); +ZEND_API void zend_attach_symbol_table(TSRMLS_D); +ZEND_API void zend_detach_symbol_table(TSRMLS_D); +ZEND_API int zend_set_local_var(const char *name, int len, zval *value, int force TSRMLS_DC); ZEND_API zend_string *zend_find_alias_name(zend_class_entry *ce, zend_string *name); ZEND_API zend_string *zend_resolve_method_name(zend_class_entry *ce, zend_function *f); diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 5691fd0b691..06c4774873d 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -593,9 +593,18 @@ ZEND_FUNCTION(each) zend_error(E_WARNING,"Variable passed to each() is not an array or object"); return; } - entry = zend_hash_get_current_data(target_hash); - if (!entry) { - RETURN_FALSE; + while (1) { + entry = zend_hash_get_current_data(target_hash); + if (!entry) { + RETURN_FALSE; + } else if (Z_TYPE_P(entry) == IS_INDIRECT) { + entry = Z_INDIRECT_P(entry); + if (Z_TYPE_P(entry) == IS_UNDEF) { + zend_hash_move_forward(target_hash); + continue; + } + } + break; } array_init(return_value); @@ -999,6 +1008,13 @@ ZEND_FUNCTION(get_object_vars) zend_hash_internal_pointer_reset_ex(properties, &pos); while ((value = zend_hash_get_current_data_ex(properties, &pos)) != NULL) { + if (Z_TYPE_P(value) == IS_INDIRECT) { + value = Z_INDIRECT_P(value); + if (Z_TYPE_P(value) == IS_UNDEF) { + zend_hash_move_forward_ex(properties, &pos); + continue; + } + } if (zend_hash_get_current_key_ex(properties, &key, &num_index, 0, &pos) == HASH_KEY_IS_STRING) { if (zend_check_property_access(zobj, key TSRMLS_CC) == SUCCESS) { zend_unmangle_property_name_ex(key->val, key->len, &class_name, &prop_name, (int*) &prop_len); diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index bc498fee0a4..51f58cf2cd5 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -206,52 +206,31 @@ static zend_always_inline zval *_get_zval_ptr_var_deref(zend_uint var, const zen static zend_never_inline zval *_get_zval_cv_lookup(zval *ptr, zend_uint var, int type TSRMLS_DC) { - zend_string *cv = CV_DEF_OF(var); - zval *ret = NULL; - - if (EG(active_symbol_table)) { - ret = zend_hash_find(&EG(active_symbol_table)->ht, cv); - if (ret) { - ZVAL_INDIRECT(ptr, ret); - return ret; - } - } + zend_string *cv; switch (type) { case BP_VAR_R: case BP_VAR_UNSET: + cv = CV_DEF_OF(var); zend_error(E_NOTICE, "Undefined variable: %s", cv->val); /* break missing intentionally */ case BP_VAR_IS: - return &EG(uninitialized_zval); + ptr = &EG(uninitialized_zval); + break; case BP_VAR_RW: + cv = CV_DEF_OF(var); zend_error(E_NOTICE, "Undefined variable: %s", cv->val); /* break missing intentionally */ case BP_VAR_W: - if (EG(active_symbol_table)) { - ret = zend_hash_update(&EG(active_symbol_table)->ht, cv, ret); - ZVAL_INDIRECT(ptr, ret); - } else { - ZVAL_NULL(ptr); - ret = ptr; - } + ZVAL_NULL(ptr); break; } - return ret; + return ptr; } static zend_never_inline zval *_get_zval_cv_lookup_BP_VAR_R(zval *ptr, zend_uint var TSRMLS_DC) { zend_string *cv = CV_DEF_OF(var); - zval *ret = NULL; - - if (EG(active_symbol_table)) { - ret = zend_hash_find(&EG(active_symbol_table)->ht, cv); - if (ret) { - ZVAL_INDIRECT(ptr, ret); - return ret; - } - } zend_error(E_NOTICE, "Undefined variable: %s", cv->val); return &EG(uninitialized_zval); @@ -260,15 +239,6 @@ static zend_never_inline zval *_get_zval_cv_lookup_BP_VAR_R(zval *ptr, zend_uint static zend_never_inline zval *_get_zval_cv_lookup_BP_VAR_UNSET(zval *ptr, zend_uint var TSRMLS_DC) { zend_string *cv = CV_DEF_OF(var); - zval *ret; - - if (EG(active_symbol_table)) { - ret = zend_hash_find(&EG(active_symbol_table)->ht, cv); - if (ret) { - ZVAL_INDIRECT(ptr, ret); - return ret; - } - } zend_error(E_NOTICE, "Undefined variable: %s", cv->val); return &EG(uninitialized_zval); @@ -276,60 +246,22 @@ static zend_never_inline zval *_get_zval_cv_lookup_BP_VAR_UNSET(zval *ptr, zend_ static zend_never_inline zval *_get_zval_cv_lookup_BP_VAR_IS(zval *ptr, zend_uint var TSRMLS_DC) { - zend_string *cv = CV_DEF_OF(var); - zval *ret; - - if (EG(active_symbol_table)) { - ret = zend_hash_find(&EG(active_symbol_table)->ht, cv); - if (ret) { - ZVAL_INDIRECT(ptr, ret); - return ret; - } - } - return &EG(uninitialized_zval); } static zend_never_inline zval *_get_zval_cv_lookup_BP_VAR_RW(zval *ptr, zend_uint var TSRMLS_DC) { zend_string *cv = CV_DEF_OF(var); - zval *ret; - if (EG(active_symbol_table)) { - ret = zend_hash_find(&EG(active_symbol_table)->ht, cv); - if (ret) { - ZVAL_INDIRECT(ptr, ret); - return ret; - } - ret = zend_hash_update(&EG(active_symbol_table)->ht, cv, &EG(uninitialized_zval)); - ZVAL_INDIRECT(ptr, ret); - zend_error(E_NOTICE, "Undefined variable: %s", cv->val); - return ret; - } else { - ZVAL_NULL(ptr); - zend_error(E_NOTICE, "Undefined variable: %s", cv->val); - return ptr; - } + ZVAL_NULL(ptr); + zend_error(E_NOTICE, "Undefined variable: %s", cv->val); + return ptr; } static zend_never_inline zval *_get_zval_cv_lookup_BP_VAR_W(zval *ptr, zend_uint var TSRMLS_DC) { - zend_string *cv = CV_DEF_OF(var); - zval *ret; - - if (EG(active_symbol_table)) { - ret = zend_hash_find(&EG(active_symbol_table)->ht, cv); - if (ret) { - ZVAL_INDIRECT(ptr, ret); - return ret; - } - ret = zend_hash_update(&EG(active_symbol_table)->ht, cv, &EG(uninitialized_zval)); - ZVAL_INDIRECT(ptr, ret); - return ret; - } else { - ZVAL_NULL(ptr); - return ptr; - } + ZVAL_NULL(ptr); + return ptr; } static zend_always_inline zval *_get_zval_ptr_cv(zend_uint var, int type TSRMLS_DC) @@ -338,8 +270,6 @@ static zend_always_inline zval *_get_zval_ptr_cv(zend_uint var, int type TSRMLS_ if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) { return _get_zval_cv_lookup(ret, var, type TSRMLS_CC); - } else if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) { - ret = Z_INDIRECT_P(ret); } return ret; } @@ -350,8 +280,6 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref(zend_uint var, int type T if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) { return _get_zval_cv_lookup(ret, var, type TSRMLS_CC); - } else if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) { - ret = Z_INDIRECT_P(ret); } if (UNEXPECTED(Z_TYPE_P(ret) == IS_REFERENCE)) { ret = Z_REFVAL_P(ret); @@ -365,8 +293,6 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(const zend_execute_dat if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) { return _get_zval_cv_lookup_BP_VAR_R(ret, var TSRMLS_CC); - } else if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) { - ret = Z_INDIRECT_P(ret); } return ret; } @@ -377,8 +303,6 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_R(const zend_execu if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) { return _get_zval_cv_lookup_BP_VAR_R(ret, var TSRMLS_CC); - } else if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) { - ret = Z_INDIRECT_P(ret); } if (UNEXPECTED(Z_TYPE_P(ret) == IS_REFERENCE)) { ret = Z_REFVAL_P(ret); @@ -392,8 +316,6 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_UNSET(const zend_execute if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) { return _get_zval_cv_lookup_BP_VAR_UNSET(ret, var TSRMLS_CC); - } else if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) { - ret = Z_INDIRECT_P(ret); } return ret; } @@ -404,8 +326,6 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_UNSET(const zend_e if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) { return _get_zval_cv_lookup_BP_VAR_UNSET(ret, var TSRMLS_CC); - } else if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) { - ret = Z_INDIRECT_P(ret); } if (UNEXPECTED(Z_TYPE_P(ret) == IS_REFERENCE)) { ret = Z_REFVAL_P(ret); @@ -419,8 +339,6 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_IS(const zend_execute_da if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) { return _get_zval_cv_lookup_BP_VAR_IS(ret, var TSRMLS_CC); - } else if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) { - ret = Z_INDIRECT_P(ret); } return ret; } @@ -431,8 +349,6 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_IS(const zend_exec if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) { return _get_zval_cv_lookup_BP_VAR_IS(ret, var TSRMLS_CC); - } else if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) { - ret = Z_INDIRECT_P(ret); } if (UNEXPECTED(Z_TYPE_P(ret) == IS_REFERENCE)) { ret = Z_REFVAL_P(ret); @@ -446,8 +362,6 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_RW(const zend_execute_da if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) { return _get_zval_cv_lookup_BP_VAR_RW(ret, var TSRMLS_CC); - } else if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) { - ret = Z_INDIRECT_P(ret); } return ret; } @@ -458,8 +372,6 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_RW(const zend_exec if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) { return _get_zval_cv_lookup_BP_VAR_RW(ret, var TSRMLS_CC); - } else if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) { - ret = Z_INDIRECT_P(ret); } if (UNEXPECTED(Z_TYPE_P(ret) == IS_REFERENCE)) { ret = Z_REFVAL_P(ret); @@ -473,8 +385,6 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(const zend_execute_dat if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) { return _get_zval_cv_lookup_BP_VAR_W(ret, var TSRMLS_CC); - } else if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) { - ret = Z_INDIRECT_P(ret); } return ret; } @@ -485,8 +395,6 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_W(const zend_execu if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) { return _get_zval_cv_lookup_BP_VAR_W(ret, var TSRMLS_CC); - } else if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) { - ret = Z_INDIRECT_P(ret); } if (UNEXPECTED(Z_TYPE_P(ret) == IS_REFERENCE)) { ret = Z_REFVAL_P(ret); @@ -774,10 +682,6 @@ static inline void zend_assign_to_object(zval *retval, zval *object_ptr, zval *p } Z_ADDREF_P(object); zend_error(E_WARNING, "Creating default object from empty value"); -//??? - if (Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } if (Z_REFCOUNT_P(object) == 1) { /* object was removed by error handler, nothing to assign to */ zval_ptr_dtor(object); @@ -790,10 +694,6 @@ static inline void zend_assign_to_object(zval *retval, zval *object_ptr, zval *p Z_DELREF_P(object); } else { zend_error(E_WARNING, "Creating default object from empty value"); -//??? - if (Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } } zval_dtor(object); object_init(object); @@ -1098,7 +998,29 @@ static inline zval *zend_fetch_dimension_address_inner(HashTable *ht, const zval } fetch_string_dim: retval = zend_hash_find(ht, offset_key); - if (retval == NULL) { +// ??? support for $GLOBALS[...] + if (retval) { + if (Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + switch (type) { + case BP_VAR_R: + zend_error(E_NOTICE, "Undefined index: %s", offset_key->val); + /* break missing intentionally */ + case BP_VAR_UNSET: + case BP_VAR_IS: + retval = &EG(uninitialized_zval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined index: %s", offset_key->val); + /* break missing intentionally */ + case BP_VAR_W: + ZVAL_NULL(retval); + break; + } + } + } + } else { switch (type) { case BP_VAR_R: zend_error(E_NOTICE, "Undefined index: %s", offset_key->val); @@ -1247,10 +1169,6 @@ convert_to_array: convert_to_long(&tmp); dim = &tmp; } -//??? container may became IS_INDIRECT because of symtable initialization in zend_error - if (Z_TYPE_P(container) == IS_INDIRECT) { - container = Z_INDIRECT_P(container); - } ZVAL_STR_OFFSET(result, container, Z_LVAL_P(dim)); if (!IS_INTERNED(Z_STR_P(container))) STR_ADDREF(Z_STR_P(container)); return; @@ -1719,16 +1637,12 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*)); } + if (EG(active_symbol_table)) { + zend_attach_symbol_table(TSRMLS_C); + } + if (op_array->this_var != -1 && Z_TYPE(EG(This)) != IS_UNDEF) { - if (!EG(active_symbol_table)) { - ZVAL_COPY(EX_VAR_NUM(op_array->this_var), &EG(This)); - } else { - ZVAL_COPY(EX_VAR_NUM(op_array->this_var), &EG(This)); - zval *zv = zend_hash_str_add(&EG(active_symbol_table)->ht, "this", sizeof("this")-1, EX_VAR(op_array->this_var)); - if (zv) { - ZVAL_INDIRECT(EX_VAR_NUM(op_array->this_var), zv); - } - } + ZVAL_COPY(EX_VAR_NUM(op_array->this_var), &EG(This)); } EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes; diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index a90dade1398..09805179356 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -202,6 +202,9 @@ void init_executor(TSRMLS_D) /* {{{ */ static int zval_call_destructor(zval *zv TSRMLS_DC) /* {{{ */ { + if (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); + } if (Z_TYPE_P(zv) == IS_OBJECT && Z_REFCOUNT_P(zv) == 1) { return ZEND_HASH_APPLY_REMOVE; } else { @@ -210,8 +213,22 @@ static int zval_call_destructor(zval *zv TSRMLS_DC) /* {{{ */ } /* }}} */ +static int zend_unclean_zval_ptr_dtor(zval *zv) /* {{{ */ +{ + TSRMLS_FETCH(); + + if (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); + } + i_zval_ptr_dtor(zv ZEND_FILE_LINE_CC TSRMLS_CC); +} +/* }}} */ + void shutdown_destructors(TSRMLS_D) /* {{{ */ { + if (CG(unclean_shutdown)) { + EG(symbol_table).ht.pDestructor = zend_unclean_zval_ptr_dtor; + } zend_try { int symbols; do { @@ -246,6 +263,10 @@ void shutdown_executor(TSRMLS_D) /* {{{ */ } */ zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_deactivator TSRMLS_CC); + + if (CG(unclean_shutdown)) { + EG(symbol_table).ht.pDestructor = zend_unclean_zval_ptr_dtor; + } zend_hash_graceful_reverse_destroy(&EG(symbol_table).ht); } zend_end_try(); @@ -1638,65 +1659,9 @@ void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC) /* {{{ */ } /* }}} */ -ZEND_API void zend_reset_all_cv(zend_array *symbol_table TSRMLS_DC) /* {{{ */ -{ - zend_execute_data *ex; - int i; - - for (ex = EG(current_execute_data); ex; ex = ex->prev_execute_data) { - if (ex->op_array && ex->symbol_table == symbol_table) { - for (i = 0; i < ex->op_array->last_var; i++) { - ZVAL_UNDEF(EX_VAR_NUM_2(ex, i)); - } - } - } -} -/* }}} */ - -ZEND_API void zend_delete_variable(zend_execute_data *ex, HashTable *ht, zend_string *name TSRMLS_DC) /* {{{ */ -{ - if (zend_hash_del(ht, name) == SUCCESS) { - while (ex && &ex->symbol_table->ht == ht) { - int i; - - if (ex->op_array) { - for (i = 0; i < ex->op_array->last_var; i++) { - if (ex->op_array->vars[i]->h == name->h && - ex->op_array->vars[i]->len == name->len && - !memcmp(ex->op_array->vars[i]->val, name->val, name->len)) { - ZVAL_UNDEF(EX_VAR_NUM_2(ex, i)); - break; - } - } - } - ex = ex->prev_execute_data; - } - } -} -/* }}} */ - ZEND_API int zend_delete_global_variable(zend_string *name TSRMLS_DC) /* {{{ */ { - zend_execute_data *ex; - - if (zend_hash_del(&EG(symbol_table).ht, name) == SUCCESS) { - for (ex = EG(current_execute_data); ex; ex = ex->prev_execute_data) { - if (ex->op_array && ex->symbol_table == &EG(symbol_table)) { - int i; - for (i = 0; i < ex->op_array->last_var; i++) { - if (ex->op_array->vars[i]->h == name->h && - ex->op_array->vars[i]->len == name->len && - !memcmp(ex->op_array->vars[i]->val, name->val, name->len) - ) { - ZVAL_UNDEF(EX_VAR_NUM_2(ex, i)); - break; - } - } - } - } - return SUCCESS; - } - return FAILURE; + return zend_hash_del_ind(&EG(symbol_table).ht, name); } /* }}} */ @@ -1736,18 +1701,97 @@ ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */ ZVAL_COPY_VALUE(EX_VAR_NUM_2(ex, ex->op_array->this_var), &EG(This)); } for (i = 0; i < ex->op_array->last_var; i++) { - if (Z_TYPE_P(EX_VAR_NUM_2(ex, i)) != IS_UNDEF) { - zval *zv = zend_hash_update(&EG(active_symbol_table)->ht, - ex->op_array->vars[i], - EX_VAR_NUM_2(ex, i)); - ZVAL_INDIRECT(EX_VAR_NUM_2(ex, i), zv); - } + zval zv; + + ZVAL_INDIRECT(&zv, EX_VAR_NUM_2(ex, i)); + zend_hash_update(&EG(active_symbol_table)->ht, + ex->op_array->vars[i], &zv); } } } } /* }}} */ +ZEND_API void zend_attach_symbol_table(TSRMLS_D) /* {{{ */ +{ + int i; + zend_execute_data *execute_data = EG(current_execute_data); + zend_op_array *op_array = execute_data->op_array; + HashTable *ht = &EG(active_symbol_table)->ht; + + /* copy real values from symbol table into CV slots and create + INDIRECT references to CV in symbol table */ + for (i = 0; i < op_array->last_var; i++) { + zval *zv = zend_hash_find(ht, op_array->vars[i]); + + if (zv) { + if (Z_TYPE_P(zv) == IS_INDIRECT) { + zval *val = Z_INDIRECT_P(zv); + if (Z_TYPE_P(val) == IS_UNDEF) { + ZVAL_UNDEF(EX_VAR_NUM(i)); + } else { + ZVAL_COPY_VALUE(EX_VAR_NUM(i), val); + } + } else { + ZVAL_COPY_VALUE(EX_VAR_NUM(i), zv); + } + } else { + ZVAL_UNDEF(EX_VAR_NUM(i)); + zv = zend_hash_update(ht, op_array->vars[i], EX_VAR_NUM(i)); + } + ZVAL_INDIRECT(zv, EX_VAR_NUM(i)); + } +} +/* }}} */ + +ZEND_API void zend_detach_symbol_table(TSRMLS_D) /* {{{ */ +{ + int i; + zend_execute_data *execute_data = EG(current_execute_data); + zend_op_array *op_array = execute_data->op_array; + HashTable *ht = &EG(active_symbol_table)->ht; + + /* copy real values from CV slots into symbol table */ + for (i = 0; i < op_array->last_var; i++) { + zend_hash_update(ht, op_array->vars[i], EX_VAR_NUM(i)); + ZVAL_UNDEF(EX_VAR_NUM(i)); + } +} +/* }}} */ + +ZEND_API int zend_set_local_var(const char *name, int len, zval *value, int force TSRMLS_DC) /* {{{ */ +{ + if (!EG(active_symbol_table)) { + int i; + zend_execute_data *execute_data = EG(current_execute_data); + zend_op_array *op_array = execute_data->op_array; + zend_ulong h = zend_hash_func(name, len); + + if (op_array) { + for (i = 0; i < op_array->last_var; i++) { + if (op_array->vars[i]->h == h && + op_array->vars[i]->len == len && + memcmp(op_array->vars[i]->val, name, len) == 0) { + ZVAL_COPY_VALUE(EX_VAR_NUM(i), value); + return SUCCESS; + } + } + } + if (force) { + zend_rebuild_symbol_table(TSRMLS_C); + if (EG(active_symbol_table)) { + zend_hash_str_update(&EG(active_symbol_table)->ht, name, len, value); + } + } else { + return FAILURE; + } + } else { + return zend_hash_str_update_ind(&EG(active_symbol_table)->ht, name, len, value); + } + return SUCCESS; +} +/* }}} */ + /* * Local variables: * tab-width: 4 diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c index 54fd532fc77..dca99c09113 100644 --- a/Zend/zend_gc.c +++ b/Zend/zend_gc.c @@ -557,7 +557,7 @@ tail_call: p = ht->arData + idx; if (!Z_REFCOUNTED(p->val)) { /* count non-refcounted for compatibilty ??? */ - if (Z_TYPE(p->val) != IS_UNDEF) { + if (Z_TYPE(p->val) != IS_UNDEF && Z_TYPE(p->val) != IS_INDIRECT) { count++; } continue; diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index be2b0c742b5..3cfc62e7a14 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -267,17 +267,23 @@ ZEND_API zval *_zend_hash_add_or_update(HashTable *ht, zend_string *key, zval *p p = zend_hash_find_bucket(ht, key); if (p) { + zval *data; + if (flag & HASH_ADD) { return NULL; } ZEND_ASSERT(&p->val != pData); + data = &p->val; + if ((flag & HASH_UPDATE_INDIRECT) && Z_TYPE_P(data) == IS_INDIRECT) { + data = Z_INDIRECT_P(data); + } HANDLE_BLOCK_INTERRUPTIONS(); if (ht->pDestructor) { - ht->pDestructor(&p->val); + ht->pDestructor(data); } - ZVAL_COPY_VALUE(&p->val, pData); + ZVAL_COPY_VALUE(data, pData); HANDLE_UNBLOCK_INTERRUPTIONS(); - return &p->val; + return data; } ZEND_HASH_IF_FULL_DO_RESIZE(ht); /* If the Hash table is full, resize it */ @@ -588,6 +594,58 @@ ZEND_API int zend_hash_del(HashTable *ht, zend_string *key) return FAILURE; } +ZEND_API int zend_hash_del_ind(HashTable *ht, zend_string *key) +{ + ulong h; + uint nIndex; + uint idx; + Bucket *p; + Bucket *prev = NULL; +#ifdef ZEND_SIGNALS + TSRMLS_FETCH(); +#endif + + IS_CONSISTENT(ht); + + if (ht->flags & HASH_FLAG_PACKED) { + return FAILURE; + } + + h = STR_HASH_VAL(key); + nIndex = h & ht->nTableMask; + + idx = ht->arHash[nIndex]; + while (idx != INVALID_IDX) { + p = ht->arData + idx; + if ((p->key == key) || + (p->h == h && + p->key && + p->key->len == key->len && + memcmp(p->key->val, key->val, key->len) == 0)) { + if (Z_TYPE(p->val) == IS_INDIRECT) { + zval *data = Z_INDIRECT(p->val); + + if (Z_TYPE_P(data) == IS_UNDEF) { + return FAILURE; + } else { + if (ht->pDestructor) { + ht->pDestructor(data); + } + ZVAL_UNDEF(data); + } + } else { + HANDLE_BLOCK_INTERRUPTIONS(); + _zend_hash_del_el_ex(ht, idx, p, prev); + HANDLE_UNBLOCK_INTERRUPTIONS(); + } + return SUCCESS; + } + prev = p; + idx = p->val.u.next; + } + return FAILURE; +} + ZEND_API int zend_hash_str_del(HashTable *ht, const char *str, int len) { ulong h; @@ -604,6 +662,53 @@ ZEND_API int zend_hash_str_del(HashTable *ht, const char *str, int len) h = zend_inline_hash_func(str, len); nIndex = h & ht->nTableMask; + idx = ht->arHash[nIndex]; + while (idx != INVALID_IDX) { + p = ht->arData + idx; + if ((p->h == h) + && p->key + && (p->key->len == len) + && !memcmp(p->key->val, str, len)) { + if (Z_TYPE(p->val) == IS_INDIRECT) { + zval *data = Z_INDIRECT(p->val); + + if (Z_TYPE_P(data) == IS_UNDEF) { + return FAILURE; + } else { + if (ht->pDestructor) { + ht->pDestructor(data); + } + ZVAL_UNDEF(data); + } + } else { + HANDLE_BLOCK_INTERRUPTIONS(); + _zend_hash_del_el_ex(ht, idx, p, prev); + HANDLE_UNBLOCK_INTERRUPTIONS(); + } + return SUCCESS; + } + prev = p; + idx = p->val.u.next; + } + return FAILURE; +} + +ZEND_API int zend_hash_str_del_ind(HashTable *ht, const char *str, int len) +{ + ulong h; + uint nIndex; + uint idx; + Bucket *p; + Bucket *prev = NULL; +#ifdef ZEND_SIGNALS + TSRMLS_FETCH(); +#endif + + IS_CONSISTENT(ht); + + h = zend_inline_hash_func(str, len); + nIndex = h & ht->nTableMask; + idx = ht->arHash[nIndex]; while (idx != INVALID_IDX) { p = ht->arData + idx; @@ -914,7 +1019,7 @@ ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_fun { uint idx; Bucket *p; - zval *new_entry; + zval *new_entry, *data; zend_bool setTargetPointer; IS_CONSISTENT(source); @@ -928,10 +1033,18 @@ ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_fun if (setTargetPointer && source->nInternalPointer == idx) { target->nInternalPointer = INVALID_IDX; } +//??? + data = &p->val; + if (Z_TYPE_P(data) == IS_INDIRECT) { + data = Z_INDIRECT_P(data); + if (Z_TYPE_P(data) == IS_UNDEF) { + continue; + } + } if (p->key) { - new_entry = zend_hash_update(target, p->key, &p->val); + new_entry = zend_hash_update(target, p->key, data); } else { - new_entry = zend_hash_index_update(target, p->h, &p->val); + new_entry = zend_hash_index_update(target, p->h, data); } if (pCopyConstructor) { pCopyConstructor(new_entry); @@ -1551,7 +1664,7 @@ ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t co uint idx1, idx2; Bucket *p1, *p2 = NULL; int result; - zval *pData2; + zval *pData1, *pData2; IS_CONSISTENT(ht1); IS_CONSISTENT(ht2); @@ -1620,7 +1733,22 @@ ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t co } } } - result = compar(&p1->val, pData2 TSRMLS_CC); + pData1 = &p1->val; + if (Z_TYPE_P(pData1) == IS_INDIRECT) { + pData1 = Z_INDIRECT_P(pData1); + } + if (Z_TYPE_P(pData2) == IS_INDIRECT) { + pData2 = Z_INDIRECT_P(pData2); + } + if (Z_TYPE_P(pData1) == IS_UNDEF) { + if (Z_TYPE_P(pData2) != IS_UNDEF) { + return -1; + } + } else if (Z_TYPE_P(pData2) == IS_UNDEF) { + return 1; + } else { + result = compar(pData1, pData2 TSRMLS_CC); + } if (result != 0) { HASH_UNPROTECT_RECURSION(ht1); HASH_UNPROTECT_RECURSION(ht2); diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index 2718356497f..b9918304cdd 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -30,9 +30,10 @@ #define HASH_KEY_NON_EXISTENT 3 #define HASH_KEY_NON_EXISTANT HASH_KEY_NON_EXISTENT /* Keeping old define (with typo) for backward compatibility */ -#define HASH_UPDATE (1<<0) -#define HASH_ADD (1<<1) -#define HASH_NEXT_INSERT (1<<2) +#define HASH_UPDATE (1<<0) +#define HASH_ADD (1<<1) +#define HASH_NEXT_INSERT (1<<2) +#define HASH_UPDATE_INDIRECT (1<<3) #define HASH_UPDATE_KEY_IF_NONE 0 #define HASH_UPDATE_KEY_IF_BEFORE 1 @@ -74,12 +75,16 @@ ZEND_API void zend_hash_to_packed(HashTable *ht); ZEND_API zval *_zend_hash_add_or_update(HashTable *ht, zend_string *key, zval *pData, int flag ZEND_FILE_LINE_DC); #define zend_hash_update(ht, key, pData) \ _zend_hash_add_or_update(ht, key, pData, HASH_UPDATE ZEND_FILE_LINE_CC) +#define zend_hash_update_ind(ht, key, pData) \ + _zend_hash_add_or_update(ht, key, pData, HASH_UPDATE | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_CC) #define zend_hash_add(ht, key, pData) \ _zend_hash_add_or_update(ht, key, pData, HASH_ADD ZEND_FILE_LINE_CC) ZEND_API zval *_zend_hash_str_add_or_update(HashTable *ht, const char *key, int len, zval *pData, int flag ZEND_FILE_LINE_DC); #define zend_hash_str_update(ht, key, len, pData) \ _zend_hash_str_add_or_update(ht, key, len, pData, HASH_UPDATE ZEND_FILE_LINE_CC) +#define zend_hash_str_update_ind(ht, key, len, pData) \ + _zend_hash_str_add_or_update(ht, key, len, pData, HASH_UPDATE | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_CC) #define zend_hash_str_add(ht, key, len, pData) \ _zend_hash_str_add_or_update(ht, key, len, pData, HASH_ADD ZEND_FILE_LINE_CC) @@ -117,7 +122,9 @@ ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSR /* Deletes */ ZEND_API int zend_hash_del(HashTable *ht, zend_string *key); +ZEND_API int zend_hash_del_ind(HashTable *ht, zend_string *key); ZEND_API int zend_hash_str_del(HashTable *ht, const char *key, int len); +ZEND_API int zend_hash_str_del_ind(HashTable *ht, const char *key, int len); ZEND_API int zend_hash_index_del(HashTable *ht, ulong h); /* Data retreival */ @@ -244,6 +251,25 @@ END_EXTERN_C() ZEND_HANDLE_NUMERIC_EX(key, length, idx, return func); \ } while (0) + +static inline zval *zend_hash_find_ind(const HashTable *ht, zend_string *key) +{ + zval *zv; + + zv = zend_hash_find(ht, key); + return (zv && Z_TYPE_P(zv) == IS_INDIRECT) ? Z_INDIRECT_P(zv) : zv; +} + + +static inline zval *zend_hash_str_find_ind(const HashTable *ht, const char *str, int len) +{ + zval *zv; + + zv = zend_hash_str_find(ht, str, len); + return (zv && Z_TYPE_P(zv) == IS_INDIRECT) ? Z_INDIRECT_P(zv) : zv; +} + + static inline zval *zend_symtable_update(HashTable *ht, zend_string *key, zval *pData) { ZEND_HANDLE_NUMERIC(key->val, key->len+1, zend_hash_index_update(ht, idx, pData)); @@ -251,6 +277,13 @@ static inline zval *zend_symtable_update(HashTable *ht, zend_string *key, zval * } +static inline zval *zend_symtable_update_ind(HashTable *ht, zend_string *key, zval *pData) +{ + ZEND_HANDLE_NUMERIC(key->val, key->len+1, zend_hash_index_update(ht, idx, pData)); + return zend_hash_update_ind(ht, key, pData); +} + + static inline int zend_symtable_del(HashTable *ht, zend_string *key) { ZEND_HANDLE_NUMERIC(key->val, key->len+1, zend_hash_index_del(ht, idx)); @@ -258,6 +291,13 @@ static inline int zend_symtable_del(HashTable *ht, zend_string *key) } +static inline int zend_symtable_del_ind(HashTable *ht, zend_string *key) +{ + ZEND_HANDLE_NUMERIC(key->val, key->len+1, zend_hash_index_del(ht, idx)); + return zend_hash_del_ind(ht, key); +} + + static inline zval *zend_symtable_find(const HashTable *ht, zend_string *key) { ZEND_HANDLE_NUMERIC(key->val, key->len+1, zend_hash_index_find(ht, idx)); @@ -265,12 +305,20 @@ static inline zval *zend_symtable_find(const HashTable *ht, zend_string *key) } +static inline zval *zend_symtable_find_ind(const HashTable *ht, zend_string *key) +{ + ZEND_HANDLE_NUMERIC(key->val, key->len+1, zend_hash_index_find(ht, idx)); + return zend_hash_find_ind(ht, key); +} + + static inline int zend_symtable_exists(HashTable *ht, zend_string *key) { ZEND_HANDLE_NUMERIC(key->val, key->len+1, zend_hash_index_exists(ht, idx)); return zend_hash_exists(ht, key); } + static inline zval *zend_symtable_str_update(HashTable *ht, const char *str, int len, zval *pData) { ZEND_HANDLE_NUMERIC(str, len+1, zend_hash_index_update(ht, idx, pData)); @@ -278,6 +326,13 @@ static inline zval *zend_symtable_str_update(HashTable *ht, const char *str, int } +static inline zval *zend_symtable_str_update_ind(HashTable *ht, const char *str, int len, zval *pData) +{ + ZEND_HANDLE_NUMERIC(str, len+1, zend_hash_index_update(ht, idx, pData)); + return zend_hash_str_update_ind(ht, str, len, pData); +} + + static inline int zend_symtable_str_del(HashTable *ht, const char *str, int len) { ZEND_HANDLE_NUMERIC(str, len+1, zend_hash_index_del(ht, idx)); @@ -285,6 +340,13 @@ static inline int zend_symtable_str_del(HashTable *ht, const char *str, int len) } +static inline int zend_symtable_str_del_ind(HashTable *ht, const char *str, int len) +{ + ZEND_HANDLE_NUMERIC(str, len+1, zend_hash_index_del(ht, idx)); + return zend_hash_str_del_ind(ht, str, len); +} + + static inline zval *zend_symtable_str_find(HashTable *ht, const char *str, int len) { ZEND_HANDLE_NUMERIC(str, len+1, zend_hash_index_find(ht, idx)); diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 24a3a9ebd8a..3d821993af4 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -85,10 +85,10 @@ ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */ (prop_info->flags & ZEND_ACC_STATIC) == 0 && prop_info->offset >= 0 && Z_TYPE(zobj->properties_table[prop_info->offset]) != IS_UNDEF) { - zval *zv = zend_hash_add(zobj->properties, prop_info->name, &zobj->properties_table[prop_info->offset]); - if (EXPECTED(zv != NULL)) { - ZVAL_INDIRECT(&zobj->properties_table[prop_info->offset], zv); - } + zval zv; + + ZVAL_INDIRECT(&zv, &zobj->properties_table[prop_info->offset]); + zend_hash_add(zobj->properties, prop_info->name, &zv); } } while (ce->parent && ce->parent->default_properties_count) { @@ -101,10 +101,10 @@ ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */ (prop_info->flags & ZEND_ACC_PRIVATE) != 0 && prop_info->offset >= 0 && Z_TYPE(zobj->properties_table[prop_info->offset]) != IS_UNDEF) { - zval *zv = zend_hash_add(zobj->properties, prop_info->name, &zobj->properties_table[prop_info->offset]); - if (EXPECTED(zv != NULL)) { - ZVAL_INDIRECT(&zobj->properties_table[prop_info->offset], zv); - } + zval zv; + + ZVAL_INDIRECT(&zv, &zobj->properties_table[prop_info->offset]); + zend_hash_add(zobj->properties, prop_info->name, &zv); } } } @@ -133,15 +133,9 @@ ZEND_API HashTable *zend_std_get_gc(zval *object, zval **table, int *n TSRMLS_DC } else { zend_object *zobj = Z_OBJ_P(object); - if (zobj->properties) { - *table = NULL; - *n = 0; - return zobj->properties; - } else { - *table = zobj->properties_table; - *n = zobj->ce->default_properties_count; - return NULL; - } + *table = zobj->properties_table; + *n = zobj->ce->default_properties_count; + return zobj->properties; } } /* }}} */ @@ -454,20 +448,18 @@ zval *zend_std_read_property(zval *object, zval *member, int type, const zend_li if (EXPECTED(property_info != NULL)) { if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && - property_info->offset >= 0 && - Z_TYPE(zobj->properties_table[property_info->offset]) != IS_UNDEF) { + property_info->offset >= 0) { retval = &zobj->properties_table[property_info->offset]; - if (Z_TYPE_P(retval) == IS_INDIRECT) { - retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) != IS_UNDEF) { + goto exit; } - goto exit; - } - if (UNEXPECTED(zobj->properties != NULL)) { + } else if (UNEXPECTED(zobj->properties != NULL)) { retval = zend_hash_find(zobj->properties, property_info->name); if (retval) goto exit; } } + /* magic get */ if (zobj->ce->__get) { long *guard = zend_get_property_guard(zobj, property_info, member); if (!((*guard) & IN_GET)) { @@ -534,6 +526,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type, const zend_li } retval = &EG(uninitialized_zval); } + exit: if (UNEXPECTED(Z_TYPE(tmp_member) != IS_UNDEF)) { if (Z_REFCOUNTED_P(retval)) Z_ADDREF_P(retval); @@ -565,15 +558,12 @@ ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, c if (EXPECTED(property_info != NULL)) { if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && - property_info->offset >= 0 && - Z_TYPE(zobj->properties_table[property_info->offset]) != IS_UNDEF) { + property_info->offset >= 0) { variable_ptr = &zobj->properties_table[property_info->offset]; - if (Z_TYPE_P(variable_ptr) == IS_INDIRECT) { - variable_ptr = Z_INDIRECT_P(variable_ptr); + if (Z_TYPE_P(variable_ptr) != IS_UNDEF) { + goto found; } - goto found; - } - if (EXPECTED(zobj->properties != NULL)) { + } else if (EXPECTED(zobj->properties != NULL)) { if ((variable_ptr = zend_hash_find(zobj->properties, property_info->name)) != NULL) { found: /* if we already have this value there, we don't actually need to do anything */ @@ -607,11 +597,12 @@ found: zval_ptr_dtor(&garbage); } } - return; + goto exit; } } } + /* magic set */ if (zobj->ce->__set) { long *guard = zend_get_property_guard(zobj, property_info, member); @@ -653,12 +644,7 @@ write_std_property: if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && property_info->offset >= 0) { - if (zobj->properties) { - zval *zv = zend_hash_update(zobj->properties, property_info->name, value); - ZVAL_INDIRECT(&zobj->properties_table[property_info->offset], zv); - } else { - ZVAL_COPY_VALUE(&zobj->properties_table[property_info->offset], value); - } + ZVAL_COPY_VALUE(&zobj->properties_table[property_info->offset], value); } else { if (!zobj->properties) { rebuild_object_properties(zobj); @@ -667,6 +653,7 @@ write_std_property: } } +exit: if (UNEXPECTED(Z_TYPE(tmp_member) != IS_UNDEF)) { zval_ptr_dtor(&tmp_member); } @@ -785,15 +772,12 @@ static zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int type, if (EXPECTED(property_info != NULL)) { if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && - property_info->offset >= 0 && - Z_TYPE(zobj->properties_table[property_info->offset]) != IS_UNDEF) { + property_info->offset >= 0) { retval = &zobj->properties_table[property_info->offset]; - if (Z_TYPE_P(retval) == IS_INDIRECT) { - retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) != IS_UNDEF) { + goto exit; } - goto exit; - } - if (UNEXPECTED(zobj->properties != NULL)) { + } else if (UNEXPECTED(zobj->properties != NULL)) { retval = zend_hash_find(zobj->properties, property_info->name); if (retval) goto exit; } @@ -810,13 +794,8 @@ static zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int type, ZVAL_NULL(&tmp); if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && property_info->offset >= 0) { - if (zobj->properties) { - retval = zend_hash_update(zobj->properties, property_info->name, &tmp); - ZVAL_INDIRECT(&zobj->properties_table[property_info->offset], retval); - } else { - retval = &zobj->properties_table[property_info->offset]; - ZVAL_NULL(retval); - } + retval = &zobj->properties_table[property_info->offset]; + ZVAL_NULL(retval); } else { if (!zobj->properties) { rebuild_object_properties(zobj); @@ -854,36 +833,39 @@ static void zend_std_unset_property(zval *object, zval *member, const zend_liter property_info = zend_get_property_info_quick(zobj->ce, member, (zobj->ce->__unset != NULL), key TSRMLS_CC); - if (EXPECTED(property_info != NULL) && - EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && - property_info->offset >= 0) { - zval_ptr_dtor(&zobj->properties_table[property_info->offset]); - ZVAL_UNDEF(&zobj->properties_table[property_info->offset]); - if (!zobj->properties) goto exit; + if (EXPECTED(property_info != NULL)) { + if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && + property_info->offset >= 0) { + if (Z_TYPE(zobj->properties_table[property_info->offset]) != IS_UNDEF) { + zval_ptr_dtor(&zobj->properties_table[property_info->offset]); + ZVAL_UNDEF(&zobj->properties_table[property_info->offset]); + goto exit; + } + } else if (zobj->properties && + UNEXPECTED(zend_hash_del(zobj->properties, property_info->name) != FAILURE)) { + goto exit; + } } - if (UNEXPECTED(!property_info) || - !zobj->properties || - UNEXPECTED(zend_hash_del(zobj->properties, property_info->name) == FAILURE)) { - if (zobj->ce->__unset) { - long *guard = zend_get_property_guard(zobj, property_info, member); - if (!((*guard) & IN_UNSET)) { - /* have unseter - try with it! */ - Z_ADDREF_P(object); - if (Z_ISREF_P(object)) { - SEPARATE_ZVAL(object); - } - (*guard) |= IN_UNSET; /* prevent circular unsetting */ - zend_std_call_unsetter(object, member TSRMLS_CC); - (*guard) &= ~IN_UNSET; - zval_ptr_dtor(object); - } else { - if (Z_STRVAL_P(member)[0] == '\0') { - if (Z_STRLEN_P(member) == 0) { - zend_error(E_ERROR, "Cannot access empty property"); - } else { - zend_error(E_ERROR, "Cannot access property started with '\\0'"); - } + /* magic unset */ + if (zobj->ce->__unset) { + long *guard = zend_get_property_guard(zobj, property_info, member); + if (!((*guard) & IN_UNSET)) { + /* have unseter - try with it! */ + Z_ADDREF_P(object); + if (Z_ISREF_P(object)) { + SEPARATE_ZVAL(object); + } + (*guard) |= IN_UNSET; /* prevent circular unsetting */ + zend_std_call_unsetter(object, member TSRMLS_CC); + (*guard) &= ~IN_UNSET; + zval_ptr_dtor(object); + } else { + if (Z_STRVAL_P(member)[0] == '\0') { + if (Z_STRLEN_P(member) == 0) { + zend_error(E_ERROR, "Cannot access empty property"); + } else { + zend_error(E_ERROR, "Cannot access property started with '\\0'"); } } } @@ -1382,12 +1364,6 @@ static int zend_std_compare_objects(zval *o1, zval *o2 TSRMLS_DC) /* {{{ */ zval *p1 = &zobj1->properties_table[i]; zval *p2 = &zobj2->properties_table[i]; - if (Z_TYPE_P(p1) == IS_INDIRECT) { - p1 = Z_INDIRECT_P(p1); - } - if (Z_TYPE_P(p2) == IS_INDIRECT) { - p1 = Z_INDIRECT_P(p2); - } if (compare_function(&result, p1, p2 TSRMLS_CC)==FAILURE) { Z_OBJ_UNPROTECT_RECURSION(o1); Z_OBJ_UNPROTECT_RECURSION(o2); @@ -1448,30 +1424,26 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists, if (EXPECTED(property_info != NULL)) { if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && - property_info->offset >= 0 && - Z_TYPE(zobj->properties_table[property_info->offset]) != IS_UNDEF) { + property_info->offset >= 0) { value = &zobj->properties_table[property_info->offset]; - if (Z_TYPE_P(value) == IS_INDIRECT) { - value = Z_INDIRECT_P(value); + if (Z_TYPE_P(value) != IS_UNDEF) { + goto found; } - goto found; - } - if (UNEXPECTED(zobj->properties != NULL)) { - if ((value = zend_hash_find(zobj->properties, property_info->name)) != NULL) { + } else if (UNEXPECTED(zobj->properties != NULL) && + (value = zend_hash_find(zobj->properties, property_info->name)) != NULL) { found: - switch (has_set_exists) { - case 0: - result = (Z_TYPE_P(value) != IS_NULL); - break; - default: - result = zend_is_true(value TSRMLS_CC); - break; - case 2: - result = 1; - break; - } - goto exit; + switch (has_set_exists) { + case 0: + result = (Z_TYPE_P(value) != IS_NULL); + break; + default: + result = zend_is_true(value TSRMLS_CC); + break; + case 2: + result = 1; + break; } + goto exit; } } diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c index 50785b86ec8..ec353b7a2c8 100644 --- a/Zend/zend_objects.c +++ b/Zend/zend_objects.c @@ -142,32 +142,39 @@ ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object *o { int i; - if (!old_object->properties) { + if (old_object->ce->default_properties_count) { for (i = 0; i < old_object->ce->default_properties_count; i++) { zval_ptr_dtor(&new_object->properties_table[i]); ZVAL_COPY(&new_object->properties_table[i], &old_object->properties_table[i]); } - } else { + } + if (old_object->properties) { + HashPosition pos; + zval *prop, new_prop; + ulong num_key; + zend_string *key; + if (!new_object->properties) { ALLOC_HASHTABLE(new_object->properties); zend_hash_init(new_object->properties, 0, NULL, ZVAL_PTR_DTOR, 0); } - zend_hash_copy(new_object->properties, old_object->properties, zval_add_ref_unref); - if (old_object->properties_table) { - HashPosition pos; - zval *prop; - zend_property_info *prop_info; - for (zend_hash_internal_pointer_reset_ex(&old_object->ce->properties_info, &pos); - (prop_info = zend_hash_get_current_data_ptr_ex(&old_object->ce->properties_info, &pos)) != NULL; - zend_hash_move_forward_ex(&old_object->ce->properties_info, &pos)) { - if ((prop_info->flags & ZEND_ACC_STATIC) == 0) { - if ((prop = zend_hash_find(new_object->properties, prop_info->name)) != NULL) { - ZVAL_INDIRECT(&new_object->properties_table[prop_info->offset], prop); - } else { - ZVAL_UNDEF(&new_object->properties_table[prop_info->offset]); - } - } + for (zend_hash_internal_pointer_reset_ex(old_object->properties, &pos); + (prop = zend_hash_get_current_data_ex(old_object->properties, &pos)) != NULL; + zend_hash_move_forward_ex(old_object->properties, &pos)) { + if (Z_TYPE_P(prop) == IS_INDIRECT) { + ZVAL_INDIRECT(&new_prop, new_object->properties_table + (Z_INDIRECT_P(prop) - old_object->properties_table)); + } else { + ZVAL_COPY_VALUE(&new_prop, prop); + zval_add_ref_unref(&new_prop); + } + switch (zend_hash_get_current_key_ex(old_object->properties, &key, &num_key, 0, &pos)) { + case HASH_KEY_IS_STRING: + zend_hash_update(new_object->properties, key, &new_prop); + break; + case HASH_KEY_IS_LONG: + zend_hash_index_update(new_object->properties, num_key, &new_prop); + break; } } } diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c index f7375edc5ee..4a7fb4f74a8 100644 --- a/Zend/zend_variables.c +++ b/Zend/zend_variables.c @@ -336,6 +336,18 @@ ZEND_API int zval_copy_static_var(zval *p TSRMLS_DC, int num_args, va_list args, zend_error(E_NOTICE,"Undefined variable: %s", key->key->val); } } else { + if (Z_TYPE_P(p) == IS_INDIRECT) { + p = Z_INDIRECT_P(p); + if (Z_TYPE_P(p) == IS_UNDEF) { + if (!is_ref) { + zend_error(E_NOTICE,"Undefined variable: %s", key->key->val); + p = &tmp; + ZVAL_NULL(&tmp); + } else { + ZVAL_NULL(p); + } + } + } if (is_ref) { SEPARATE_ZVAL_TO_MAKE_IS_REF(p); Z_ADDREF_P(p); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 37bd9107b70..e97646be2eb 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -340,17 +340,8 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } -//???: object may become INDIRECT - if (OP1_TYPE == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { make_real_object(object TSRMLS_CC); -//??? - if (Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } } if (UNEXPECTED(Z_ISREF_P(object))) { object = Z_REFVAL_P(object); @@ -1048,10 +1039,6 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, UNUSED|CONST| FREE_OP1(); } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (OP1_TYPE == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } /* if (!target_symbol_table) { CHECK_EXCEPTION(); @@ -1076,6 +1063,29 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, UNUSED|CONST| break; EMPTY_SWITCH_DEFAULT_CASE() } +//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV + } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/ + Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_IS: + retval = EX_VAR(opline->result.var); + ZVAL_NULL(retval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_W: + ZVAL_NULL(retval); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + } } switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) { case ZEND_FETCH_GLOBAL: @@ -1860,9 +1870,15 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) zend_bool nested = EX(nested); zend_op_array *op_array = EX(op_array); + if ((nested && EX(prev_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL) || + EG(active_symbol_table) == &EG(symbol_table)) { + zend_detach_symbol_table(TSRMLS_C); + } + EG(current_execute_data) = EX(prev_execute_data); EG(opline_ptr) = NULL; - if (!EG(active_symbol_table)) { + + if (EG(active_symbol_table) != &EG(symbol_table)) { i_free_compiled_variables(execute_data TSRMLS_CC); } @@ -1882,6 +1898,8 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) LOAD_OPLINE(); if (UNEXPECTED(opline->opcode == ZEND_INCLUDE_OR_EVAL)) { + zend_attach_symbol_table(TSRMLS_C); + EX(function_state).function = (zend_function *) EX(op_array); EX(function_state).arguments = NULL; @@ -3027,11 +3045,6 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV) zval_ptr_dtor(EX_VAR_NUM(opline->op2.var)); } ZVAL_OBJ(EX_VAR_NUM(opline->op2.var), EG(exception)); - if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op2.var); - zval *zv = zend_hash_update(&EG(active_symbol_table)->ht, cv, EX_VAR_NUM(opline->op2.var)); - ZVAL_INDIRECT(EX_VAR_NUM(opline->op2.var), zv); - } if (UNEXPECTED(EG(exception) != exception)) { EG(exception)->gc.refcount++; HANDLE_EXCEPTION(); @@ -3222,7 +3235,7 @@ ZEND_VM_HANDLER(165, ZEND_SEND_UNPACK, ANY, ANY) args = GET_OP1_ZVAL_PTR(BP_VAR_R); arg_num = opline->op2.num + EX(call)->num_additional_args + 1; -again: +ZEND_VM_C_LABEL(send_again): switch (Z_TYPE_P(args)) { case IS_ARRAY: { HashTable *ht = Z_ARRVAL_P(args); @@ -3350,7 +3363,7 @@ ZEND_VM_C_LABEL(unpack_iter_dtor): } case IS_REFERENCE: args = Z_REFVAL_P(args); - goto again; + ZEND_VM_C_GOTO(send_again); break; default: zend_error(E_WARNING, "Only arrays and Traversables can be unpacked"); @@ -3419,10 +3432,6 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST) ZVAL_COPY_VALUE(&tmp, opline->op2.zv); zval_update_constant(&tmp, 0 TSRMLS_CC); -//???: var_ptr may become INDIRECT - if (Z_TYPE_P(var_ptr) == IS_INDIRECT) { - var_ptr = Z_INDIRECT_P(var_ptr); - } ZVAL_COPY_VALUE(var_ptr, &tmp); } else { ZVAL_COPY_VALUE(var_ptr, opline->op2.zv); @@ -3467,10 +3476,6 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, ANY, ANY) for (; arg_num <= arg_count; ++arg_num) { zval *param = zend_vm_stack_get_arg(arg_num TSRMLS_CC); zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, param, opline->extended_value TSRMLS_CC); -//??? "params" may became IS_INDIRECT because of symtable initialization in zend_error - if (Z_TYPE_P(params) == IS_INDIRECT) { - params = Z_INDIRECT_P(params); - } zend_hash_next_index_insert(Z_ARRVAL_P(params), param); if (Z_REFCOUNTED_P(param)) { Z_ADDREF_P(param); @@ -3805,7 +3810,7 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMP|VAR|UNUS zval *offset = GET_OP2_ZVAL_PTR(BP_VAR_R); ulong hval; -again: +ZEND_VM_C_LABEL(add_again): switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -3827,7 +3832,7 @@ ZEND_VM_C_LABEL(num_index): break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + ZEND_VM_C_GOTO(add_again); break; default: zend_error(E_WARNING, "Illegal offset type"); @@ -3877,7 +3882,7 @@ ZEND_VM_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY) } } -again: +ZEND_VM_C_LABEL(cast_again): switch (opline->extended_value) { case IS_NULL: convert_to_null(result); @@ -3917,7 +3922,7 @@ again: break; case IS_REFERENCE: result = Z_REFVAL_P(result); - goto again; + ZEND_VM_C_GOTO(cast_again); break; } FREE_OP1_IF_VAR(); @@ -4061,15 +4066,8 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) if (OP1_TYPE == IS_CV && OP2_TYPE == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { - zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } + zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); + ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -4112,11 +4110,7 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) zend_std_unset_static_property(ce, Z_STR_P(varname), ((OP1_TYPE == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC); } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (OP1_TYPE == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } - zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC); + zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } if (OP1_TYPE != IS_CONST && varname == &tmp) { @@ -4145,12 +4139,11 @@ ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMP|VAR|CV) offset = GET_OP2_ZVAL_PTR(BP_VAR_R); if (OP1_TYPE != IS_VAR || container) { -//???deref -container_again: +ZEND_VM_C_LABEL(container_again): switch (Z_TYPE_P(container)) { case IS_ARRAY: { HashTable *ht = Z_ARRVAL_P(container); -offset_again: +ZEND_VM_C_LABEL(offset_again): switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -4189,7 +4182,7 @@ ZEND_VM_C_LABEL(num_index_dim): break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto offset_again; + ZEND_VM_C_GOTO(offset_again); break; default: zend_error(E_WARNING, "Illegal offset type in unset"); @@ -4221,7 +4214,7 @@ ZEND_VM_C_LABEL(num_index_dim): ZEND_VM_CONTINUE(); /* bailed out before */ case IS_REFERENCE: container = Z_REFVAL_P(container); - goto container_again; + ZEND_VM_C_GOTO(container_again); break; default: FREE_OP2(); @@ -4492,16 +4485,28 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY) fe_ht = Z_OBJPROP_P(array); zend_hash_set_pointer(fe_ht, (HashPointer*)EX_VAR((opline+1)->op1.var)); - do { + while (1) { if ((value = zend_hash_get_current_data(fe_ht)) == NULL) { /* reached end of iteration */ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); } + + if (Z_TYPE_P(value) == IS_INDIRECT) { + value = Z_INDIRECT_P(value); + if (Z_TYPE_P(value) == IS_UNDEF) { + zend_hash_move_forward(fe_ht); + continue; + } + } + key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &int_key, 0, NULL); zend_hash_move_forward(fe_ht); - } while (key_type != HASH_KEY_IS_LONG && - zend_check_property_access(zobj, str_key TSRMLS_CC) != SUCCESS); + if (key_type == HASH_KEY_IS_LONG || + zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) { + break; + } + } if (key) { if (key_type == HASH_KEY_IS_LONG) { @@ -4599,18 +4604,9 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) (opline->extended_value & ZEND_QUICK_SET)) { if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { value = EX_VAR_NUM(opline->op1.var); - if (Z_TYPE_P(value) == IS_INDIRECT) { - value = Z_INDIRECT_P(value); - } if (Z_TYPE_P(value) == IS_REFERENCE) { value = Z_REFVAL_P(value); } - } else if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) { - isset = 0; - } } else { isset = 0; } @@ -4648,10 +4644,6 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) } } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (OP1_TYPE == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } @@ -4704,7 +4696,7 @@ ZEND_VM_HELPER_EX(zend_isset_isempty_dim_prop_obj_handler, VAR|UNUSED|CV, CONST| ht = Z_ARRVAL_P(container); -again: +ZEND_VM_C_LABEL(isset_again): switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -4722,18 +4714,18 @@ ZEND_VM_C_LABEL(num_index_prop): if (OP2_TYPE != IS_CONST) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, ZEND_VM_C_GOTO(num_index_prop)); } - if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) { + if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) { isset = 1; } break; case IS_NULL: - if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) { + if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) { isset = 1; } break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + ZEND_VM_C_GOTO(isset_again); break; default: zend_error(E_WARNING, "Illegal offset type in isset or empty"); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index c61ad640450..2ebff4738d4 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -386,9 +386,15 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) zend_bool nested = EX(nested); zend_op_array *op_array = EX(op_array); + if ((nested && EX(prev_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL) || + EG(active_symbol_table) == &EG(symbol_table)) { + zend_detach_symbol_table(TSRMLS_C); + } + EG(current_execute_data) = EX(prev_execute_data); EG(opline_ptr) = NULL; - if (!EG(active_symbol_table)) { + + if (EG(active_symbol_table) != &EG(symbol_table)) { i_free_compiled_variables(execute_data TSRMLS_CC); } @@ -408,6 +414,8 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) LOAD_OPLINE(); if (UNEXPECTED(opline->opcode == ZEND_INCLUDE_OR_EVAL)) { + zend_attach_symbol_table(TSRMLS_C); + EX(function_state).function = (zend_function *) EX(op_array); EX(function_state).arguments = NULL; @@ -702,7 +710,7 @@ static int ZEND_FASTCALL ZEND_SEND_UNPACK_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS args = get_zval_ptr(opline->op1_type, &opline->op1, execute_data, &free_op1, BP_VAR_R); arg_num = opline->op2.num + EX(call)->num_additional_args + 1; -again: +send_again: switch (Z_TYPE_P(args)) { case IS_ARRAY: { HashTable *ht = Z_ARRVAL_P(args); @@ -830,7 +838,7 @@ unpack_iter_dtor: } case IS_REFERENCE: args = Z_REFVAL_P(args); - goto again; + goto send_again; break; default: zend_error(E_WARNING, "Only arrays and Traversables can be unpacked"); @@ -902,10 +910,6 @@ static int ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR for (; arg_num <= arg_count; ++arg_num) { zval *param = zend_vm_stack_get_arg(arg_num TSRMLS_CC); zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, param, opline->extended_value TSRMLS_CC); -//??? "params" may became IS_INDIRECT because of symtable initialization in zend_error - if (Z_TYPE_P(params) == IS_INDIRECT) { - params = Z_INDIRECT_P(params); - } zend_hash_next_index_insert(Z_ARRVAL_P(params), param); if (Z_REFCOUNTED_P(param)) { Z_ADDREF_P(param); @@ -1616,10 +1620,6 @@ static int ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ ZVAL_COPY_VALUE(&tmp, opline->op2.zv); zval_update_constant(&tmp, 0 TSRMLS_CC); -//???: var_ptr may become INDIRECT - if (Z_TYPE_P(var_ptr) == IS_INDIRECT) { - var_ptr = Z_INDIRECT_P(var_ptr); - } ZVAL_COPY_VALUE(var_ptr, &tmp); } else { ZVAL_COPY_VALUE(var_ptr, opline->op2.zv); @@ -2814,7 +2814,7 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } } -again: +cast_again: switch (opline->extended_value) { case IS_NULL: convert_to_null(result); @@ -2854,7 +2854,7 @@ again: break; case IS_REFERENCE: result = Z_REFVAL_P(result); - goto again; + goto cast_again; break; } @@ -3603,10 +3603,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_CONST(int type } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_CONST == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } /* if (!target_symbol_table) { CHECK_EXCEPTION(); @@ -3631,6 +3627,29 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_CONST(int type break; EMPTY_SWITCH_DEFAULT_CASE() } +//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV + } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/ + Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_IS: + retval = EX_VAR(opline->result.var); + ZVAL_NULL(retval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_W: + ZVAL_NULL(retval); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + } } switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) { case ZEND_FETCH_GLOBAL: @@ -4013,7 +4032,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_O zval *offset = opline->op2.zv; ulong hval; -again: +add_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -4035,7 +4054,7 @@ num_index: break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto add_again; break; default: zend_error(E_WARNING, "Illegal offset type"); @@ -4079,15 +4098,8 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HA if (IS_CONST == IS_CV && IS_CONST == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { - zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } + zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); + ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -4130,11 +4142,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HA zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CONST == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC); } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_CONST == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } - zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC); + zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } if (IS_CONST != IS_CONST && varname == &tmp) { @@ -4159,18 +4167,9 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_CONST_HANDLER(ZEND_O (opline->extended_value & ZEND_QUICK_SET)) { if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { value = EX_VAR_NUM(opline->op1.var); - if (Z_TYPE_P(value) == IS_INDIRECT) { - value = Z_INDIRECT_P(value); - } if (Z_TYPE_P(value) == IS_REFERENCE) { value = Z_REFVAL_P(value); } - } else if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) { - isset = 0; - } } else { isset = 0; } @@ -4208,10 +4207,6 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_CONST_HANDLER(ZEND_O } } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_CONST == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } @@ -4868,7 +4863,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMP_HANDLER(ZEND_OPC zval *offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ulong hval; -again: +add_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -4890,7 +4885,7 @@ num_index: break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto add_again; break; default: zend_error(E_WARNING, "Illegal offset type"); @@ -5381,10 +5376,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_VAR(int type, } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_CONST == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } /* if (!target_symbol_table) { CHECK_EXCEPTION(); @@ -5409,6 +5400,29 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_VAR(int type, break; EMPTY_SWITCH_DEFAULT_CASE() } +//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV + } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/ + Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_IS: + retval = EX_VAR(opline->result.var); + ZVAL_NULL(retval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_W: + ZVAL_NULL(retval); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + } } switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) { case ZEND_FETCH_GLOBAL: @@ -5677,7 +5691,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_VAR_HANDLER(ZEND_OPC zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ulong hval; -again: +add_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -5699,7 +5713,7 @@ num_index: break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto add_again; break; default: zend_error(E_WARNING, "Illegal offset type"); @@ -5743,15 +5757,8 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HAND if (IS_CONST == IS_CV && IS_VAR == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { - zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } + zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); + ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -5794,11 +5801,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HAND zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CONST == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC); } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_CONST == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } - zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC); + zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } if (IS_CONST != IS_CONST && varname == &tmp) { @@ -5823,18 +5826,9 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPC (opline->extended_value & ZEND_QUICK_SET)) { if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { value = EX_VAR_NUM(opline->op1.var); - if (Z_TYPE_P(value) == IS_INDIRECT) { - value = Z_INDIRECT_P(value); - } if (Z_TYPE_P(value) == IS_REFERENCE) { value = Z_REFVAL_P(value); } - } else if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) { - isset = 0; - } } else { isset = 0; } @@ -5872,10 +5866,6 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPC } } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_CONST == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } @@ -6088,10 +6078,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int typ } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_CONST == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } /* if (!target_symbol_table) { CHECK_EXCEPTION(); @@ -6116,6 +6102,29 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int typ break; EMPTY_SWITCH_DEFAULT_CASE() } +//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV + } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/ + Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_IS: + retval = EX_VAR(opline->result.var); + ZVAL_NULL(retval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_W: + ZVAL_NULL(retval); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + } } switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) { case ZEND_FETCH_GLOBAL: @@ -6352,7 +6361,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_ zval *offset = NULL; ulong hval; -again: +add_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -6374,7 +6383,7 @@ num_index: break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto add_again; break; default: zend_error(E_WARNING, "Illegal offset type"); @@ -6418,15 +6427,8 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_H if (IS_CONST == IS_CV && IS_UNUSED == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { - zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } + zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); + ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -6469,11 +6471,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_H zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CONST == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC); } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_CONST == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } - zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC); + zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } if (IS_CONST != IS_CONST && varname == &tmp) { @@ -6498,18 +6496,9 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_ (opline->extended_value & ZEND_QUICK_SET)) { if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { value = EX_VAR_NUM(opline->op1.var); - if (Z_TYPE_P(value) == IS_INDIRECT) { - value = Z_INDIRECT_P(value); - } if (Z_TYPE_P(value) == IS_REFERENCE) { value = Z_REFVAL_P(value); } - } else if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) { - isset = 0; - } } else { isset = 0; } @@ -6547,10 +6536,6 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_ } } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_CONST == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } @@ -7186,11 +7171,6 @@ static int ZEND_FASTCALL ZEND_CATCH_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A zval_ptr_dtor(EX_VAR_NUM(opline->op2.var)); } ZVAL_OBJ(EX_VAR_NUM(opline->op2.var), EG(exception)); - if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op2.var); - zval *zv = zend_hash_update(&EG(active_symbol_table)->ht, cv, EX_VAR_NUM(opline->op2.var)); - ZVAL_INDIRECT(EX_VAR_NUM(opline->op2.var), zv); - } if (UNEXPECTED(EG(exception) != exception)) { EG(exception)->gc.refcount++; HANDLE_EXCEPTION(); @@ -7250,7 +7230,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCO zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); ulong hval; -again: +add_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -7272,7 +7252,7 @@ num_index: break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto add_again; break; default: zend_error(E_WARNING, "Illegal offset type"); @@ -7906,7 +7886,7 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } } -again: +cast_again: switch (opline->extended_value) { case IS_NULL: convert_to_null(result); @@ -7946,7 +7926,7 @@ again: break; case IS_REFERENCE: result = Z_REFVAL_P(result); - goto again; + goto cast_again; break; } @@ -8745,10 +8725,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_CONST(int type, zval_dtor(free_op1.var); } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_TMP_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } /* if (!target_symbol_table) { CHECK_EXCEPTION(); @@ -8773,6 +8749,29 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_CONST(int type, break; EMPTY_SWITCH_DEFAULT_CASE() } +//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV + } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/ + Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_IS: + retval = EX_VAR(opline->result.var); + ZVAL_NULL(retval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_W: + ZVAL_NULL(retval); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + } } switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) { case ZEND_FETCH_GLOBAL: @@ -9063,7 +9062,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPC zval *offset = opline->op2.zv; ulong hval; -again: +add_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -9085,7 +9084,7 @@ num_index: break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto add_again; break; default: zend_error(E_WARNING, "Illegal offset type"); @@ -9129,15 +9128,8 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HAND if (IS_TMP_VAR == IS_CV && IS_CONST == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { - zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } + zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); + ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -9180,11 +9172,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HAND zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_TMP_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC); } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_TMP_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } - zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC); + zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } if (IS_TMP_VAR != IS_CONST && varname == &tmp) { @@ -9209,18 +9197,9 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPC (opline->extended_value & ZEND_QUICK_SET)) { if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { value = EX_VAR_NUM(opline->op1.var); - if (Z_TYPE_P(value) == IS_INDIRECT) { - value = Z_INDIRECT_P(value); - } if (Z_TYPE_P(value) == IS_REFERENCE) { value = Z_REFVAL_P(value); } - } else if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) { - isset = 0; - } } else { isset = 0; } @@ -9258,10 +9237,6 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPC } } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_TMP_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } @@ -9895,7 +9870,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP_HANDLER(ZEND_OPCOD zval *offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ulong hval; -again: +add_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -9917,7 +9892,7 @@ num_index: break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto add_again; break; default: zend_error(E_WARNING, "Illegal offset type"); @@ -10408,10 +10383,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_VAR(int type, ZE zval_dtor(free_op1.var); } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_TMP_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } /* if (!target_symbol_table) { CHECK_EXCEPTION(); @@ -10436,6 +10407,29 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_VAR(int type, ZE break; EMPTY_SWITCH_DEFAULT_CASE() } +//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV + } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/ + Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_IS: + retval = EX_VAR(opline->result.var); + ZVAL_NULL(retval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_W: + ZVAL_NULL(retval); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + } } switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) { case ZEND_FETCH_GLOBAL: @@ -10714,7 +10708,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ulong hval; -again: +add_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -10736,7 +10730,7 @@ num_index: break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto add_again; break; default: zend_error(E_WARNING, "Illegal offset type"); @@ -10780,15 +10774,8 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLE if (IS_TMP_VAR == IS_CV && IS_VAR == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { - zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } + zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); + ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -10831,11 +10818,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLE zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_TMP_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC); } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_TMP_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } - zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC); + zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } if (IS_TMP_VAR != IS_CONST && varname == &tmp) { @@ -10860,18 +10843,9 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD (opline->extended_value & ZEND_QUICK_SET)) { if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { value = EX_VAR_NUM(opline->op1.var); - if (Z_TYPE_P(value) == IS_INDIRECT) { - value = Z_INDIRECT_P(value); - } if (Z_TYPE_P(value) == IS_REFERENCE) { value = Z_REFVAL_P(value); } - } else if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) { - isset = 0; - } } else { isset = 0; } @@ -10909,10 +10883,6 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD } } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_TMP_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } @@ -11125,10 +11095,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type, zval_dtor(free_op1.var); } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_TMP_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } /* if (!target_symbol_table) { CHECK_EXCEPTION(); @@ -11153,6 +11119,29 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type, break; EMPTY_SWITCH_DEFAULT_CASE() } +//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV + } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/ + Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_IS: + retval = EX_VAR(opline->result.var); + ZVAL_NULL(retval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_W: + ZVAL_NULL(retval); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + } } switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) { case ZEND_FETCH_GLOBAL: @@ -11278,7 +11267,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OP zval *offset = NULL; ulong hval; -again: +add_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -11300,7 +11289,7 @@ num_index: break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto add_again; break; default: zend_error(E_WARNING, "Illegal offset type"); @@ -11344,15 +11333,8 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HAN if (IS_TMP_VAR == IS_CV && IS_UNUSED == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { - zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } + zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); + ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -11395,11 +11377,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HAN zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_TMP_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC); } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_TMP_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } - zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC); + zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } if (IS_TMP_VAR != IS_CONST && varname == &tmp) { @@ -11424,18 +11402,9 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OP (opline->extended_value & ZEND_QUICK_SET)) { if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { value = EX_VAR_NUM(opline->op1.var); - if (Z_TYPE_P(value) == IS_INDIRECT) { - value = Z_INDIRECT_P(value); - } if (Z_TYPE_P(value) == IS_REFERENCE) { value = Z_REFVAL_P(value); } - } else if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) { - isset = 0; - } } else { isset = 0; } @@ -11473,10 +11442,6 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OP } } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_TMP_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } @@ -12107,7 +12072,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); ulong hval; -again: +add_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -12129,7 +12094,7 @@ num_index: break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto add_again; break; default: zend_error(E_WARNING, "Illegal offset type"); @@ -13076,7 +13041,7 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } } -again: +cast_again: switch (opline->extended_value) { case IS_NULL: convert_to_null(result); @@ -13116,7 +13081,7 @@ again: break; case IS_REFERENCE: result = Z_REFVAL_P(result); - goto again; + goto cast_again; break; } zval_ptr_dtor_nogc(free_op1.var); @@ -13464,16 +13429,28 @@ static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG fe_ht = Z_OBJPROP_P(array); zend_hash_set_pointer(fe_ht, (HashPointer*)EX_VAR((opline+1)->op1.var)); - do { + while (1) { if ((value = zend_hash_get_current_data(fe_ht)) == NULL) { /* reached end of iteration */ ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num); } + + if (Z_TYPE_P(value) == IS_INDIRECT) { + value = Z_INDIRECT_P(value); + if (Z_TYPE_P(value) == IS_UNDEF) { + zend_hash_move_forward(fe_ht); + continue; + } + } + key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &int_key, 0, NULL); zend_hash_move_forward(fe_ht); - } while (key_type != HASH_KEY_IS_LONG && - zend_check_property_access(zobj, str_key TSRMLS_CC) != SUCCESS); + if (key_type == HASH_KEY_IS_LONG || + zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) { + break; + } + } if (key) { if (key_type == HASH_KEY_IS_LONG) { @@ -13988,17 +13965,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } -//???: object may become INDIRECT - if (IS_VAR == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { make_real_object(object TSRMLS_CC); -//??? - if (Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } } if (UNEXPECTED(Z_ISREF_P(object))) { object = Z_REFVAL_P(object); @@ -14475,10 +14443,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_CONST(int type, zval_ptr_dtor_nogc(free_op1.var); } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } /* if (!target_symbol_table) { CHECK_EXCEPTION(); @@ -14503,6 +14467,29 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_CONST(int type, break; EMPTY_SWITCH_DEFAULT_CASE() } +//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV + } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/ + Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_IS: + retval = EX_VAR(opline->result.var); + ZVAL_NULL(retval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_W: + ZVAL_NULL(retval); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + } } switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) { case ZEND_FETCH_GLOBAL: @@ -15527,7 +15514,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPC zval *offset = opline->op2.zv; ulong hval; -again: +add_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -15549,7 +15536,7 @@ num_index: break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto add_again; break; default: zend_error(E_WARNING, "Illegal offset type"); @@ -15593,15 +15580,8 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND if (IS_VAR == IS_CV && IS_CONST == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { - zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } + zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); + ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -15644,11 +15624,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC); } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } - zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC); + zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } if (IS_VAR != IS_CONST && varname == &tmp) { @@ -15677,7 +15653,6 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND offset = opline->op2.zv; if (IS_VAR != IS_VAR || container) { -//???deref container_again: switch (Z_TYPE_P(container)) { case IS_ARRAY: { @@ -15821,18 +15796,9 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPC (opline->extended_value & ZEND_QUICK_SET)) { if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { value = EX_VAR_NUM(opline->op1.var); - if (Z_TYPE_P(value) == IS_INDIRECT) { - value = Z_INDIRECT_P(value); - } if (Z_TYPE_P(value) == IS_REFERENCE) { value = Z_REFVAL_P(value); } - } else if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) { - isset = 0; - } } else { isset = 0; } @@ -15870,10 +15836,6 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPC } } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } @@ -15926,7 +15888,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CONST( ht = Z_ARRVAL_P(container); -again: +isset_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -15944,18 +15906,18 @@ num_index_prop: if (IS_CONST != IS_CONST) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop); } - if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) { + if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) { isset = 1; } break; case IS_NULL: - if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) { + if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) { isset = 1; } break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto isset_again; break; default: zend_error(E_WARNING, "Illegal offset type in isset or empty"); @@ -16483,17 +16445,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } -//???: object may become INDIRECT - if (IS_VAR == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { make_real_object(object TSRMLS_CC); -//??? - if (Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } } if (UNEXPECTED(Z_ISREF_P(object))) { object = Z_REFVAL_P(object); @@ -17773,7 +17726,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP_HANDLER(ZEND_OPCOD zval *offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ulong hval; -again: +add_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -17795,7 +17748,7 @@ num_index: break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto add_again; break; default: zend_error(E_WARNING, "Illegal offset type"); @@ -17844,7 +17797,6 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLE offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR != IS_VAR || container) { -//???deref container_again: switch (Z_TYPE_P(container)) { case IS_ARRAY: { @@ -17999,7 +17951,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_TMP(in ht = Z_ARRVAL_P(container); -again: +isset_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -18017,18 +17969,18 @@ num_index_prop: if (IS_TMP_VAR != IS_CONST) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop); } - if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) { + if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) { isset = 1; } break; case IS_NULL: - if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) { + if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) { isset = 1; } break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto isset_again; break; default: zend_error(E_WARNING, "Illegal offset type in isset or empty"); @@ -18556,17 +18508,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } -//???: object may become INDIRECT - if (IS_VAR == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { make_real_object(object TSRMLS_CC); -//??? - if (Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } } if (UNEXPECTED(Z_ISREF_P(object))) { object = Z_REFVAL_P(object); @@ -19044,10 +18987,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_VAR(int type, ZE zval_ptr_dtor_nogc(free_op1.var); } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } /* if (!target_symbol_table) { CHECK_EXCEPTION(); @@ -19072,6 +19011,29 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_VAR(int type, ZE break; EMPTY_SWITCH_DEFAULT_CASE() } +//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV + } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/ + Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_IS: + retval = EX_VAR(opline->result.var); + ZVAL_NULL(retval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_W: + ZVAL_NULL(retval); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + } } switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) { case ZEND_FETCH_GLOBAL: @@ -20066,7 +20028,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ulong hval; -again: +add_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -20088,7 +20050,7 @@ num_index: break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto add_again; break; default: zend_error(E_WARNING, "Illegal offset type"); @@ -20132,15 +20094,8 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE if (IS_VAR == IS_CV && IS_VAR == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { - zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } + zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); + ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -20183,11 +20138,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC); } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } - zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC); + zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } if (IS_VAR != IS_CONST && varname == &tmp) { @@ -20216,7 +20167,6 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR != IS_VAR || container) { -//???deref container_again: switch (Z_TYPE_P(container)) { case IS_ARRAY: { @@ -20360,18 +20310,9 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD (opline->extended_value & ZEND_QUICK_SET)) { if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { value = EX_VAR_NUM(opline->op1.var); - if (Z_TYPE_P(value) == IS_INDIRECT) { - value = Z_INDIRECT_P(value); - } if (Z_TYPE_P(value) == IS_REFERENCE) { value = Z_REFVAL_P(value); } - } else if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) { - isset = 0; - } } else { isset = 0; } @@ -20409,10 +20350,6 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD } } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } @@ -20465,7 +20402,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_VAR(in ht = Z_ARRVAL_P(container); -again: +isset_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -20483,18 +20420,18 @@ num_index_prop: if (IS_VAR != IS_CONST) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop); } - if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) { + if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) { isset = 1; } break; case IS_NULL: - if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) { + if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) { isset = 1; } break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto isset_again; break; default: zend_error(E_WARNING, "Illegal offset type in isset or empty"); @@ -20747,17 +20684,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (* zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } -//???: object may become INDIRECT - if (IS_VAR == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { make_real_object(object TSRMLS_CC); -//??? - if (Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } } if (UNEXPECTED(Z_ISREF_P(object))) { object = Z_REFVAL_P(object); @@ -21040,10 +20968,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_UNUSED(int type, zval_ptr_dtor_nogc(free_op1.var); } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } /* if (!target_symbol_table) { CHECK_EXCEPTION(); @@ -21068,6 +20992,29 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_UNUSED(int type, break; EMPTY_SWITCH_DEFAULT_CASE() } +//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV + } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/ + Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_IS: + retval = EX_VAR(opline->result.var); + ZVAL_NULL(retval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_W: + ZVAL_NULL(retval); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + } } switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) { case ZEND_FETCH_GLOBAL: @@ -21491,7 +21438,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OP zval *offset = NULL; ulong hval; -again: +add_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -21513,7 +21460,7 @@ num_index: break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto add_again; break; default: zend_error(E_WARNING, "Illegal offset type"); @@ -21557,15 +21504,8 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAN if (IS_VAR == IS_CV && IS_UNUSED == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { - zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } + zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); + ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -21608,11 +21548,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAN zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC); } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } - zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC); + zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } if (IS_VAR != IS_CONST && varname == &tmp) { @@ -21637,18 +21573,9 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OP (opline->extended_value & ZEND_QUICK_SET)) { if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { value = EX_VAR_NUM(opline->op1.var); - if (Z_TYPE_P(value) == IS_INDIRECT) { - value = Z_INDIRECT_P(value); - } if (Z_TYPE_P(value) == IS_REFERENCE) { value = Z_REFVAL_P(value); } - } else if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) { - isset = 0; - } } else { isset = 0; } @@ -21686,10 +21613,6 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OP } } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } @@ -22167,17 +22090,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } -//???: object may become INDIRECT - if (IS_VAR == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { make_real_object(object TSRMLS_CC); -//??? - if (Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } } if (UNEXPECTED(Z_ISREF_P(object))) { object = Z_REFVAL_P(object); @@ -23511,7 +23425,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); ulong hval; -again: +add_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -23533,7 +23447,7 @@ num_index: break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto add_again; break; default: zend_error(E_WARNING, "Illegal offset type"); @@ -23582,7 +23496,6 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_VAR != IS_VAR || container) { -//???deref container_again: switch (Z_TYPE_P(container)) { case IS_ARRAY: { @@ -23737,7 +23650,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CV(int ht = Z_ARRVAL_P(container); -again: +isset_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -23755,18 +23668,18 @@ num_index_prop: if (IS_CV != IS_CONST) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop); } - if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) { + if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) { isset = 1; } break; case IS_NULL: - if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) { + if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) { isset = 1; } break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto isset_again; break; default: zend_error(E_WARNING, "Illegal offset type in isset or empty"); @@ -24099,17 +24012,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } -//???: object may become INDIRECT - if (IS_UNUSED == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { make_real_object(object TSRMLS_CC); -//??? - if (Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } } if (UNEXPECTED(Z_ISREF_P(object))) { object = Z_REFVAL_P(object); @@ -25070,7 +24974,6 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_H offset = opline->op2.zv; if (IS_UNUSED != IS_VAR || container) { -//???deref container_again: switch (Z_TYPE_P(container)) { case IS_ARRAY: { @@ -25223,7 +25126,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CON ht = Z_ARRVAL_P(container); -again: +isset_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -25241,18 +25144,18 @@ num_index_prop: if (IS_CONST != IS_CONST) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop); } - if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) { + if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) { isset = 1; } break; case IS_NULL: - if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) { + if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) { isset = 1; } break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto isset_again; break; default: zend_error(E_WARNING, "Illegal offset type in isset or empty"); @@ -25500,17 +25403,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (* zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } -//???: object may become INDIRECT - if (IS_UNUSED == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { make_real_object(object TSRMLS_CC); -//??? - if (Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } } if (UNEXPECTED(Z_ISREF_P(object))) { object = Z_REFVAL_P(object); @@ -26388,7 +26282,6 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HAN offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED != IS_VAR || container) { -//???deref container_again: switch (Z_TYPE_P(container)) { case IS_ARRAY: { @@ -26541,7 +26434,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_TMP ht = Z_ARRVAL_P(container); -again: +isset_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -26559,18 +26452,18 @@ num_index_prop: if (IS_TMP_VAR != IS_CONST) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop); } - if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) { + if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) { isset = 1; } break; case IS_NULL: - if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) { + if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) { isset = 1; } break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto isset_again; break; default: zend_error(E_WARNING, "Illegal offset type in isset or empty"); @@ -26818,17 +26711,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (* zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } -//???: object may become INDIRECT - if (IS_UNUSED == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { make_real_object(object TSRMLS_CC); -//??? - if (Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } } if (UNEXPECTED(Z_ISREF_P(object))) { object = Z_REFVAL_P(object); @@ -27706,7 +27590,6 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HAN offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED != IS_VAR || container) { -//???deref container_again: switch (Z_TYPE_P(container)) { case IS_ARRAY: { @@ -27859,7 +27742,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_VAR ht = Z_ARRVAL_P(container); -again: +isset_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -27877,18 +27760,18 @@ num_index_prop: if (IS_VAR != IS_CONST) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop); } - if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) { + if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) { isset = 1; } break; case IS_NULL: - if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) { + if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) { isset = 1; } break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto isset_again; break; default: zend_error(E_WARNING, "Illegal offset type in isset or empty"); @@ -28137,17 +28020,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } -//???: object may become INDIRECT - if (IS_UNUSED == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { make_real_object(object TSRMLS_CC); -//??? - if (Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } } if (UNEXPECTED(Z_ISREF_P(object))) { object = Z_REFVAL_P(object); @@ -28552,17 +28426,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*b zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } -//???: object may become INDIRECT - if (IS_UNUSED == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { make_real_object(object TSRMLS_CC); -//??? - if (Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } } if (UNEXPECTED(Z_ISREF_P(object))) { object = Z_REFVAL_P(object); @@ -29437,7 +29302,6 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAND offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_UNUSED != IS_VAR || container) { -//???deref container_again: switch (Z_TYPE_P(container)) { case IS_ARRAY: { @@ -29590,7 +29454,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CV( ht = Z_ARRVAL_P(container); -again: +isset_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -29608,18 +29472,18 @@ num_index_prop: if (IS_CV != IS_CONST) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop); } - if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) { + if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) { isset = 1; } break; case IS_NULL: - if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) { + if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) { isset = 1; } break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto isset_again; break; default: zend_error(E_WARNING, "Illegal offset type in isset or empty"); @@ -30597,7 +30461,7 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } } -again: +cast_again: switch (opline->extended_value) { case IS_NULL: convert_to_null(result); @@ -30637,7 +30501,7 @@ again: break; case IS_REFERENCE: result = Z_REFVAL_P(result); - goto again; + goto cast_again; break; } @@ -31377,17 +31241,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } -//???: object may become INDIRECT - if (IS_CV == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { make_real_object(object TSRMLS_CC); -//??? - if (Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } } if (UNEXPECTED(Z_ISREF_P(object))) { object = Z_REFVAL_P(object); @@ -31863,10 +31718,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_CONST(int type, Z } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_CV == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } /* if (!target_symbol_table) { CHECK_EXCEPTION(); @@ -31891,6 +31742,29 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_CONST(int type, Z break; EMPTY_SWITCH_DEFAULT_CASE() } +//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV + } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/ + Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_IS: + retval = EX_VAR(opline->result.var); + ZVAL_NULL(retval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_W: + ZVAL_NULL(retval); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + } } switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) { case ZEND_FETCH_GLOBAL: @@ -32704,7 +32578,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCO zval *offset = opline->op2.zv; ulong hval; -again: +add_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -32726,7 +32600,7 @@ num_index: break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto add_again; break; default: zend_error(E_WARNING, "Illegal offset type"); @@ -32770,15 +32644,8 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL if (IS_CV == IS_CV && IS_CONST == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { - zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } + zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); + ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -32821,11 +32688,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CV == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC); } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_CV == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } - zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC); + zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } if (IS_CV != IS_CONST && varname == &tmp) { @@ -32854,7 +32717,6 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL offset = opline->op2.zv; if (IS_CV != IS_VAR || container) { -//???deref container_again: switch (Z_TYPE_P(container)) { case IS_ARRAY: { @@ -32996,18 +32858,9 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCO (opline->extended_value & ZEND_QUICK_SET)) { if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { value = EX_VAR_NUM(opline->op1.var); - if (Z_TYPE_P(value) == IS_INDIRECT) { - value = Z_INDIRECT_P(value); - } if (Z_TYPE_P(value) == IS_REFERENCE) { value = Z_REFVAL_P(value); } - } else if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) { - isset = 0; - } } else { isset = 0; } @@ -33045,10 +32898,6 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCO } } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_CV == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } @@ -33101,7 +32950,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CONST(i ht = Z_ARRVAL_P(container); -again: +isset_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -33119,18 +32968,18 @@ num_index_prop: if (IS_CONST != IS_CONST) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop); } - if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) { + if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) { isset = 1; } break; case IS_NULL: - if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) { + if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) { isset = 1; } break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto isset_again; break; default: zend_error(E_WARNING, "Illegal offset type in isset or empty"); @@ -33654,17 +33503,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*bina zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } -//???: object may become INDIRECT - if (IS_CV == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { make_real_object(object TSRMLS_CC); -//??? - if (Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } } if (UNEXPECTED(Z_ISREF_P(object))) { object = Z_REFVAL_P(object); @@ -34825,7 +34665,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE zval *offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ulong hval; -again: +add_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -34847,7 +34687,7 @@ num_index: break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto add_again; break; default: zend_error(E_WARNING, "Illegal offset type"); @@ -34896,7 +34736,6 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_CV != IS_VAR || container) { -//???deref container_again: switch (Z_TYPE_P(container)) { case IS_ARRAY: { @@ -35049,7 +34888,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_TMP(int ht = Z_ARRVAL_P(container); -again: +isset_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -35067,18 +34906,18 @@ num_index_prop: if (IS_TMP_VAR != IS_CONST) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop); } - if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) { + if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) { isset = 1; } break; case IS_NULL: - if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) { + if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) { isset = 1; } break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto isset_again; break; default: zend_error(E_WARNING, "Illegal offset type in isset or empty"); @@ -35602,17 +35441,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*bina zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } -//???: object may become INDIRECT - if (IS_CV == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { make_real_object(object TSRMLS_CC); -//??? - if (Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } } if (UNEXPECTED(Z_ISREF_P(object))) { object = Z_REFVAL_P(object); @@ -36089,10 +35919,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type, ZEN } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_CV == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } /* if (!target_symbol_table) { CHECK_EXCEPTION(); @@ -36117,6 +35943,29 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type, ZEN break; EMPTY_SWITCH_DEFAULT_CASE() } +//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV + } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/ + Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_IS: + retval = EX_VAR(opline->result.var); + ZVAL_NULL(retval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_W: + ZVAL_NULL(retval); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + } } switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) { case ZEND_FETCH_GLOBAL: @@ -36992,7 +36841,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ulong hval; -again: +add_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -37014,7 +36863,7 @@ num_index: break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto add_again; break; default: zend_error(E_WARNING, "Illegal offset type"); @@ -37058,15 +36907,8 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER if (IS_CV == IS_CV && IS_VAR == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { - zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } + zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); + ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -37109,11 +36951,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CV == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC); } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_CV == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } - zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC); + zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } if (IS_CV != IS_CONST && varname == &tmp) { @@ -37142,7 +36980,6 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_CV != IS_VAR || container) { -//???deref container_again: switch (Z_TYPE_P(container)) { case IS_ARRAY: { @@ -37284,18 +37121,9 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE (opline->extended_value & ZEND_QUICK_SET)) { if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { value = EX_VAR_NUM(opline->op1.var); - if (Z_TYPE_P(value) == IS_INDIRECT) { - value = Z_INDIRECT_P(value); - } if (Z_TYPE_P(value) == IS_REFERENCE) { value = Z_REFVAL_P(value); } - } else if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) { - isset = 0; - } } else { isset = 0; } @@ -37333,10 +37161,6 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE } } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_CV == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } @@ -37389,7 +37213,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_VAR(int ht = Z_ARRVAL_P(container); -again: +isset_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -37407,18 +37231,18 @@ num_index_prop: if (IS_VAR != IS_CONST) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop); } - if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) { + if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) { isset = 1; } break; case IS_NULL: - if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) { + if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) { isset = 1; } break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto isset_again; break; default: zend_error(E_WARNING, "Illegal offset type in isset or empty"); @@ -37667,17 +37491,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } -//???: object may become INDIRECT - if (IS_CV == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { make_real_object(object TSRMLS_CC); -//??? - if (Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } } if (UNEXPECTED(Z_ISREF_P(object))) { object = Z_REFVAL_P(object); @@ -37959,10 +37774,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type, } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_CV == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } /* if (!target_symbol_table) { CHECK_EXCEPTION(); @@ -37987,6 +37798,29 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type, break; EMPTY_SWITCH_DEFAULT_CASE() } +//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV + } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/ + Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + switch (type) { + case BP_VAR_R: + case BP_VAR_UNSET: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_IS: + retval = EX_VAR(opline->result.var); + ZVAL_NULL(retval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname)); + /* break missing intentionally */ + case BP_VAR_W: + ZVAL_NULL(retval); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + } } switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) { case ZEND_FETCH_GLOBAL: @@ -38297,7 +38131,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPC zval *offset = NULL; ulong hval; -again: +add_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -38319,7 +38153,7 @@ num_index: break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto add_again; break; default: zend_error(E_WARNING, "Illegal offset type"); @@ -38363,15 +38197,8 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAND if (IS_CV == IS_CV && IS_UNUSED == IS_UNUSED && (opline->extended_value & ZEND_QUICK_SET)) { - if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { - zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); - ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); - } + zval_ptr_dtor(EX_VAR_NUM(opline->op1.var)); + ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var)); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -38414,11 +38241,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAND zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CV == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC); } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_CV == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } - zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC); + zend_hash_del_ind(target_symbol_table, Z_STR_P(varname)); } if (IS_CV != IS_CONST && varname == &tmp) { @@ -38443,18 +38266,9 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPC (opline->extended_value & ZEND_QUICK_SET)) { if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) { value = EX_VAR_NUM(opline->op1.var); - if (Z_TYPE_P(value) == IS_INDIRECT) { - value = Z_INDIRECT_P(value); - } if (Z_TYPE_P(value) == IS_REFERENCE) { value = Z_REFVAL_P(value); } - } else if (EG(active_symbol_table)) { - zend_string *cv = CV_DEF_OF(opline->op1.var); - - if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) { - isset = 0; - } } else { isset = 0; } @@ -38492,10 +38306,6 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPC } } else { target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); -//???: STRING may become INDIRECT - if (IS_CV == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) { - varname = Z_INDIRECT_P(varname); - } if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) { isset = 0; } @@ -38953,17 +38763,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } -//???: object may become INDIRECT - if (IS_CV == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } - if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { make_real_object(object TSRMLS_CC); -//??? - if (Z_TYPE_P(object) == IS_INDIRECT) { - object = Z_INDIRECT_P(object); - } } if (UNEXPECTED(Z_ISREF_P(object))) { object = Z_REFVAL_P(object); @@ -40177,7 +39978,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_ zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); ulong hval; -again: +add_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -40199,7 +40000,7 @@ num_index: break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto add_again; break; default: zend_error(E_WARNING, "Illegal offset type"); @@ -40248,7 +40049,6 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_CV != IS_VAR || container) { -//???deref container_again: switch (Z_TYPE_P(container)) { case IS_ARRAY: { @@ -40401,7 +40201,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CV(int ht = Z_ARRVAL_P(container); -again: +isset_again: switch (Z_TYPE_P(offset)) { case IS_DOUBLE: hval = zend_dval_to_lval(Z_DVAL_P(offset)); @@ -40419,18 +40219,18 @@ num_index_prop: if (IS_CV != IS_CONST) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop); } - if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) { + if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) { isset = 1; } break; case IS_NULL: - if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) { + if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) { isset = 1; } break; case IS_REFERENCE: offset = Z_REFVAL_P(offset); - goto again; + goto isset_again; break; default: zend_error(E_WARNING, "Illegal offset type in isset or empty"); diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 148dae43783..53101b46239 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -223,14 +223,23 @@ static inline reflection_object *reflection_object_from_obj(zend_object *obj) /* static zend_object_handlers reflection_object_handlers; +static zval *_default_load_entry(zval *object, char *name, int name_len TSRMLS_DC) /* {{{ */ +{ + zval *value; + + if ((value = zend_hash_str_find_ind(Z_OBJPROP_P(object), name, name_len)) == NULL) { + return NULL; + } + return value; +} + static void _default_get_entry(zval *object, char *name, int name_len, zval *return_value TSRMLS_DC) /* {{{ */ { zval *value; - if ((value = zend_hash_str_find(Z_OBJPROP_P(object), name, name_len)) == NULL) { + if ((value = _default_load_entry(object, name, name_len TSRMLS_CC)) == NULL) { RETURN_FALSE; } - ZVAL_DUP(return_value, value); } /* }}} */ @@ -3102,7 +3111,7 @@ ZEND_METHOD(reflection_function, inNamespace) if (zend_parse_parameters_none() == FAILURE) { return; } - if ((name = zend_hash_str_find(Z_OBJPROP_P(getThis()), "name", sizeof("name")-1)) == NULL) { + if ((name = _default_load_entry(getThis(), "name", sizeof("name")-1) TSRMLS_CC) == NULL) { RETURN_FALSE; } if (Z_TYPE_P(name) == IS_STRING @@ -3125,7 +3134,7 @@ ZEND_METHOD(reflection_function, getNamespaceName) if (zend_parse_parameters_none() == FAILURE) { return; } - if ((name = zend_hash_str_find(Z_OBJPROP_P(getThis()), "name", sizeof("name")-1)) == NULL) { + if ((name = _default_load_entry(getThis(), "name", sizeof("name")-1) TSRMLS_CC) == NULL) { RETURN_FALSE; } if (Z_TYPE_P(name) == IS_STRING @@ -3148,7 +3157,7 @@ ZEND_METHOD(reflection_function, getShortName) if (zend_parse_parameters_none() == FAILURE) { return; } - if ((name = zend_hash_str_find(Z_OBJPROP_P(getThis()), "name", sizeof("name")-1)) == NULL) { + if ((name = _default_load_entry(getThis(), "name", sizeof("name")-1) TSRMLS_CC) == NULL) { RETURN_FALSE; } if (Z_TYPE_P(name) == IS_STRING @@ -4654,7 +4663,7 @@ ZEND_METHOD(reflection_class, inNamespace) if (zend_parse_parameters_none() == FAILURE) { return; } - if ((name = zend_hash_str_find(Z_OBJPROP_P(getThis()), "name", sizeof("name")-1)) == NULL) { + if ((name = _default_load_entry(getThis(), "name", sizeof("name")-1) TSRMLS_CC) == NULL) { RETURN_FALSE; } if (Z_TYPE_P(name) == IS_STRING @@ -4677,7 +4686,7 @@ ZEND_METHOD(reflection_class, getNamespaceName) if (zend_parse_parameters_none() == FAILURE) { return; } - if ((name = zend_hash_str_find(Z_OBJPROP_P(getThis()), "name", sizeof("name")-1)) == NULL) { + if ((name = _default_load_entry(getThis(), "name", sizeof("name")-1) TSRMLS_CC) == NULL) { RETURN_FALSE; } if (Z_TYPE_P(name) == IS_STRING @@ -4700,7 +4709,7 @@ ZEND_METHOD(reflection_class, getShortName) if (zend_parse_parameters_none() == FAILURE) { return; } - if ((name = zend_hash_str_find(Z_OBJPROP_P(getThis()), "name", sizeof("name")-1)) == NULL) { + if ((name = _default_load_entry(getThis(), "name", sizeof("name")-1) TSRMLS_CC) == NULL) { RETURN_FALSE; } if (Z_TYPE_P(name) == IS_STRING @@ -4937,17 +4946,16 @@ ZEND_METHOD(reflection_property, getValue) { reflection_object *intern; property_reference *ref; - zval *object, name; + zval *object, *name; zval *member_p = NULL; METHOD_NOTSTATIC(reflection_property_ptr); GET_REFLECTION_OBJECT_PTR(ref); if (!(ref->prop.flags & (ZEND_ACC_PUBLIC | ZEND_ACC_IMPLICIT_PUBLIC)) && intern->ignore_visibility == 0) { - _default_get_entry(getThis(), "name", sizeof("name")-1, &name TSRMLS_CC); + name = _default_load_entry(getThis(), "name", sizeof("name")-1 TSRMLS_CC); zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, - "Cannot access non-public member %s::%s", intern->ce->name->val, Z_STRVAL(name)); - zval_dtor(&name); + "Cannot access non-public member %s::%s", intern->ce->name->val, Z_STRVAL_P(name)); return; } @@ -4984,7 +4992,7 @@ ZEND_METHOD(reflection_property, setValue) reflection_object *intern; property_reference *ref; zval *variable_ptr; - zval *object, name; + zval *object, *name; zval *value; zval *tmp; @@ -4992,10 +5000,9 @@ ZEND_METHOD(reflection_property, setValue) GET_REFLECTION_OBJECT_PTR(ref); if (!(ref->prop.flags & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) { - _default_get_entry(getThis(), "name", sizeof("name")-1, &name TSRMLS_CC); + name = _default_load_entry(getThis(), "name", sizeof("name")-1 TSRMLS_CC); zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, - "Cannot access non-public member %s::%s", intern->ce->name->val, Z_STRVAL(name)); - zval_dtor(&name); + "Cannot access non-public member %s::%s", intern->ce->name->val, Z_STRVAL_P(name)); return; } diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index c6634ecf8a1..47f5fa2402e 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -324,7 +324,27 @@ static zval *spl_array_get_dimension_ptr(int check_inherited, zval *object, zval case IS_STRING: offset_key = Z_STR_P(offset); fetch_dim_string: - if ((retval = (zend_symtable_find(ht, offset_key))) == NULL) { + retval = zend_symtable_find(ht, offset_key); + if (retval) { + if (Z_TYPE_P(retval) == IS_INDIRECT) { + retval = Z_INDIRECT_P(retval); + if (Z_TYPE_P(retval) == IS_UNDEF) { + switch (type) { + case BP_VAR_R: + zend_error(E_NOTICE, "Undefined index: %s", offset_key->val); + case BP_VAR_UNSET: + case BP_VAR_IS: + retval = &EG(uninitialized_zval); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined index: %s", offset_key->val); + case BP_VAR_W: { + ZVAL_NULL(retval); + } + } + } + } + } else { switch (type) { case BP_VAR_R: zend_error(E_NOTICE, "Undefined index: %s", offset_key->val); @@ -430,6 +450,7 @@ static void spl_array_write_dimension_ex(int check_inherited, zval *object, zval if (check_inherited && intern->fptr_offset_set) { zval tmp; + if (!offset) { ZVAL_NULL(&tmp); offset = &tmp; @@ -464,7 +485,7 @@ static void spl_array_write_dimension_ex(int check_inherited, zval *object, zval zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited"); return; } - zend_symtable_update(ht, Z_STR_P(offset), value); + zend_symtable_update_ind(ht, Z_STR_P(offset), value); return; case IS_DOUBLE: case IS_RESOURCE: @@ -526,36 +547,29 @@ static void spl_array_unset_dimension_ex(int check_inherited, zval *object, zval zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset)); } } else { - if (zend_symtable_del(ht, Z_STR_P(offset)) == FAILURE) { - zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset)); - } else { - spl_array_object *obj = intern; +//??? see below +#if 0 + if (zend_symtable_del_ind(ht, Z_STR_P(offset)) == FAILURE) { +#else + zval *data = zend_symtable_find(ht, Z_STR_P(offset)); - while (1) { - if ((obj->ar_flags & SPL_ARRAY_IS_SELF) != 0) { - break; - } else if (Z_TYPE(obj->array) == IS_OBJECT) { - if ((obj->ar_flags & SPL_ARRAY_USE_OTHER) == 0) { - obj = Z_SPLARRAY_P(&obj->array); - break; - } else { - obj = Z_SPLARRAY_P(&obj->array); - } + if (data) { + if (Z_TYPE_P(data) == IS_INDIRECT) { + data = Z_INDIRECT_P(data); + if (Z_TYPE_P(data) == IS_UNDEF) { + zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset)); } else { - obj = NULL; - break; - } - } - if (obj) { - zend_property_info *property_info = zend_get_property_info(obj->std.ce, offset, 1 TSRMLS_CC); - - if (property_info && - (property_info->flags & ZEND_ACC_STATIC) == 0 && - property_info->offset >= 0) { - zval_ptr_dtor(&obj->std.properties_table[property_info->offset]); - ZVAL_UNDEF(&obj->std.properties_table[property_info->offset]); + zval_ptr_dtor(data); + ZVAL_UNDEF(data); } +//??? fix for ext/spl/tests/bug45614.phpt (may be fix is wrong) + spl_array_rewind(intern TSRMLS_CC); + } else if (zend_symtable_del(ht, Z_STR_P(offset)) == FAILURE) { + zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset)); } + } else { +#endif + zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset)); } } break; @@ -610,7 +624,7 @@ static int spl_array_has_dimension_ex(int check_inherited, zval *object, zval *o case IS_STRING: { HashTable *ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); - if ((tmp = zend_symtable_find(ht, Z_STR_P(offset))) != NULL) { + if ((tmp = zend_symtable_find_ind(ht, Z_STR_P(offset))) != NULL) { switch (check_empty) { case 0: return Z_TYPE_P(tmp) != IS_NULL; @@ -919,11 +933,16 @@ static int spl_array_skip_protected(spl_array_object *intern, HashTable *aht TSR { zend_string *string_key; ulong num_key; + zval *data; if (Z_TYPE(intern->array) == IS_OBJECT) { do { if (zend_hash_get_current_key_ex(aht, &string_key, &num_key, 0, &intern->pos) == HASH_KEY_IS_STRING) { - if (!string_key->len || string_key->val[0]) { + data = zend_hash_get_current_data_ex(aht, &intern->pos); + if (data && Z_TYPE_P(data) == IS_INDIRECT && + Z_TYPE_P(data = Z_INDIRECT_P(data)) == IS_UNDEF) { + /* skip */ + } else if (!string_key->len || string_key->val[0]) { return SUCCESS; } } else { @@ -1002,7 +1021,11 @@ static zval *spl_array_it_get_current_data(zend_object_iterator *iter TSRMLS_DC) if (object->ar_flags & SPL_ARRAY_OVERLOADED_CURRENT) { return zend_user_it_get_current_data(iter TSRMLS_CC); } else { - return zend_hash_get_current_data_ex(aht, &object->pos); + zval *data = zend_hash_get_current_data_ex(aht, &object->pos); + if (Z_TYPE_P(data) == IS_INDIRECT) { + data = Z_INDIRECT_P(data); + } + return data; } } /* }}} */ @@ -1096,14 +1119,14 @@ static void spl_array_set_array(zval *object, spl_array_object *intern, zval *ar ar_flags = other->ar_flags & ~SPL_ARRAY_INT_MASK; } ar_flags |= SPL_ARRAY_USE_OTHER; - intern->array = *array; + ZVAL_COPY_VALUE(&intern->array, array); } else { if (Z_TYPE_P(array) != IS_OBJECT && Z_TYPE_P(array) != IS_ARRAY) { zend_throw_exception(spl_ce_InvalidArgumentException, "Passed variable is not an array or object, using empty array instead", 0 TSRMLS_CC); return; } zval_ptr_dtor(&intern->array); - intern->array = *array; + ZVAL_COPY_VALUE(&intern->array, array); } if (Z_TYPE_P(array) == IS_OBJECT && Z_OBJ_P(object) == Z_OBJ_P(array)) { intern->ar_flags |= SPL_ARRAY_IS_SELF; @@ -1507,6 +1530,12 @@ SPL_METHOD(Array, current) if ((entry = zend_hash_get_current_data_ex(aht, &intern->pos)) == NULL) { return; } + if (Z_TYPE_P(entry) == IS_INDIRECT) { + entry = Z_INDIRECT_P(entry); + if (Z_TYPE_P(entry) == IS_UNDEF) { + return; + } + } RETVAL_ZVAL(entry, 1, 0); } /* }}} */ @@ -1765,10 +1794,7 @@ SPL_METHOD(Array, unserialize) } /* copy members */ - if (!intern->std.properties) { - rebuild_object_properties(&intern->std); - } - zend_hash_copy(intern->std.properties, Z_ARRVAL(members), (copy_ctor_func_t) zval_add_ref); + object_properties_load(&intern->std, Z_ARRVAL(members)); zval_ptr_dtor(&members); /* done reading $serialized */ diff --git a/ext/standard/array.c b/ext/standard/array.c index 84c5f87a434..e2a2f023325 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -370,6 +370,12 @@ static int php_array_data_compare(const void *a, const void *b TSRMLS_DC) /* {{{ first = &f->val; second = &s->val; + if (Z_TYPE_P(first) == IS_INDIRECT) { + first = Z_INDIRECT_P(first); + } + if (Z_TYPE_P(second) == IS_INDIRECT) { + second = Z_INDIRECT_P(second); + } if (ARRAYG(compare_func)(&result, first, second TSRMLS_CC) == FAILURE) { return 0; } @@ -1056,6 +1062,13 @@ static int php_array_walk(HashTable *target_hash, zval *userdata, int recursive /* Iterate through hash */ zend_hash_internal_pointer_reset(target_hash); while (!EG(exception) && (zv = zend_hash_get_current_data(target_hash)) != NULL) { + if (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); + if (Z_TYPE_P(zv) == IS_UNDEF) { + zend_hash_move_forward(target_hash); + continue; + } + } ZVAL_COPY(&args[0], zv); if (recursive && (Z_TYPE(args[0]) == IS_ARRAY || @@ -1332,6 +1345,14 @@ PHP_FUNCTION(extract) while ((entry = zend_hash_get_current_data_ex(Z_ARRVAL_P(var_array), &pos)) != NULL) { zval final_name; + if (Z_TYPE_P(entry) == IS_INDIRECT) { + entry = Z_INDIRECT_P(entry); + if (Z_TYPE_P(entry) == IS_UNDEF) { + zend_hash_move_forward_ex(Z_ARRVAL_P(var_array), &pos); + continue; + } + } + ZVAL_NULL(&final_name); key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(var_array), &var_name, &num_key, 0, &pos); @@ -1410,6 +1431,9 @@ PHP_FUNCTION(extract) Z_ADDREF_P(entry); if ((orig_var = zend_hash_find(&EG(active_symbol_table)->ht, Z_STR(final_name))) != NULL) { + if (Z_TYPE_P(orig_var) == IS_INDIRECT) { + orig_var = Z_INDIRECT_P(orig_var); + } zval_ptr_dtor(orig_var); ZVAL_COPY_VALUE(orig_var, entry); } else { @@ -1417,7 +1441,7 @@ PHP_FUNCTION(extract) } } else { ZVAL_DUP(&data, entry); - ZEND_SET_SYMBOL_WITH_LENGTH(&EG(active_symbol_table)->ht, Z_STRVAL(final_name), Z_STRLEN(final_name), &data, 1, 0); + zend_set_local_var(Z_STRVAL(final_name), Z_STRLEN(final_name), &data, 1 TSRMLS_CC); } count++; } @@ -1442,12 +1466,11 @@ static void php_compact_var(HashTable *eg_active_symbol_table, zval *return_valu entry = Z_REFVAL_P(entry); } if (Z_TYPE_P(entry) == IS_STRING) { - if ((value_ptr = zend_hash_find(eg_active_symbol_table, Z_STR_P(entry))) != NULL) { + if ((value_ptr = zend_hash_find_ind(eg_active_symbol_table, Z_STR_P(entry))) != NULL) { ZVAL_DUP(&data, value_ptr); zend_hash_update(Z_ARRVAL_P(return_value), Z_STR_P(entry), &data); } - } - else if (Z_TYPE_P(entry) == IS_ARRAY) { + } else if (Z_TYPE_P(entry) == IS_ARRAY) { HashPosition pos; if ((Z_ARRVAL_P(entry)->nApplyCount > 1)) { @@ -1459,6 +1482,13 @@ static void php_compact_var(HashTable *eg_active_symbol_table, zval *return_valu zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(entry), &pos); while ((value_ptr = zend_hash_get_current_data_ex(Z_ARRVAL_P(entry), &pos)) != NULL) { + if (Z_TYPE_P(value_ptr) == IS_INDIRECT) { + value_ptr = Z_INDIRECT_P(value_ptr); + if (Z_TYPE_P(value_ptr) == IS_UNDEF) { + zend_hash_move_forward_ex(Z_ARRVAL_P(entry), &pos); + continue; + } + } php_compact_var(eg_active_symbol_table, return_value, value_ptr TSRMLS_CC); zend_hash_move_forward_ex(Z_ARRVAL_P(entry), &pos); } @@ -1963,7 +1993,19 @@ static void _phpi_pop(INTERNAL_FUNCTION_PARAMETERS, int off_the_end) } else { zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack)); } - val = zend_hash_get_current_data(Z_ARRVAL_P(stack)); + while (1) { + val = zend_hash_get_current_data(Z_ARRVAL_P(stack)); + if (!val) { + return; + } else if (Z_TYPE_P(val) == IS_INDIRECT) { + val = Z_INDIRECT_P(val); + if (Z_TYPE_P(val) == IS_UNDEF) { + zend_hash_move_forward(Z_ARRVAL_P(stack)); + continue; + } + } + break; + } RETVAL_ZVAL_FAST(val); /* Delete the first or last value */ @@ -2045,9 +2087,6 @@ PHP_FUNCTION(array_unshift) * hashtable and replace it with new one */ new_hash = php_splice(Z_ARRVAL_P(stack), 0, 0, &args[0], argc, NULL); old_hash = *Z_ARRVAL_P(stack); - if (Z_ARRVAL_P(stack) == &EG(symbol_table).ht) { - zend_reset_all_cv(&EG(symbol_table) TSRMLS_CC); - } *Z_ARRVAL_P(stack) = *new_hash; FREE_HASHTABLE(new_hash); zend_hash_destroy(&old_hash); @@ -2128,9 +2167,6 @@ PHP_FUNCTION(array_splice) /* Replace input array's hashtable with the new one */ old_hash = *Z_ARRVAL_P(array); - if (Z_ARRVAL_P(array) == &EG(symbol_table).ht) { - zend_reset_all_cv(&EG(symbol_table) TSRMLS_CC); - } *Z_ARRVAL_P(array) = *new_hash; FREE_HASHTABLE(new_hash); zend_hash_destroy(&old_hash); @@ -2789,9 +2825,6 @@ PHP_FUNCTION(array_pad) /* Copy the result hash into return value */ old_hash = *Z_ARRVAL_P(return_value); - if (Z_ARRVAL_P(return_value) == &EG(symbol_table).ht) { - zend_reset_all_cv(&EG(symbol_table) TSRMLS_CC); - } *Z_ARRVAL_P(return_value) = *new_hash; FREE_HASHTABLE(new_hash); zend_hash_destroy(&old_hash); @@ -2911,6 +2944,7 @@ PHP_FUNCTION(array_unique) for (i = 0, idx = 0; idx < Z_ARRVAL_P(array)->nNumUsed; idx++) { p = Z_ARRVAL_P(array)->arData + idx; if (Z_TYPE(p->val) == IS_UNDEF) continue; + if (Z_TYPE(p->val) == IS_INDIRECT && Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF) continue; arTmp[i].b = *p; arTmp[i].i = i; i++; @@ -2954,6 +2988,12 @@ static int zval_compare(zval *a, zval *b TSRMLS_DC) /* {{{ */ first = a; second = b; + if (Z_TYPE_P(first) == IS_INDIRECT) { + first = Z_INDIRECT_P(first); + } + if (Z_TYPE_P(second) == IS_INDIRECT) { + second = Z_INDIRECT_P(second); + } if (string_compare_function(&result, first, second TSRMLS_CC) == FAILURE) { return 0; } @@ -2985,6 +3025,13 @@ static int zval_user_compare(zval *a, zval *b TSRMLS_DC) /* {{{ */ zval args[2]; zval retval; + if (Z_TYPE_P(a) == IS_INDIRECT) { + a = Z_INDIRECT_P(a); + } + if (Z_TYPE_P(b) == IS_INDIRECT) { + b = Z_INDIRECT_P(b); + } + ZVAL_COPY_VALUE(&args[0], a); ZVAL_COPY_VALUE(&args[1], b); diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index d666c025bb3..2018c90b928 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -4265,13 +4265,16 @@ PHP_FUNCTION(getopt) * in order to be on the safe side, even though it is also available * from the symbol table. */ if (Z_TYPE(PG(http_globals)[TRACK_VARS_SERVER]) != IS_UNDEF && - ((args = zend_hash_str_find(HASH_OF(&PG(http_globals)[TRACK_VARS_SERVER]), "argv", sizeof("argv")-1)) != NULL || - (args = zend_hash_str_find(&EG(symbol_table).ht, "argv", sizeof("argv")-1)) != NULL) && Z_TYPE_P(args) == IS_ARRAY + ((args = zend_hash_str_find_ind(HASH_OF(&PG(http_globals)[TRACK_VARS_SERVER]), "argv", sizeof("argv")-1)) != NULL || + (args = zend_hash_str_find_ind(&EG(symbol_table).ht, "argv", sizeof("argv")-1)) != NULL) ) { int pos = 0; zval *entry; - argc = zend_hash_num_elements(Z_ARRVAL_P(args)); + if (Z_TYPE_P(args) != IS_ARRAY) { + RETURN_FALSE; + } + argc = zend_hash_num_elements(Z_ARRVAL_P(args)); /* Attempt to allocate enough memory to hold all of the arguments * and a trailing NULL */ diff --git a/ext/standard/http.c b/ext/standard/http.c index 62437f82d69..fc5727d7ce9 100644 --- a/ext/standard/http.c +++ b/ext/standard/http.c @@ -82,6 +82,12 @@ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr, php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error traversing form data array"); return FAILURE; } + if (Z_TYPE_P(zdata) == IS_INDIRECT) { + zdata = Z_INDIRECT_P(zdata); + if (Z_TYPE_P(zdata) == IS_UNDEF) { + continue; + } + } if (Z_TYPE_P(zdata) == IS_ARRAY || Z_TYPE_P(zdata) == IS_OBJECT) { if (key_type == HASH_KEY_IS_STRING) { zend_string *ekey; diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c index 29e5db0ebf2..0fdba305592 100644 --- a/ext/standard/http_fopen_wrapper.c +++ b/ext/standard/http_fopen_wrapper.c @@ -659,7 +659,7 @@ finish: if (header_init) { zval ztmp; array_init(&ztmp); - ZEND_SET_SYMBOL(&EG(active_symbol_table)->ht, "http_response_header", &ztmp); + zend_set_local_var("http_response_header", sizeof("http_response_header")-1, &ztmp, 0 TSRMLS_CC); } response_header = zend_hash_str_find(&EG(active_symbol_table)->ht, "http_response_header", sizeof("http_response_header")-1); diff --git a/ext/standard/var.c b/ext/standard/var.c index 8c2694bef7d..9ea1119cea6 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -35,12 +35,37 @@ #define COMMON (is_ref ? "&" : "") /* }}} */ +static uint zend_obj_num_elements(HashTable *ht) +{ + Bucket *p; + uint idx; + uint num; + + num = ht->nNumOfElements; + for (idx = 0; idx < ht->nNumUsed; idx++) { + p = ht->arData + idx; + if (Z_TYPE(p->val) == IS_UNDEF) continue; + if (Z_TYPE(p->val) == IS_INDIRECT) { + if (Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF) { + num--; + } + } + } + return num; +} + static int php_array_element_dump(zval *zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */ { int level; level = va_arg(args, int); + if (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); + if (Z_TYPE_P(zv) == IS_UNDEF) { + return 0; + } + } if (hash_key->key == NULL) { /* numeric key */ php_printf("%*c[%ld]=>\n", level + 1, ' ', hash_key->h); } else { /* string key */ @@ -60,6 +85,12 @@ static int php_object_property_dump(zval *zv TSRMLS_DC, int num_args, va_list ar level = va_arg(args, int); + if (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); + if (Z_TYPE_P(zv) == IS_UNDEF) { + return 0; + } + } if (hash_key->key == NULL) { /* numeric key */ php_printf("%*c[%ld]=>\n", level + 1, ' ', hash_key->h); } else { /* string key */ @@ -136,10 +167,10 @@ again: if (Z_OBJ_HANDLER_P(struc, get_class_name)) { class_name = Z_OBJ_HANDLER_P(struc, get_class_name)(struc, 0 TSRMLS_CC); - php_printf("%sobject(%s)#%d (%d) {\n", COMMON, class_name->val, Z_OBJ_HANDLE_P(struc), myht ? zend_hash_num_elements(myht) : 0); + php_printf("%sobject(%s)#%d (%d) {\n", COMMON, class_name->val, Z_OBJ_HANDLE_P(struc), myht ? zend_obj_num_elements(myht) : 0); STR_RELEASE(class_name); } else { - php_printf("%sobject(unknown class)#%d (%d) {\n", COMMON, Z_OBJ_HANDLE_P(struc), myht ? zend_hash_num_elements(myht) : 0); + php_printf("%sobject(unknown class)#%d (%d) {\n", COMMON, Z_OBJ_HANDLE_P(struc), myht ? zend_obj_num_elements(myht) : 0); } php_element_dump_func = php_object_property_dump; head_done: @@ -162,7 +193,7 @@ again: break; } case IS_REFERENCE: - //??? hide references with refcount==1 (for compatibility) +//??? hide references with refcount==1 (for compatibility) if (Z_REFCOUNT_P(struc) > 1) { is_ref = 1; } @@ -200,6 +231,12 @@ static int zval_array_element_dump(zval *zv TSRMLS_DC, int num_args, va_list arg level = va_arg(args, int); + if (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); + if (Z_TYPE_P(zv) == IS_UNDEF) { + return 0; + } + } if (hash_key->key == NULL) { /* numeric key */ php_printf("%*c[%ld]=>\n", level + 1, ' ', hash_key->h); } else { /* string key */ @@ -225,6 +262,12 @@ static int zval_object_property_dump(zval *zv TSRMLS_DC, int num_args, va_list a level = va_arg(args, int); + if (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); + if (Z_TYPE_P(zv) == IS_UNDEF) { + return 0; + } + } if (hash_key->key == NULL) { /* numeric key */ php_printf("%*c[%ld]=>\n", level + 1, ' ', hash_key->h); } else { /* string key */ @@ -259,14 +302,7 @@ PHPAPI void php_debug_zval_dump(zval *struc, int level TSRMLS_DC) /* {{{ */ php_printf("%*c", level - 1, ' '); } - if (Z_TYPE_P(struc) == IS_REFERENCE) { -//??? hide references with refcount==1 (for compatibility) - if (Z_REFCOUNT_P(struc) > 1) { - is_ref = 1; - } - struc = Z_REFVAL_P(struc); - } - +again: switch (Z_TYPE_P(struc)) { case IS_BOOL: php_printf("%sbool(%s)\n", COMMON, Z_LVAL_P(struc)?"true":"false"); @@ -301,7 +337,7 @@ PHPAPI void php_debug_zval_dump(zval *struc, int level TSRMLS_DC) /* {{{ */ return; } class_name = Z_OBJ_HANDLER_P(struc, get_class_name)(struc, 0 TSRMLS_CC); - php_printf("%sobject(%s)#%d (%d) refcount(%u){\n", COMMON, class_name->val, Z_OBJ_HANDLE_P(struc), myht ? zend_hash_num_elements(myht) : 0, Z_REFCOUNT_P(struc)); + php_printf("%sobject(%s)#%d (%d) refcount(%u){\n", COMMON, class_name->val, Z_OBJ_HANDLE_P(struc), myht ? zend_obj_num_elements(myht) : 0, Z_REFCOUNT_P(struc)); STR_RELEASE(class_name); zval_element_dump_func = zval_object_property_dump; head_done: @@ -322,6 +358,13 @@ head_done: php_printf("%sresource(%ld) of type (%s) refcount(%u)\n", COMMON, Z_RES_P(struc)->handle, type_name ? type_name : "Unknown", Z_REFCOUNT_P(struc)); break; } + case IS_REFERENCE: +//??? hide references with refcount==1 (for compatibility) + if (Z_REFCOUNT_P(struc) > 1) { + is_ref = 1; + } + struc = Z_REFVAL_P(struc); + goto again; default: php_printf("%sUNKNOWN:0\n", COMMON); break; @@ -364,6 +407,12 @@ static int php_array_element_export(zval *zv TSRMLS_DC, int num_args, va_list ar level = va_arg(args, int); buf = va_arg(args, smart_str *); + if (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); + if (Z_TYPE_P(zv) == IS_UNDEF) { + return 0; + } + } if (hash_key->key == NULL) { /* numeric key */ buffer_append_spaces(buf, level+1); smart_str_append_long(buf, (long) hash_key->h); @@ -400,6 +449,13 @@ static int php_object_element_export(zval *zv TSRMLS_DC, int num_args, va_list a level = va_arg(args, int); buf = va_arg(args, smart_str *); + if (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); + if (Z_TYPE_P(zv) == IS_UNDEF) { + return 0; + } + } + buffer_append_spaces(buf, level + 2); if (hash_key->key != NULL) { const char *class_name; /* ignored, but must be passed to unmangle */ @@ -683,6 +739,12 @@ static void php_var_serialize_class(smart_str *buf, zval *struc, zval *retval_pt } propers = Z_OBJPROP_P(struc); if ((d = zend_hash_find(propers, Z_STR_P(name))) != NULL) { + if (Z_TYPE_P(d) == IS_INDIRECT) { + d = Z_INDIRECT_P(d); + if (Z_TYPE_P(d) == IS_UNDEF) { + continue; + } + } php_var_serialize_string(buf, Z_STRVAL_P(name), Z_STRLEN_P(name)); php_var_serialize_intern(buf, d, var_hash TSRMLS_CC); } else { @@ -694,6 +756,13 @@ static void php_var_serialize_class(smart_str *buf, zval *struc, zval *retval_pt do { priv_name = zend_mangle_property_name(ce->name->val, ce->name->len, Z_STRVAL_P(name), Z_STRLEN_P(name), ce->type & ZEND_INTERNAL_CLASS); if ((d = zend_hash_find(propers, priv_name)) != NULL) { + if (Z_TYPE_P(d) == IS_INDIRECT) { + d = Z_INDIRECT_P(d); + if (Z_TYPE_P(d) == IS_UNDEF) { + STR_FREE(prot_name); + break; + } + } php_var_serialize_string(buf, priv_name->val, priv_name->len); STR_FREE(priv_name); php_var_serialize_intern(buf, d, var_hash TSRMLS_CC); @@ -702,6 +771,13 @@ static void php_var_serialize_class(smart_str *buf, zval *struc, zval *retval_pt STR_FREE(priv_name); prot_name = zend_mangle_property_name("*", 1, Z_STRVAL_P(name), Z_STRLEN_P(name), ce->type & ZEND_INTERNAL_CLASS); if ((d = zend_hash_find(propers, prot_name)) != NULL) { + if (Z_TYPE_P(d) == IS_INDIRECT) { + d = Z_INDIRECT_P(d); + if (Z_TYPE_P(d) == IS_UNDEF) { + STR_FREE(prot_name); + break; + } + } php_var_serialize_string(buf, prot_name->val, prot_name->len); STR_FREE(prot_name); php_var_serialize_intern(buf, d, var_hash TSRMLS_CC); @@ -873,10 +949,17 @@ again: zend_hash_internal_pointer_reset_ex(myht, &pos); for (;; zend_hash_move_forward_ex(myht, &pos)) { - i = zend_hash_get_current_key_ex(myht, &key, &index, 0, &pos); - if (i == HASH_KEY_NON_EXISTENT) { + data = zend_hash_get_current_data_ex(myht, &pos); + if (!data) { break; + } else if (Z_TYPE_P(data) == IS_INDIRECT) { + data = Z_INDIRECT_P(data); + if (Z_TYPE_P(data) == IS_UNDEF) { + continue; + } } + + i = zend_hash_get_current_key_ex(myht, &key, &index, 0, &pos); if (incomplete_class && strcmp(key->val, MAGIC_MEMBER) == 0) { continue; } @@ -892,8 +975,7 @@ again: /* we should still add element even if it's not OK, * since we already wrote the length of the array before */ - if ((data = zend_hash_get_current_data_ex(myht, &pos)) == NULL - || (Z_TYPE_P(data) == IS_ARRAY && Z_TYPE_P(struc) == IS_ARRAY && Z_ARR_P(data) == Z_ARR_P(struc)) + if ((Z_TYPE_P(data) == IS_ARRAY && Z_TYPE_P(struc) == IS_ARRAY && Z_ARR_P(data) == Z_ARR_P(struc)) || (Z_TYPE_P(data) == IS_ARRAY && Z_ARRVAL_P(data)->nApplyCount > 1) ) { smart_str_appendl(buf, "N;", 2); diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index 8e69338b021..13f645b58e1 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -79,7 +79,7 @@ PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval *rval) (*var_hashx)->last_dtor = var_hash; } - Z_ADDREF_P(rval); + if (Z_REFCOUNTED_P(rval)) Z_ADDREF_P(rval); var_hash->data[var_hash->used_slots++] = rval; } @@ -306,7 +306,21 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long } else { /* object properties should include no integers */ convert_to_string(&key); - data = zend_hash_update(ht, Z_STR(key), &d); +//??? +#if 1 + data = zend_hash_update_ind(ht, Z_STR(key), &d); +#else + if ((data = zend_hash_find(ht, Z_STR(key))) != NULL) { + if (Z_TYPE_P(data) == IS_INDIRECT) { + data = Z_INDIRECT_P(data); + } + zval_ptr_dtor(data); +//??? var_push_dtor(var_hash, data); + ZVAL_UNDEF(data); + } else { + data = zend_hash_update(ht, Z_STR(key), &d); + } +#endif } zval_dtor(&key); @@ -428,7 +442,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) start = cursor; -#line 432 "ext/standard/var_unserializer.c" +#line 446 "ext/standard/var_unserializer.c" { YYCTYPE yych; static const unsigned char yybm[] = { @@ -488,9 +502,9 @@ yy2: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy95; yy3: -#line 778 "ext/standard/var_unserializer.re" +#line 792 "ext/standard/var_unserializer.re" { return 0; } -#line 494 "ext/standard/var_unserializer.c" +#line 508 "ext/standard/var_unserializer.c" yy4: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy89; @@ -533,13 +547,13 @@ yy13: goto yy3; yy14: ++YYCURSOR; -#line 772 "ext/standard/var_unserializer.re" +#line 786 "ext/standard/var_unserializer.re" { /* this is the case where we have less data than planned */ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data"); return 0; /* not sure if it should be 0 or 1 here? */ } -#line 543 "ext/standard/var_unserializer.c" +#line 557 "ext/standard/var_unserializer.c" yy16: yych = *++YYCURSOR; goto yy3; @@ -569,7 +583,7 @@ yy20: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 633 "ext/standard/var_unserializer.re" +#line 647 "ext/standard/var_unserializer.re" { size_t len, len2, len3, maxlen; long elements; @@ -708,7 +722,7 @@ yy20: return object_common2(UNSERIALIZE_PASSTHRU, elements); } -#line 712 "ext/standard/var_unserializer.c" +#line 726 "ext/standard/var_unserializer.c" yy25: yych = *++YYCURSOR; if (yych <= ',') { @@ -733,7 +747,7 @@ yy27: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 625 "ext/standard/var_unserializer.re" +#line 639 "ext/standard/var_unserializer.re" { //??? INIT_PZVAL(rval); @@ -741,7 +755,7 @@ yy27: return object_common2(UNSERIALIZE_PASSTHRU, object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR)); } -#line 745 "ext/standard/var_unserializer.c" +#line 759 "ext/standard/var_unserializer.c" yy32: yych = *++YYCURSOR; if (yych == '+') goto yy33; @@ -762,7 +776,7 @@ yy34: yych = *++YYCURSOR; if (yych != '{') goto yy18; ++YYCURSOR; -#line 604 "ext/standard/var_unserializer.re" +#line 618 "ext/standard/var_unserializer.re" { long elements = parse_iv(start + 2); /* use iv() not uiv() in order to check data range */ @@ -783,7 +797,7 @@ yy34: return finish_nested_data(UNSERIALIZE_PASSTHRU); } -#line 787 "ext/standard/var_unserializer.c" +#line 801 "ext/standard/var_unserializer.c" yy39: yych = *++YYCURSOR; if (yych == '+') goto yy40; @@ -804,7 +818,7 @@ yy41: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 574 "ext/standard/var_unserializer.re" +#line 588 "ext/standard/var_unserializer.re" { size_t len, maxlen; //??? TODO: use zend_string* instead of char* @@ -834,7 +848,7 @@ yy41: efree(str); return 1; } -#line 838 "ext/standard/var_unserializer.c" +#line 852 "ext/standard/var_unserializer.c" yy46: yych = *++YYCURSOR; if (yych == '+') goto yy47; @@ -855,7 +869,7 @@ yy48: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 547 "ext/standard/var_unserializer.re" +#line 561 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -882,7 +896,7 @@ yy48: ZVAL_STRINGL(rval, str, len); return 1; } -#line 886 "ext/standard/var_unserializer.c" +#line 900 "ext/standard/var_unserializer.c" yy53: yych = *++YYCURSOR; if (yych <= '/') { @@ -970,7 +984,7 @@ yy61: } yy63: ++YYCURSOR; -#line 538 "ext/standard/var_unserializer.re" +#line 552 "ext/standard/var_unserializer.re" { #if SIZEOF_LONG == 4 use_double: @@ -979,7 +993,7 @@ use_double: ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL)); return 1; } -#line 983 "ext/standard/var_unserializer.c" +#line 997 "ext/standard/var_unserializer.c" yy65: yych = *++YYCURSOR; if (yych <= ',') { @@ -1038,7 +1052,7 @@ yy73: yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 522 "ext/standard/var_unserializer.re" +#line 536 "ext/standard/var_unserializer.re" { *p = YYCURSOR; @@ -1054,7 +1068,7 @@ yy73: return 1; } -#line 1058 "ext/standard/var_unserializer.c" +#line 1072 "ext/standard/var_unserializer.c" yy76: yych = *++YYCURSOR; if (yych == 'N') goto yy73; @@ -1081,7 +1095,7 @@ yy79: if (yych <= '9') goto yy79; if (yych != ';') goto yy18; ++YYCURSOR; -#line 496 "ext/standard/var_unserializer.re" +#line 510 "ext/standard/var_unserializer.re" { #if SIZEOF_LONG == 4 int digits = YYCURSOR - start - 3; @@ -1107,7 +1121,7 @@ yy79: ZVAL_LONG(rval, parse_iv(start + 2)); return 1; } -#line 1111 "ext/standard/var_unserializer.c" +#line 1125 "ext/standard/var_unserializer.c" yy83: yych = *++YYCURSOR; if (yych <= '/') goto yy18; @@ -1115,22 +1129,22 @@ yy83: yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 490 "ext/standard/var_unserializer.re" +#line 504 "ext/standard/var_unserializer.re" { *p = YYCURSOR; ZVAL_BOOL(rval, parse_iv(start + 2)); return 1; } -#line 1125 "ext/standard/var_unserializer.c" +#line 1139 "ext/standard/var_unserializer.c" yy87: ++YYCURSOR; -#line 484 "ext/standard/var_unserializer.re" +#line 498 "ext/standard/var_unserializer.re" { *p = YYCURSOR; ZVAL_NULL(rval); return 1; } -#line 1134 "ext/standard/var_unserializer.c" +#line 1148 "ext/standard/var_unserializer.c" yy89: yych = *++YYCURSOR; if (yych <= ',') { @@ -1153,7 +1167,7 @@ yy91: if (yych <= '9') goto yy91; if (yych != ';') goto yy18; ++YYCURSOR; -#line 461 "ext/standard/var_unserializer.re" +#line 475 "ext/standard/var_unserializer.re" { long id; @@ -1176,7 +1190,7 @@ yy91: return 1; } -#line 1180 "ext/standard/var_unserializer.c" +#line 1194 "ext/standard/var_unserializer.c" yy95: yych = *++YYCURSOR; if (yych <= ',') { @@ -1199,7 +1213,7 @@ yy97: if (yych <= '9') goto yy97; if (yych != ';') goto yy18; ++YYCURSOR; -#line 436 "ext/standard/var_unserializer.re" +#line 450 "ext/standard/var_unserializer.re" { long id; @@ -1224,9 +1238,9 @@ yy97: return 1; } -#line 1228 "ext/standard/var_unserializer.c" +#line 1242 "ext/standard/var_unserializer.c" } -#line 780 "ext/standard/var_unserializer.re" +#line 794 "ext/standard/var_unserializer.re" return 0; diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index ae195ae88bf..cda2dcd4528 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -77,7 +77,7 @@ PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval *rval) (*var_hashx)->last_dtor = var_hash; } - Z_ADDREF_P(rval); + if (Z_REFCOUNTED_P(rval)) Z_ADDREF_P(rval); var_hash->data[var_hash->used_slots++] = rval; } @@ -310,7 +310,21 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long } else { /* object properties should include no integers */ convert_to_string(&key); - data = zend_hash_update(ht, Z_STR(key), &d); +//??? +#if 1 + data = zend_hash_update_ind(ht, Z_STR(key), &d); +#else + if ((data = zend_hash_find(ht, Z_STR(key))) != NULL) { + if (Z_TYPE_P(data) == IS_INDIRECT) { + data = Z_INDIRECT_P(data); + } + zval_ptr_dtor(data); +//??? var_push_dtor(var_hash, data); + ZVAL_UNDEF(data); + } else { + data = zend_hash_update(ht, Z_STR(key), &d); + } +#endif } zval_dtor(&key); diff --git a/main/main.c b/main/main.c index 0f8a029b513..931a5246c65 100644 --- a/main/main.c +++ b/main/main.c @@ -857,13 +857,10 @@ PHPAPI void php_verror(const char *docref, const char *params, int type, const c if (PG(track_errors) && module_initialized && (Z_TYPE(EG(user_error_handler)) == IS_UNDEF || !(EG(user_error_handler_error_reporting) & type))) { - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); - } - if (EG(active_symbol_table)) { - zval tmp; - ZVAL_STRINGL(&tmp, buffer, buffer_len); - zend_hash_str_update(&EG(active_symbol_table)->ht, "php_errormsg", sizeof("php_errormsg")-1, &tmp); + zval tmp; + ZVAL_STRINGL(&tmp, buffer, buffer_len); + if (zend_set_local_var("php_errormsg", sizeof("php_errormsg")-1, &tmp, 0 TSRMLS_CC) == FAILURE) { + zval_ptr_dtor(&tmp); } } if (replace_buffer) { @@ -1195,7 +1192,9 @@ static void php_error_cb(int type, const char *error_filename, const uint error_ if (EG(active_symbol_table)) { zval tmp; ZVAL_STRINGL(&tmp, buffer, buffer_len); - zend_hash_str_update(&EG(active_symbol_table)->ht, "php_errormsg", sizeof("php_errormsg")-1, &tmp); + if (zend_set_local_var("php_errormsg", sizeof("php_errormsg")-1, &tmp, 0 TSRMLS_CC) == FAILURE) { + zval_ptr_dtor(&tmp); + } } } diff --git a/main/php_variables.c b/main/php_variables.c index 47b2c522bde..20bee7e8d9f 100644 --- a/main/php_variables.c +++ b/main/php_variables.c @@ -181,10 +181,19 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars return; } } else { - if ((gpc_element_p = zend_symtable_str_find(symtable1, index, index_len)) == NULL - || Z_TYPE_P(gpc_element_p) != IS_ARRAY) { - array_init(&gpc_element); - gpc_element_p = zend_symtable_str_update(symtable1, index, index_len, &gpc_element); + gpc_element_p = zend_symtable_str_find(symtable1, index, index_len); + if (!gpc_element_p) { + zval tmp; + array_init(&tmp); + gpc_element_p = zend_symtable_str_update_ind(symtable1, index, index_len, &tmp); + } else { + if (Z_TYPE_P(gpc_element_p) == IS_INDIRECT) { + gpc_element_p = Z_INDIRECT_P(gpc_element_p); + } + if (Z_TYPE_P(gpc_element_p) != IS_ARRAY) { + zval_ptr_dtor(gpc_element_p); + array_init(gpc_element_p); + } } } symtable1 = Z_ARRVAL_P(gpc_element_p); @@ -219,7 +228,7 @@ plain_var: zend_symtable_str_exists(symtable1, index, index_len)) { zval_ptr_dtor(&gpc_element); } else { - gpc_element_p = zend_symtable_str_update(symtable1, index, index_len, &gpc_element); + gpc_element_p = zend_symtable_str_update_ind(symtable1, index, index_len, &gpc_element); } } }