From 6499162ff0d8aa6e862d3e3cdd2288b87636b8a1 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 28 Apr 2016 04:13:34 +0300 Subject: [PATCH] - get rid of EG(scope). zend_get_executed_scope() should be used instead. - ichanged zval_update_constant_ex(). Use IS_TYPE_IMMUTABLE flag on shared constants and AST, instead of "inline_change" parameter. --- ...nt_expressions_self_referencing_array.phpt | 2 +- Zend/zend_API.c | 108 ++++++------ Zend/zend_ast.c | 20 +-- Zend/zend_builtin_functions.c | 44 +++-- Zend/zend_constants.c | 26 +-- Zend/zend_execute.c | 11 +- Zend/zend_execute.h | 5 +- Zend/zend_execute_API.c | 73 ++++---- Zend/zend_generators.c | 5 +- Zend/zend_globals.h | 2 +- Zend/zend_ini_parser.y | 2 +- Zend/zend_object_handlers.c | 117 +++++++++---- Zend/zend_objects.c | 40 ++--- Zend/zend_types.h | 5 + Zend/zend_vm_def.h | 76 +++------ Zend/zend_vm_execute.h | 159 +++++++----------- .../transliterator/transliterator_class.c | 8 +- ext/mysqli/mysqli.c | 2 +- ext/opcache/zend_accelerator_util_funcs.c | 57 ------- ext/opcache/zend_persist.c | 120 +------------ ext/pdo/pdo_dbh.c | 2 +- ext/pdo/pdo_stmt.c | 2 +- ext/pgsql/pgsql.c | 2 +- ext/reflection/php_reflection.c | 42 ++--- ext/soap/php_encoding.c | 21 +-- ext/spl/spl_engine.h | 2 +- ext/standard/array.c | 7 +- ext/standard/assert.c | 3 - ext/standard/basic_functions.c | 6 +- ext/wddx/wddx.c | 6 +- main/streams/userspace.c | 2 +- sapi/phpdbg/phpdbg_frame.c | 4 - sapi/phpdbg/phpdbg_list.c | 5 +- sapi/phpdbg/phpdbg_print.c | 6 +- sapi/phpdbg/phpdbg_prompt.c | 2 - sapi/phpdbg/phpdbg_watch.c | 4 +- 36 files changed, 409 insertions(+), 589 deletions(-) diff --git a/Zend/tests/constant_expressions_self_referencing_array.phpt b/Zend/tests/constant_expressions_self_referencing_array.phpt index 63f2b20ef5..c584b5d503 100644 --- a/Zend/tests/constant_expressions_self_referencing_array.phpt +++ b/Zend/tests/constant_expressions_self_referencing_array.phpt @@ -9,7 +9,7 @@ class A { var_dump(A::FOO); ?> --EXPECTF-- -Fatal error: Uncaught Error: Cannot declare self-referencing constant 'self::FOO' in %s:%d +Fatal error: Uncaught Error: Cannot declare self-referencing constant 'self::BAR' in %s:%d Stack trace: #0 {main} thrown in %s on line %d diff --git a/Zend/zend_API.c b/Zend/zend_API.c index fdb9628dbf..9963ef322a 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1063,11 +1063,11 @@ ZEND_API int _array_init(zval *arg, uint32_t size ZEND_FILE_LINE_DC) /* {{{ */ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */ { const zend_object_handlers *obj_ht = Z_OBJ_HT_P(obj); - zend_class_entry *old_scope = EG(scope); + zend_class_entry *old_scope = EG(fake_scope); zend_string *key; zval *value; - EG(scope) = Z_OBJCE_P(obj); + EG(fake_scope) = Z_OBJCE_P(obj); ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, value) { if (key) { zval member; @@ -1076,7 +1076,7 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */ obj_ht->write_property(obj, &member, value, NULL); } } ZEND_HASH_FOREACH_END(); - EG(scope) = old_scope; + EG(fake_scope) = old_scope; } /* }}} */ @@ -1119,18 +1119,15 @@ ZEND_API int zend_update_class_constants(zend_class_entry *class_type) /* {{{ */ } } } else { - zend_class_entry **scope = EG(current_execute_data) ? &EG(scope) : &CG(active_class_entry); - zend_class_entry *old_scope = *scope; zend_class_entry *ce; zend_class_constant *c; zval *val; zend_property_info *prop_info; - *scope = class_type; ZEND_HASH_FOREACH_PTR(&class_type->constants_table, c) { val = &c->value; if (Z_CONSTANT_P(val)) { - if (UNEXPECTED(zval_update_constant_ex(val, 1, class_type) != SUCCESS)) { + if (UNEXPECTED(zval_update_constant_ex(val, class_type) != SUCCESS)) { return FAILURE; } } @@ -1147,8 +1144,7 @@ ZEND_API int zend_update_class_constants(zend_class_entry *class_type) /* {{{ */ } ZVAL_DEREF(val); if (Z_CONSTANT_P(val)) { - *scope = ce; - if (UNEXPECTED(zval_update_constant_ex(val, 1, NULL) != SUCCESS)) { + if (UNEXPECTED(zval_update_constant_ex(val, ce) != SUCCESS)) { return FAILURE; } } @@ -1156,8 +1152,6 @@ ZEND_API int zend_update_class_constants(zend_class_entry *class_type) /* {{{ */ } ZEND_HASH_FOREACH_END(); ce = ce->parent; } - - *scope = old_scope; } } return SUCCESS; @@ -1221,15 +1215,15 @@ ZEND_API void object_properties_load(zend_object *object, HashTable *properties) size_t prop_name_len; if (zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_name_len) == SUCCESS) { zend_string *pname = zend_string_init(prop_name, prop_name_len, 0); - zend_class_entry *prev_scope = EG(scope); + zend_class_entry *prev_scope = EG(fake_scope); if (class_name && class_name[0] != '*') { zend_string *cname = zend_string_init(class_name, strlen(class_name), 0); - EG(scope) = zend_lookup_class(cname); + EG(fake_scope) = zend_lookup_class(cname); zend_string_release(cname); } property_info = zend_get_property_info(object->ce, pname, 1); zend_string_release(pname); - EG(scope) = prev_scope; + EG(fake_scope) = prev_scope; } else { property_info = ZEND_WRONG_PROPERTY_INFO; } @@ -2819,7 +2813,7 @@ ZEND_API int zend_disable_class(char *class_name, size_t class_name_length) /* { } /* }}} */ -static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache *fcc, int *strict_class, char **error) /* {{{ */ +static int zend_is_callable_check_class(zend_string *name, zend_class_entry *scope, zend_fcall_info_cache *fcc, int *strict_class, char **error) /* {{{ */ { int ret = 0; zend_class_entry *ce; @@ -2832,24 +2826,24 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache *strict_class = 0; if (zend_string_equals_literal(lcname, "self")) { - if (!EG(scope)) { + if (!scope) { if (error) *error = estrdup("cannot access self:: when no class scope is active"); } else { fcc->called_scope = zend_get_called_scope(EG(current_execute_data)); - fcc->calling_scope = EG(scope); + fcc->calling_scope = scope; if (!fcc->object) { fcc->object = zend_get_this_object(EG(current_execute_data)); } ret = 1; } } else if (zend_string_equals_literal(lcname, "parent")) { - if (!EG(scope)) { + if (!scope) { if (error) *error = estrdup("cannot access parent:: when no class scope is active"); - } else if (!EG(scope)->parent) { + } else if (!scope->parent) { if (error) *error = estrdup("cannot access parent:: when current class scope has no parent"); } else { fcc->called_scope = zend_get_called_scope(EG(current_execute_data)); - fcc->calling_scope = EG(scope)->parent; + fcc->calling_scope = scope->parent; if (!fcc->object) { fcc->object = zend_get_this_object(EG(current_execute_data)); } @@ -2911,9 +2905,9 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca zend_string *lmname; const char *colon; size_t clen, mlen; - zend_class_entry *last_scope; HashTable *ftable; int call_via_handler = 0; + zend_class_entry *scope; ALLOCA_FLAG(use_heap) if (error) { @@ -2974,19 +2968,18 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca /* This is a compound name. * Try to fetch class and then find static method. */ - last_scope = EG(scope); if (ce_org) { - EG(scope) = ce_org; + scope = ce_org; + } else { + scope = zend_get_executed_scope(); } cname = zend_string_init(Z_STRVAL_P(callable), clen, 0); - if (!zend_is_callable_check_class(cname, fcc, &strict_class, error)) { + if (!zend_is_callable_check_class(cname, scope, fcc, &strict_class, error)) { zend_string_release(cname); - EG(scope) = last_scope; return 0; } zend_string_release(cname); - EG(scope) = last_scope; ftable = &fcc->calling_scope->function_table; if (ce_org && !instanceof_function(ce_org, fcc->calling_scope)) { @@ -3020,14 +3013,17 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca } else if ((fcc->function_handler = zend_hash_find_ptr(ftable, lmname)) != NULL) { retval = 1; if ((fcc->function_handler->op_array.fn_flags & ZEND_ACC_CHANGED) && - !strict_class && EG(scope) && - instanceof_function(fcc->function_handler->common.scope, EG(scope))) { - zend_function *priv_fbc; - - if ((priv_fbc = zend_hash_find_ptr(&EG(scope)->function_table, lmname)) != NULL - && priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE - && priv_fbc->common.scope == EG(scope)) { - fcc->function_handler = priv_fbc; + !strict_class) { + scope = zend_get_executed_scope(); + if (scope && + instanceof_function(fcc->function_handler->common.scope, scope)) { + zend_function *priv_fbc; + + if ((priv_fbc = zend_hash_find_ptr(&scope->function_table, lmname)) != NULL + && priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE + && priv_fbc->common.scope == scope) { + fcc->function_handler = priv_fbc; + } } } if ((check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0 && @@ -3035,13 +3031,15 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca ((fcc->object && fcc->calling_scope->__call) || (!fcc->object && fcc->calling_scope->__callstatic)))) { if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) { - if (!zend_check_private(fcc->function_handler, fcc->object ? fcc->object->ce : EG(scope), lmname)) { + scope = zend_get_executed_scope(); + if (!zend_check_private(fcc->function_handler, fcc->object ? fcc->object->ce : scope, lmname)) { retval = 0; fcc->function_handler = NULL; goto get_function_via_handler; } } else if (fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED) { - if (!zend_check_protected(fcc->function_handler->common.scope, EG(scope))) { + scope = zend_get_executed_scope(); + if (!zend_check_protected(fcc->function_handler->common.scope, scope)) { retval = 0; fcc->function_handler = NULL; goto get_function_via_handler; @@ -3132,7 +3130,8 @@ get_function_via_handler: } if (retval && (check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0) { if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) { - if (!zend_check_private(fcc->function_handler, fcc->object ? fcc->object->ce : EG(scope), lmname)) { + scope = zend_get_executed_scope(); + if (!zend_check_private(fcc->function_handler, fcc->object ? fcc->object->ce : scope, lmname)) { if (error) { if (*error) { efree(*error); @@ -3142,7 +3141,8 @@ get_function_via_handler: retval = 0; } } else if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED)) { - if (!zend_check_protected(fcc->function_handler->common.scope, EG(scope))) { + scope = zend_get_executed_scope(); + if (!zend_check_protected(fcc->function_handler->common.scope, scope)) { if (error) { if (*error) { efree(*error); @@ -3279,7 +3279,7 @@ again: return 1; } - if (!zend_is_callable_check_class(Z_STR_P(obj), fcc, &strict_class, error)) { + if (!zend_is_callable_check_class(Z_STR_P(obj), zend_get_executed_scope(), fcc, &strict_class, error)) { return 0; } @@ -3838,9 +3838,9 @@ ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char ZEND_API void zend_update_property_ex(zend_class_entry *scope, zval *object, zend_string *name, zval *value) /* {{{ */ { zval property; - zend_class_entry *old_scope = EG(scope); + zend_class_entry *old_scope = EG(fake_scope); - EG(scope) = scope; + EG(fake_scope) = scope; if (!Z_OBJ_HT_P(object)->write_property) { zend_error_noreturn(E_CORE_ERROR, "Property %s of class %s cannot be updated", name, ZSTR_VAL(Z_OBJCE_P(object)->name)); @@ -3848,16 +3848,16 @@ ZEND_API void zend_update_property_ex(zend_class_entry *scope, zval *object, zen ZVAL_STR(&property, name); Z_OBJ_HT_P(object)->write_property(object, &property, value, NULL); - EG(scope) = old_scope; + EG(fake_scope) = old_scope; } /* }}} */ ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zval *value) /* {{{ */ { zval property; - zend_class_entry *old_scope = EG(scope); + zend_class_entry *old_scope = EG(fake_scope); - EG(scope) = scope; + EG(fake_scope) = scope; if (!Z_OBJ_HT_P(object)->write_property) { zend_error_noreturn(E_CORE_ERROR, "Property %s of class %s cannot be updated", name, ZSTR_VAL(Z_OBJCE_P(object)->name)); @@ -3866,7 +3866,7 @@ ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const Z_OBJ_HT_P(object)->write_property(object, &property, value, NULL); zval_ptr_dtor(&property); - EG(scope) = old_scope; + EG(fake_scope) = old_scope; } /* }}} */ @@ -3938,12 +3938,12 @@ ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *name, size_t name_length, zval *value) /* {{{ */ { zval *property; - zend_class_entry *old_scope = EG(scope); + zend_class_entry *old_scope = EG(fake_scope); zend_string *key = zend_string_init(name, name_length, 0); - EG(scope) = scope; + EG(fake_scope) = scope; property = zend_std_get_static_property(scope, key, 0); - EG(scope) = old_scope; + EG(fake_scope) = old_scope; zend_string_free(key); if (!property) { return FAILURE; @@ -4033,9 +4033,9 @@ ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, const ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_bool silent, zval *rv) /* {{{ */ { zval property, *value; - zend_class_entry *old_scope = EG(scope); + zend_class_entry *old_scope = EG(fake_scope); - EG(scope) = scope; + EG(fake_scope) = scope; if (!Z_OBJ_HT_P(object)->read_property) { zend_error_noreturn(E_CORE_ERROR, "Property %s of class %s cannot be read", name, ZSTR_VAL(Z_OBJCE_P(object)->name)); @@ -4045,7 +4045,7 @@ ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const c value = Z_OBJ_HT_P(object)->read_property(object, &property, silent?BP_VAR_IS:BP_VAR_R, NULL, rv); zval_ptr_dtor(&property); - EG(scope) = old_scope; + EG(fake_scope) = old_scope; return value; } /* }}} */ @@ -4053,12 +4053,12 @@ ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const c ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *name, size_t name_length, zend_bool silent) /* {{{ */ { zval *property; - zend_class_entry *old_scope = EG(scope); + zend_class_entry *old_scope = EG(fake_scope); zend_string *key = zend_string_init(name, name_length, 0); - EG(scope) = scope; + EG(fake_scope) = scope; property = zend_std_get_static_property(scope, key, silent); - EG(scope) = old_scope; + EG(fake_scope) = old_scope; zend_string_free(key); return property; diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 3772887092..eee4a44e86 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -256,23 +256,23 @@ ZEND_API int zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *sc case ZEND_AST_ZVAL: { zval *zv = zend_ast_get_zval(ast); - if (scope) { - /* class constants may be updated in-place */ - if (Z_OPT_CONSTANT_P(zv)) { - if (UNEXPECTED(zval_update_constant_ex(zv, 1, scope) != SUCCESS)) { + + if (Z_OPT_CONSTANT_P(zv)) { + if (!(Z_TYPE_FLAGS_P(zv) & IS_TYPE_IMMUTABLE)) { + if (UNEXPECTED(zval_update_constant_ex(zv, scope) != SUCCESS)) { ret = FAILURE; break; } - } - ZVAL_DUP(result, zv); - } else { - ZVAL_DUP(result, zv); - if (Z_OPT_CONSTANT_P(result)) { - if (UNEXPECTED(zval_update_constant_ex(result, 1, scope) != SUCCESS)) { + ZVAL_COPY(result, zv); + } else { + ZVAL_COPY_VALUE(result, zv); + if (UNEXPECTED(zval_update_constant_ex(result, scope) != SUCCESS)) { ret = FAILURE; break; } } + } else { + ZVAL_COPY(result, zv); } break; } diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 0cbafc7818..4492766117 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -982,7 +982,7 @@ ZEND_FUNCTION(defined) ZEND_PARSE_PARAMETERS_END(); #endif - if (zend_get_constant_ex(name, NULL, ZEND_FETCH_CLASS_SILENT)) { + if (zend_get_constant_ex(name, zend_get_executed_scope(), ZEND_FETCH_CLASS_SILENT)) { RETURN_TRUE; } else { RETURN_FALSE; @@ -1001,8 +1001,10 @@ ZEND_FUNCTION(get_class) } if (!obj) { - if (EG(scope)) { - RETURN_STR_COPY(EG(scope)->name); + zend_class_entry *scope = zend_get_executed_scope(); + + if (scope) { + RETURN_STR_COPY(scope->name); } else { zend_error(E_WARNING, "get_class() called without object from outside a class"); RETURN_FALSE; @@ -1026,8 +1028,11 @@ ZEND_FUNCTION(get_called_class) called_scope = zend_get_called_scope(execute_data); if (called_scope) { RETURN_STR_COPY(called_scope->name); - } else if (!EG(scope)) { - zend_error(E_WARNING, "get_called_class() called from outside a class"); + } else { + zend_class_entry *scope = zend_get_executed_scope(); + if (!scope) { + zend_error(E_WARNING, "get_called_class() called from outside a class"); + } } RETURN_FALSE; } @@ -1045,7 +1050,7 @@ ZEND_FUNCTION(get_parent_class) } if (!ZEND_NUM_ARGS()) { - ce = EG(scope); + ce = zend_get_executed_scope(); if (ce && ce->parent) { RETURN_STR_COPY(ce->parent->name); } else { @@ -1142,7 +1147,7 @@ ZEND_FUNCTION(is_a) /* }}} */ /* {{{ add_class_vars */ -static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value) +static void add_class_vars(zend_class_entry *scope, zend_class_entry *ce, int statics, zval *return_value) { zend_property_info *prop_info; zval *prop, prop_copy; @@ -1150,12 +1155,12 @@ static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) { if (((prop_info->flags & ZEND_ACC_SHADOW) && - prop_info->ce != EG(scope)) || + prop_info->ce != scope) || ((prop_info->flags & ZEND_ACC_PROTECTED) && - !zend_check_protected(prop_info->ce, EG(scope))) || + !zend_check_protected(prop_info->ce, scope)) || ((prop_info->flags & ZEND_ACC_PRIVATE) && - ce != EG(scope) && - prop_info->ce != EG(scope))) { + ce != scope && + prop_info->ce != scope)) { continue; } prop = NULL; @@ -1180,7 +1185,7 @@ static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value /* this is necessary to make it able to work with default array * properties, returned to user */ if (Z_OPT_CONSTANT_P(prop)) { - if (UNEXPECTED(zval_update_constant_ex(prop, 0, NULL) != SUCCESS)) { + if (UNEXPECTED(zval_update_constant_ex(prop, NULL) != SUCCESS)) { return; } } @@ -1195,7 +1200,7 @@ static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value ZEND_FUNCTION(get_class_vars) { zend_string *class_name; - zend_class_entry *ce; + zend_class_entry *ce, *scope; if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &class_name) == FAILURE) { return; @@ -1211,8 +1216,9 @@ ZEND_FUNCTION(get_class_vars) return; } } - add_class_vars(ce, 0, return_value); - add_class_vars(ce, 1, return_value); + scope = zend_get_executed_scope(); + add_class_vars(scope, ce, 0, return_value); + add_class_vars(scope, ce, 1, return_value); } } /* }}} */ @@ -1310,6 +1316,7 @@ ZEND_FUNCTION(get_class_methods) zval *klass; zval method_name; zend_class_entry *ce = NULL; + zend_class_entry *scope; zend_function *mptr; zend_string *key; @@ -1328,15 +1335,16 @@ ZEND_FUNCTION(get_class_methods) } array_init(return_value); + scope = zend_get_executed_scope(); ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->function_table, key, mptr) { if ((mptr->common.fn_flags & ZEND_ACC_PUBLIC) - || (EG(scope) && + || (scope && (((mptr->common.fn_flags & ZEND_ACC_PROTECTED) && - zend_check_protected(mptr->common.scope, EG(scope))) + zend_check_protected(mptr->common.scope, scope)) || ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) && - EG(scope) == mptr->common.scope)))) { + scope == mptr->common.scope)))) { size_t len = ZSTR_LEN(mptr->common.function_name); /* Do not display old-style inherited constructors */ diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c index 0249d35626..22162d8976 100644 --- a/Zend/zend_constants.c +++ b/Zend/zend_constants.c @@ -334,13 +334,6 @@ ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, class_name = zend_string_init(name, class_name_len, 0); lcname = do_alloca(class_name_len + 1, use_heap); zend_str_tolower_copy(lcname, name, class_name_len); - if (!scope) { - if (EG(current_execute_data)) { - scope = EG(scope); - } else { - scope = CG(active_class_entry); - } - } if (class_name_len == sizeof("self")-1 && !memcmp(lcname, "self", sizeof("self")-1)) { @@ -391,13 +384,26 @@ ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, ret_constant = &c->value; } } - zend_string_release(class_name); - zend_string_free(constant_name); if (ret_constant && Z_CONSTANT_P(ret_constant)) { - if (UNEXPECTED(zval_update_constant_ex(ret_constant, 1, ce) != SUCCESS)) { + if (Z_TYPE_P(ret_constant) == IS_CONSTANT_AST) { + if (IS_CONSTANT_VISITED(ret_constant)) { + zend_throw_error(NULL, "Cannot declare self-referencing constant '%s::%s'", ZSTR_VAL(class_name), ZSTR_VAL(constant_name)); + zend_string_release(class_name); + zend_string_free(constant_name); + return NULL; + } + MARK_CONSTANT_VISITED(ret_constant); + } + if (UNEXPECTED(zval_update_constant_ex(ret_constant, ce) != SUCCESS)) { + RESET_CONSTANT_VISITED(ret_constant); + zend_string_release(class_name); + zend_string_free(constant_name); return NULL; } + RESET_CONSTANT_VISITED(ret_constant); } + zend_string_release(class_name); + zend_string_free(constant_name); return ret_constant; } diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 68fc5e7f5d..95aea65ac8 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -645,19 +645,19 @@ static ZEND_COLD void zend_verify_arg_error(const zend_function *zf, uint32_t ar } } -static int is_null_constant(zval *default_value) +static int is_null_constant(zend_class_entry *scope, zval *default_value) { if (Z_CONSTANT_P(default_value)) { zval constant; - ZVAL_COPY_VALUE(&constant, default_value); - if (UNEXPECTED(zval_update_constant_ex(&constant, 0, NULL) != SUCCESS)) { + ZVAL_COPY(&constant, default_value); + if (UNEXPECTED(zval_update_constant_ex(&constant, scope) != SUCCESS)) { return 0; } if (Z_TYPE(constant) == IS_NULL) { return 1; } - zval_dtor(&constant); + zval_ptr_dtor(&constant); } return 0; } @@ -822,7 +822,7 @@ static zend_always_inline int zend_verify_arg_type(zend_function *zf, uint32_t a return 0; } } - } else if (Z_TYPE_P(arg) != IS_NULL || !(cur_arg_info->allow_null || (default_value && is_null_constant(default_value)))) { + } else if (Z_TYPE_P(arg) != IS_NULL || !(cur_arg_info->allow_null || (default_value && is_null_constant(zf->common.scope, default_value)))) { if (cur_arg_info->class_name) { if (EXPECTED(*cache_slot)) { ce = (zend_class_entry*)*cache_slot; @@ -2979,7 +2979,6 @@ static zend_never_inline int zend_do_fcall_overloaded(zend_function *fbc, zend_e } object = Z_OBJ(call->This); - EG(scope) = fbc->common.scope; ZVAL_NULL(ret); diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 05f0e9a956..011a4f126a 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -122,8 +122,8 @@ static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval return variable_ptr; } -ZEND_API int zval_update_constant(zval *pp, zend_bool inline_change); -ZEND_API int zval_update_constant_ex(zval *pp, zend_bool inline_change, zend_class_entry *scope); +ZEND_API int zval_update_constant(zval *pp); +ZEND_API int zval_update_constant_ex(zval *pp, zend_class_entry *scope); /* dedicated Zend executor functions - do not use! */ struct _zend_vm_stack { @@ -284,6 +284,7 @@ ZEND_API const char *get_active_function_name(void); ZEND_API const char *zend_get_executed_filename(void); ZEND_API zend_string *zend_get_executed_filename_ex(void); ZEND_API uint zend_get_executed_lineno(void); +ZEND_API zend_class_entry *zend_get_executed_scope(void); ZEND_API zend_bool zend_is_executing(void); ZEND_API void zend_set_timeout(zend_long seconds, int reset_signals); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 63d20e1fe2..023b341f21 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -177,7 +177,7 @@ void init_executor(void) /* {{{ */ EG(exception) = NULL; EG(prev_exception) = NULL; - EG(scope) = NULL; + EG(fake_scope) = NULL; EG(ht_iterators_count) = sizeof(EG(ht_iterators_slots)) / sizeof(HashTableIterator); EG(ht_iterators_used) = 0; @@ -523,6 +523,21 @@ ZEND_API uint zend_get_executed_lineno(void) /* {{{ */ } /* }}} */ +ZEND_API zend_class_entry *zend_get_executed_scope(void) /* {{{ */ +{ + zend_execute_data *ex = EG(current_execute_data); + + while (1) { + if (!ex) { + return NULL; + } else if (ex->func && (ZEND_USER_CODE(ex->func->type) || ex->func->common.scope)) { + return ex->func->common.scope; + } + ex = ex->prev_execute_data; + } +} +/* }}} */ + ZEND_API zend_bool zend_is_executing(void) /* {{{ */ { return EG(current_execute_data) != 0; @@ -546,21 +561,18 @@ ZEND_API void _zval_internal_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC) /* {{{ * } /* }}} */ -#define IS_VISITED_CONSTANT 0x80 -#define IS_CONSTANT_VISITED(p) (Z_TYPE_P(p) & IS_VISITED_CONSTANT) -#define MARK_CONSTANT_VISITED(p) Z_TYPE_INFO_P(p) |= IS_VISITED_CONSTANT -#define RESET_CONSTANT_VISITED(p) Z_TYPE_INFO_P(p) &= ~IS_VISITED_CONSTANT - -ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_class_entry *scope) /* {{{ */ +ZEND_API int zval_update_constant_ex(zval *p, zend_class_entry *scope) /* {{{ */ { zval *const_value; char *colon; + zend_bool inline_change; - if (IS_CONSTANT_VISITED(p)) { - zend_throw_error(NULL, "Cannot declare self-referencing constant '%s'", Z_STRVAL_P(p)); - return FAILURE; - } else if (Z_TYPE_P(p) == IS_CONSTANT) { - + if (Z_TYPE_P(p) == IS_CONSTANT) { + if (IS_CONSTANT_VISITED(p)) { + zend_throw_error(NULL, "Cannot declare self-referencing constant '%s'", Z_STRVAL_P(p)); + return FAILURE; + } + inline_change = (Z_TYPE_FLAGS_P(p) & IS_TYPE_IMMUTABLE) == 0; SEPARATE_ZVAL_NOREF(p); MARK_CONSTANT_VISITED(p); if (Z_CONST_FLAGS_P(p) & IS_CONSTANT_CLASS) { @@ -568,8 +580,8 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas if (inline_change) { zend_string_release(Z_STR_P(p)); } - if (EG(scope) && EG(scope)->name) { - ZVAL_STR_COPY(p, EG(scope)->name); + if (scope && scope->name) { + ZVAL_STR_COPY(p, scope->name); } else { ZVAL_EMPTY_STRING(p); } @@ -635,7 +647,7 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas } ZVAL_COPY_VALUE(p, const_value); if (Z_OPT_CONSTANT_P(p)) { - if (UNEXPECTED(zval_update_constant_ex(p, 1, NULL) != SUCCESS)) { + if (UNEXPECTED(zval_update_constant_ex(p, scope) != SUCCESS)) { RESET_CONSTANT_VISITED(p); return FAILURE; } @@ -645,6 +657,7 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas } else if (Z_TYPE_P(p) == IS_CONSTANT_AST) { zval tmp; + inline_change = (Z_TYPE_FLAGS_P(p) & IS_TYPE_IMMUTABLE) == 0; if (UNEXPECTED(zend_ast_evaluate(&tmp, Z_ASTVAL_P(p), scope) != SUCCESS)) { return FAILURE; } @@ -657,9 +670,9 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas } /* }}} */ -ZEND_API int zval_update_constant(zval *pp, zend_bool inline_change) /* {{{ */ +ZEND_API int zval_update_constant(zval *pp) /* {{{ */ { - return zval_update_constant_ex(pp, inline_change, NULL); + return zval_update_constant_ex(pp, EG(current_execute_data) ? zend_get_executed_scope() : CG(active_class_entry)); } /* }}} */ @@ -682,11 +695,9 @@ int _call_user_function_ex(zval *object, zval *function_name, zval *retval_ptr, int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /* {{{ */ { uint32_t i; - zend_class_entry *calling_scope = NULL; zend_execute_data *call, dummy_execute_data; zend_fcall_info_cache fci_cache_local; zend_function *func; - zend_class_entry *orig_scope; ZVAL_UNDEF(fci->retval); @@ -706,8 +717,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / break; } - orig_scope = EG(scope); - /* Initialize execute_data */ if (!EG(current_execute_data)) { /* This only happens when we're called outside any execute()'s @@ -763,7 +772,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / } func = fci_cache->function_handler; - calling_scope = fci_cache->calling_scope; fci->object = (func->common.fn_flags & ZEND_ACC_STATIC) ? NULL : fci_cache->object; @@ -837,8 +845,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / ZVAL_COPY_VALUE(param, arg); } - EG(scope) = calling_scope; - if (UNEXPECTED(func->op_array.fn_flags & ZEND_ACC_CLOSURE)) { ZEND_ASSERT(GC_TYPE((zend_object*)func->op_array.prototype) == IS_OBJECT); GC_REFCOUNT((zend_object*)func->op_array.prototype)++; @@ -847,7 +853,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / if (func->type == ZEND_USER_FUNCTION) { int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0; - EG(scope) = func->common.scope; call->symbol_table = NULL; if (EXPECTED((func->op_array.fn_flags & ZEND_ACC_GENERATOR) == 0)) { zend_init_execute_data(call, &func->op_array, fci->retval); @@ -862,9 +867,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / } else if (func->type == ZEND_INTERNAL_FUNCTION) { int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0; ZVAL_NULL(fci->retval); - if (func->common.scope) { - EG(scope) = func->common.scope; - } call->prev_execute_data = EG(current_execute_data); call->return_value = NULL; /* this is not a constructor call */ EG(current_execute_data) = call; @@ -918,7 +920,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / } } - EG(scope) = orig_scope; zend_vm_stack_free_call_frame(call); if (EG(current_execute_data) == &dummy_execute_data) { @@ -1379,25 +1380,27 @@ void zend_unset_timeout(void) /* {{{ */ zend_class_entry *zend_fetch_class(zend_string *class_name, int fetch_type) /* {{{ */ { - zend_class_entry *ce; + zend_class_entry *ce, *scope; int fetch_sub_type = fetch_type & ZEND_FETCH_CLASS_MASK; check_fetch_type: switch (fetch_sub_type) { case ZEND_FETCH_CLASS_SELF: - if (UNEXPECTED(!EG(scope))) { + scope = zend_get_executed_scope(); + if (UNEXPECTED(!scope)) { zend_throw_or_error(fetch_type, NULL, "Cannot access self:: when no class scope is active"); } - return EG(scope); + return scope; case ZEND_FETCH_CLASS_PARENT: - if (UNEXPECTED(!EG(scope))) { + scope = zend_get_executed_scope(); + if (UNEXPECTED(!scope)) { zend_throw_or_error(fetch_type, NULL, "Cannot access parent:: when no class scope is active"); return NULL; } - if (UNEXPECTED(!EG(scope)->parent)) { + if (UNEXPECTED(!scope->parent)) { zend_throw_or_error(fetch_type, NULL, "Cannot access parent:: when current class scope has no parent"); } - return EG(scope)->parent; + return scope->parent; case ZEND_FETCH_CLASS_STATIC: ce = zend_get_called_scope(EG(current_execute_data)); if (UNEXPECTED(!ce)) { diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 33f187c96f..5524a165fa 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -321,7 +321,7 @@ static zend_object *zend_generator_create(zend_class_entry *class_type) /* {{{ * } /* }}} */ -/* Requires globals EG(scope), EG(This) and EG(current_execute_data). */ +/* Requires globals EG(current_execute_data). */ ZEND_API void zend_generator_create_zval(zend_execute_data *call, zend_op_array *op_array, zval *return_value) /* {{{ */ { zend_generator *generator; @@ -761,13 +761,11 @@ try_again: { /* Backup executor globals */ zend_execute_data *original_execute_data = EG(current_execute_data); - zend_class_entry *original_scope = EG(scope); zend_vm_stack original_stack = EG(vm_stack); original_stack->top = EG(vm_stack_top); /* Set executor globals */ EG(current_execute_data) = generator->execute_data; - EG(scope) = generator->execute_data->func->common.scope; EG(vm_stack_top) = generator->stack->top; EG(vm_stack_end) = generator->stack->end; EG(vm_stack) = generator->stack; @@ -797,7 +795,6 @@ try_again: /* Restore executor globals */ EG(current_execute_data) = original_execute_data; - EG(scope) = original_scope; EG(vm_stack_top) = original_stack->top; EG(vm_stack_end) = original_stack->end; EG(vm_stack) = original_stack; diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 6c1280117a..14f47554d1 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -161,7 +161,7 @@ struct _zend_executor_globals { zend_vm_stack vm_stack; struct _zend_execute_data *current_execute_data; - zend_class_entry *scope; + zend_class_entry *fake_scope; /* used to avoid checks accessing properties */ zend_long precision; diff --git a/Zend/zend_ini_parser.y b/Zend/zend_ini_parser.y index ae04d2b70c..315455bf88 100644 --- a/Zend/zend_ini_parser.y +++ b/Zend/zend_ini_parser.y @@ -134,7 +134,7 @@ static void zend_ini_get_constant(zval *result, zval *name) if (Z_TYPE_P(c) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, c); if (Z_OPT_CONSTANT(tmp)) { - zval_update_constant_ex(&tmp, 1, NULL); + zval_update_constant_ex(&tmp, NULL); } zval_opt_copy_ctor(&tmp); convert_to_string(&tmp); diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index d0c5106342..ca6ec6ac7e 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -271,12 +271,24 @@ static void zend_std_call_issetter(zval *object, zval *member, zval *retval) /* static zend_always_inline int zend_verify_property_access(zend_property_info *property_info, zend_class_entry *ce) /* {{{ */ { + zend_class_entry *scope; + if (property_info->flags & ZEND_ACC_PUBLIC) { return 1; } else if (property_info->flags & ZEND_ACC_PRIVATE) { - return (ce == EG(scope) || property_info->ce == EG(scope)); + if (EG(fake_scope)) { + scope = EG(fake_scope); + } else { + scope = zend_get_executed_scope(); + } + return (ce == scope || property_info->ce == scope); } else if (property_info->flags & ZEND_ACC_PROTECTED) { - return zend_check_protected(property_info->ce, EG(scope)); + if (EG(fake_scope)) { + scope = EG(fake_scope); + } else { + scope = zend_get_executed_scope(); + } + return zend_check_protected(property_info->ce, scope); } return 0; } @@ -301,6 +313,7 @@ static zend_always_inline uint32_t zend_get_property_offset(zend_class_entry *ce zval *zv; zend_property_info *property_info = NULL; uint32_t flags; + zend_class_entry *scope; if (cache_slot && EXPECTED(ce == CACHED_PTR_EX(cache_slot))) { return (uint32_t)(intptr_t)CACHED_PTR_EX(cache_slot + 1); @@ -347,10 +360,16 @@ static zend_always_inline uint32_t zend_get_property_offset(zend_class_entry *ce } } - if (EG(scope) != ce - && EG(scope) - && is_derived_class(ce, EG(scope)) - && (zv = zend_hash_find(&EG(scope)->properties_info, member)) != NULL + if (EG(fake_scope)) { + scope = EG(fake_scope); + } else { + scope = zend_get_executed_scope(); + } + + if (scope != ce + && scope + && is_derived_class(ce, scope) + && (zv = zend_hash_find(&scope->properties_info, member)) != NULL && ((zend_property_info*)Z_PTR_P(zv))->flags & ZEND_ACC_PRIVATE) { property_info = (zend_property_info*)Z_PTR_P(zv); if (UNEXPECTED((property_info->flags & ZEND_ACC_STATIC) != 0)) { @@ -383,6 +402,7 @@ ZEND_API zend_property_info *zend_get_property_info(zend_class_entry *ce, zend_s zval *zv; zend_property_info *property_info = NULL; uint32_t flags; + zend_class_entry *scope; if (UNEXPECTED(ZSTR_VAL(member)[0] == '\0')) { if (!silent) { @@ -424,10 +444,16 @@ ZEND_API zend_property_info *zend_get_property_info(zend_class_entry *ce, zend_s } } - if (EG(scope) != ce - && EG(scope) - && is_derived_class(ce, EG(scope)) - && (zv = zend_hash_find(&EG(scope)->properties_info, member)) != NULL + if (EG(fake_scope)) { + scope = EG(fake_scope); + } else { + scope = zend_get_executed_scope(); + } + + if (scope != ce + && scope + && is_derived_class(ce, scope) + && (zv = zend_hash_find(&scope->properties_info, member)) != NULL && ((zend_property_info*)Z_PTR_P(zv))->flags & ZEND_ACC_PRIVATE) { property_info = (zend_property_info*)Z_PTR_P(zv); } else if (UNEXPECTED(property_info == NULL)) { @@ -1022,6 +1048,7 @@ static void zend_std_unset_dimension(zval *object, zval *offset) /* {{{ */ static inline zend_function *zend_check_private_int(zend_function *fbc, zend_class_entry *ce, zend_string *function_name) /* {{{ */ { zval *func; + zend_class_entry *scope; if (!ce) { return 0; @@ -1033,7 +1060,8 @@ static inline zend_function *zend_check_private_int(zend_function *fbc, zend_cla * 2. One of our parent classes are the same as the scope, and it contains * a private function with the same name that has the same scope. */ - if (fbc->common.scope == ce && EG(scope) == ce) { + scope = zend_get_executed_scope(); + if (fbc->common.scope == ce && scope == ce) { /* rule #1 checks out ok, allow the function call */ return fbc; } @@ -1042,11 +1070,11 @@ static inline zend_function *zend_check_private_int(zend_function *fbc, zend_cla /* Check rule #2 */ ce = ce->parent; while (ce) { - if (ce == EG(scope)) { + if (ce == scope) { if ((func = zend_hash_find(&ce->function_table, function_name))) { fbc = Z_FUNC_P(func); if (fbc->common.fn_flags & ZEND_ACC_PRIVATE - && fbc->common.scope == EG(scope)) { + && fbc->common.scope == scope) { return fbc; } } @@ -1149,6 +1177,7 @@ static union _zend_function *zend_std_get_method(zend_object **obj_ptr, zend_str zval *func; zend_function *fbc; zend_string *lc_method_name; + zend_class_entry *scope = NULL; ALLOCA_FLAG(use_heap); if (EXPECTED(key != NULL)) { @@ -1187,7 +1216,8 @@ static union _zend_function *zend_std_get_method(zend_object **obj_ptr, zend_str if (zobj->ce->__call) { fbc = zend_get_user_call_function(zobj->ce, method_name); } else { - zend_throw_error(NULL, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), ZSTR_VAL(method_name), EG(scope) ? ZSTR_VAL(EG(scope)->name) : ""); + scope = zend_get_executed_scope(); + zend_throw_error(NULL, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), ZSTR_VAL(method_name), scope ? ZSTR_VAL(scope->name) : ""); fbc = NULL; } } @@ -1195,26 +1225,29 @@ static union _zend_function *zend_std_get_method(zend_object **obj_ptr, zend_str /* Ensure that we haven't overridden a private function and end up calling * the overriding public function... */ - if (EG(scope) && - is_derived_class(fbc->common.scope, EG(scope)) && - fbc->op_array.fn_flags & ZEND_ACC_CHANGED) { - if ((func = zend_hash_find(&EG(scope)->function_table, lc_method_name)) != NULL) { - zend_function *priv_fbc = Z_FUNC_P(func); - if (priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE - && priv_fbc->common.scope == EG(scope)) { - fbc = priv_fbc; + if (fbc->op_array.fn_flags & (ZEND_ACC_CHANGED|ZEND_ACC_PROTECTED)) { + scope = zend_get_executed_scope(); + } + if (fbc->op_array.fn_flags & ZEND_ACC_CHANGED) { + if (scope && is_derived_class(fbc->common.scope, scope)) { + if ((func = zend_hash_find(&scope->function_table, lc_method_name)) != NULL) { + zend_function *priv_fbc = Z_FUNC_P(func); + if (priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE + && priv_fbc->common.scope == scope) { + fbc = priv_fbc; + } } } } - if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) { + if (fbc->common.fn_flags & ZEND_ACC_PROTECTED) { /* Ensure that if we're calling a protected function, we're allowed to do so. * If we're not and __call() handler exists, invoke it, otherwise error out. */ - if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fbc), EG(scope)))) { + if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fbc), scope))) { if (zobj->ce->__call) { fbc = zend_get_user_call_function(zobj->ce, method_name); } else { - zend_throw_error(NULL, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), ZSTR_VAL(method_name), EG(scope) ? ZSTR_VAL(EG(scope)->name) : ""); + zend_throw_error(NULL, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), ZSTR_VAL(method_name), scope ? ZSTR_VAL(scope->name) : ""); fbc = NULL; } } @@ -1240,6 +1273,7 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st char *lc_class_name; zend_string *lc_function_name; zend_object *object; + zend_class_entry *scope; if (EXPECTED(key != NULL)) { lc_function_name = Z_STR_P(key); @@ -1300,25 +1334,27 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st /* Ensure that if we're calling a private function, we're allowed to do so. */ - updated_fbc = zend_check_private_int(fbc, EG(scope), lc_function_name); + scope = zend_get_executed_scope(); + updated_fbc = zend_check_private_int(fbc, scope, lc_function_name); if (EXPECTED(updated_fbc != NULL)) { fbc = updated_fbc; } else { if (ce->__callstatic) { fbc = zend_get_user_callstatic_function(ce, function_name); } else { - zend_throw_error(NULL, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), ZSTR_VAL(function_name), EG(scope) ? ZSTR_VAL(EG(scope)->name) : ""); + zend_throw_error(NULL, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), ZSTR_VAL(function_name), scope ? ZSTR_VAL(scope->name) : ""); fbc = NULL; } } } else if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. */ - if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fbc), EG(scope)))) { + scope = zend_get_executed_scope(); + if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fbc), scope))) { if (ce->__callstatic) { fbc = zend_get_user_callstatic_function(ce, function_name); } else { - zend_throw_error(NULL, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), ZSTR_VAL(function_name), EG(scope) ? ZSTR_VAL(EG(scope)->name) : ""); + zend_throw_error(NULL, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), ZSTR_VAL(function_name), scope ? ZSTR_VAL(scope->name) : ""); fbc = NULL; } } @@ -1382,6 +1418,7 @@ ZEND_API ZEND_COLD zend_bool zend_std_unset_static_property(zend_class_entry *ce ZEND_API union _zend_function *zend_std_get_constructor(zend_object *zobj) /* {{{ */ { zend_function *constructor = zobj->ce->constructor; + zend_class_entry *scope; if (constructor) { if (constructor->op_array.fn_flags & ZEND_ACC_PUBLIC) { @@ -1389,9 +1426,14 @@ ZEND_API union _zend_function *zend_std_get_constructor(zend_object *zobj) /* {{ } else if (constructor->op_array.fn_flags & ZEND_ACC_PRIVATE) { /* Ensure that if we're calling a private function, we're allowed to do so. */ - if (UNEXPECTED(constructor->common.scope != EG(scope))) { - if (EG(scope)) { - zend_throw_error(NULL, "Call to private %s::%s() from context '%s'", ZSTR_VAL(constructor->common.scope->name), ZSTR_VAL(constructor->common.function_name), ZSTR_VAL(EG(scope)->name)); + if (EG(fake_scope)) { + scope = EG(fake_scope); + } else { + scope = zend_get_executed_scope(); + } + if (UNEXPECTED(constructor->common.scope != scope)) { + if (scope) { + zend_throw_error(NULL, "Call to private %s::%s() from context '%s'", ZSTR_VAL(constructor->common.scope->name), ZSTR_VAL(constructor->common.function_name), ZSTR_VAL(scope->name)); constructor = NULL; } else { zend_throw_error(NULL, "Call to private %s::%s() from invalid context", ZSTR_VAL(constructor->common.scope->name), ZSTR_VAL(constructor->common.function_name)); @@ -1403,9 +1445,14 @@ ZEND_API union _zend_function *zend_std_get_constructor(zend_object *zobj) /* {{ * Constructors only have prototype if they are defined by an interface but * it is the compilers responsibility to take care of the prototype. */ - if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(constructor), EG(scope)))) { - if (EG(scope)) { - zend_throw_error(NULL, "Call to protected %s::%s() from context '%s'", ZSTR_VAL(constructor->common.scope->name), ZSTR_VAL(constructor->common.function_name), ZSTR_VAL(EG(scope)->name)); + if (EG(fake_scope)) { + scope = EG(fake_scope); + } else { + scope = zend_get_executed_scope(); + } + if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(constructor), scope))) { + if (scope) { + zend_throw_error(NULL, "Call to protected %s::%s() from context '%s'", ZSTR_VAL(constructor->common.scope->name), ZSTR_VAL(constructor->common.function_name), ZSTR_VAL(scope->name)); constructor = NULL; } else { zend_throw_error(NULL, "Call to protected %s::%s() from invalid context", ZSTR_VAL(constructor->common.scope->name), ZSTR_VAL(constructor->common.function_name)); diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c index 0f052335db..53d215d27e 100644 --- a/Zend/zend_objects.c +++ b/Zend/zend_objects.c @@ -96,39 +96,39 @@ ZEND_API void zend_objects_destroy_object(zend_object *object) if (destructor->op_array.fn_flags & ZEND_ACC_PRIVATE) { /* Ensure that if we're calling a private function, we're allowed to do so. */ - if (object->ce != EG(scope)) { - zend_class_entry *ce = object->ce; + if (EG(current_execute_data)) { + zend_class_entry *scope = zend_get_executed_scope(); - if (EG(current_execute_data)) { + if (object->ce != scope) { zend_throw_error(NULL, "Call to private %s::__destruct() from context '%s'", - ZSTR_VAL(ce->name), - EG(scope) ? ZSTR_VAL(EG(scope)->name) : ""); - } else { - zend_error(E_WARNING, - "Call to private %s::__destruct() from context '%s' during shutdown ignored", - ZSTR_VAL(ce->name), - EG(scope) ? ZSTR_VAL(EG(scope)->name) : ""); + ZSTR_VAL(object->ce->name), + scope ? ZSTR_VAL(scope->name) : ""); + return; } + } else { + zend_error(E_WARNING, + "Call to private %s::__destruct() from context '' during shutdown ignored", + ZSTR_VAL(object->ce->name)); return; } } else { /* Ensure that if we're calling a protected function, we're allowed to do so. */ - if (!zend_check_protected(zend_get_function_root_class(destructor), EG(scope))) { - zend_class_entry *ce = object->ce; + if (EG(current_execute_data)) { + zend_class_entry *scope = zend_get_executed_scope(); - if (EG(current_execute_data)) { + if (!zend_check_protected(zend_get_function_root_class(destructor), scope)) { zend_throw_error(NULL, "Call to protected %s::__destruct() from context '%s'", - ZSTR_VAL(ce->name), - EG(scope) ? ZSTR_VAL(EG(scope)->name) : ""); - } else { - zend_error(E_WARNING, - "Call to protected %s::__destruct() from context '%s' during shutdown ignored", - ZSTR_VAL(ce->name), - EG(scope) ? ZSTR_VAL(EG(scope)->name) : ""); + ZSTR_VAL(object->ce->name), + scope ? ZSTR_VAL(scope->name) : ""); + return; } + } else { + zend_error(E_WARNING, + "Call to protected %s::__destruct() from context '' during shutdown ignored", + ZSTR_VAL(object->ce->name)); return; } } diff --git a/Zend/zend_types.h b/Zend/zend_types.h index b775bd7e53..45c2ebdf70 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -410,9 +410,14 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) { /* zval.u1.v.const_flags */ #define IS_CONSTANT_UNQUALIFIED 0x010 +#define IS_CONSTANT_VISITED_MARK 0x020 #define IS_CONSTANT_CLASS 0x080 /* __CLASS__ in trait */ #define IS_CONSTANT_IN_NAMESPACE 0x100 /* used only in opline->extended_value */ +#define IS_CONSTANT_VISITED(p) (Z_CONST_FLAGS_P(p) & IS_CONSTANT_VISITED_MARK) +#define MARK_CONSTANT_VISITED(p) Z_CONST_FLAGS_P(p) |= IS_CONSTANT_VISITED_MARK +#define RESET_CONSTANT_VISITED(p) Z_CONST_FLAGS_P(p) &= ~IS_CONSTANT_VISITED_MARK + /* string flags (zval.value->gc.u.flags) */ #define IS_STR_PERSISTENT (1<<0) /* allocated using malloc */ #define IS_STR_INTERNED (1<<1) /* interned string */ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index e1a87bbc9e..2b29e62887 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2537,8 +2537,6 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) execute_data = EX(prev_execute_data); } - EG(scope) = EX(func)->op_array.scope; - if (UNEXPECTED(EG(exception) != NULL)) { const zend_op *old_opline = EX(opline); zend_throw_exception_internal(NULL); @@ -3591,7 +3589,6 @@ ZEND_VM_HANDLER(130, ZEND_DO_UCALL, ANY, ANY, SPEC(RETVAL)) SAVE_OPLINE(); EX(call) = call->prev_execute_data; - EG(scope) = NULL; ret = NULL; call->symbol_table = NULL; if (RETURN_VALUE_USED(opline)) { @@ -3616,7 +3613,6 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL)) EX(call) = call->prev_execute_data; if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { - EG(scope) = NULL; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) { if (EXPECTED(RETURN_VALUE_USED(opline))) { ret = EX_VAR(opline->result.var); @@ -3639,7 +3635,6 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL)) ZEND_VM_ENTER(); } - EG(scope) = EX(func)->op_array.scope; } else { zval retval; ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); @@ -3727,7 +3722,6 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) LOAD_OPLINE(); if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { - EG(scope) = fbc->common.scope; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) { if (EXPECTED(RETURN_VALUE_USED(opline))) { ret = EX_VAR(opline->result.var); @@ -3757,14 +3751,8 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) } } } else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) { - int should_change_scope = 0; zval retval; - if (fbc->common.scope) { - should_change_scope = 1; - EG(scope) = fbc->common.scope; - } - call->prev_execute_data = execute_data; EG(current_execute_data) = call; @@ -3773,11 +3761,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) if (RETURN_VALUE_USED(opline)) { ZVAL_UNDEF(EX_VAR(opline->result.var)); } - if (UNEXPECTED(should_change_scope)) { - ZEND_VM_C_GOTO(fcall_end_change_scope); - } else { - ZEND_VM_C_GOTO(fcall_end); - } + ZEND_VM_C_GOTO(fcall_end); } ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; @@ -3806,11 +3790,6 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) zval_ptr_dtor(ret); } - if (UNEXPECTED(should_change_scope)) { - ZEND_VM_C_GOTO(fcall_end_change_scope); - } else { - ZEND_VM_C_GOTO(fcall_end); - } } else { /* ZEND_OVERLOADED_FUNCTION */ zval retval; @@ -3827,7 +3806,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) } } -ZEND_VM_C_LABEL(fcall_end_change_scope): +ZEND_VM_C_LABEL(fcall_end): if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS)) { object = Z_OBJ(call->This); #if 0 @@ -3842,9 +3821,7 @@ ZEND_VM_C_LABEL(fcall_end_change_scope): } OBJ_RELEASE(object); } - EG(scope) = EX(func)->op_array.scope; -ZEND_VM_C_LABEL(fcall_end): zend_vm_stack_free_call_frame(call); if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL); @@ -4688,17 +4665,13 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, NUM, CONST) arg_num = opline->op1.num; param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var); if (arg_num > EX_NUM_ARGS()) { - ZVAL_COPY_VALUE(param, EX_CONSTANT(opline->op2)); + ZVAL_COPY(param, EX_CONSTANT(opline->op2)); if (Z_OPT_CONSTANT_P(param)) { SAVE_OPLINE(); - if (UNEXPECTED(zval_update_constant_ex(param, 0, NULL) != SUCCESS)) { + if (UNEXPECTED(zval_update_constant_ex(param, EX(func)->op_array.scope) != SUCCESS)) { ZVAL_UNDEF(param); HANDLE_EXCEPTION(); } - } else { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(param))) { - Z_ADDREF_P(param); - } } } @@ -4923,7 +4896,7 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY) USE_OPLINE zend_free_op free_op1; zval *obj; - zend_class_entry *ce; + zend_class_entry *ce, *scope; zend_function *clone; zend_object_clone_obj_t clone_call; @@ -4969,16 +4942,18 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY) if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) { /* Ensure that if we're calling a private function, we're allowed to do so. */ - if (UNEXPECTED(ce != EG(scope))) { - zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(ce->name), EG(scope) ? ZSTR_VAL(EG(scope)->name) : ""); + scope = EX(func)->op_array.scope; + if (UNEXPECTED(ce != scope)) { + zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(ce->name), scope ? ZSTR_VAL(scope->name) : ""); FREE_OP1(); HANDLE_EXCEPTION(); } } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. */ - if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) { - zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(ce->name), EG(scope) ? ZSTR_VAL(EG(scope)->name) : ""); + scope = EX(func)->op_array.scope; + if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { + zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(ce->name), scope ? ZSTR_VAL(scope->name) : ""); FREE_OP1(); HANDLE_EXCEPTION(); } @@ -5040,7 +5015,7 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, UNUSED, CONST, CONST_FETCH) ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED|CLASS_FETCH, CONST) { - zend_class_entry *ce; + zend_class_entry *ce, *scope; zend_class_constant *c; zval *value; USE_OPLINE @@ -5083,15 +5058,14 @@ ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED|CLASS_FETCH, CO } if (EXPECTED((c = zend_hash_find_ptr(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) { - if (!zend_verify_const_access(c, EG(scope))) { + scope = EX(func)->op_array.scope; + if (!zend_verify_const_access(c, scope)) { zend_throw_error(NULL, "Cannot access %s const %s::%s", zend_visibility_string(Z_ACCESS_FLAGS(c->value)), ZSTR_VAL(ce->name), Z_STRVAL_P(EX_CONSTANT(opline->op2))); HANDLE_EXCEPTION(); } value = &c->value; if (Z_CONSTANT_P(value)) { - EG(scope) = ce; - zval_update_constant_ex(value, 1, NULL); - EG(scope) = EX(func)->op_array.scope; + zval_update_constant_ex(value, ce); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -5372,7 +5346,7 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY, EVAL) return_value = EX_VAR(opline->result.var); } - new_op_array->scope = EG(scope); + new_op_array->scope = EX(func)->op_array.scope; call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE, (zend_function*)new_op_array, 0, @@ -7201,7 +7175,7 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST) ZVAL_COPY_VALUE(&c.value, val); if (Z_OPT_CONSTANT(c.value)) { - if (UNEXPECTED(zval_update_constant_ex(&c.value, 0, NULL) != SUCCESS)) { + if (UNEXPECTED(zval_update_constant_ex(&c.value, EX(func)->op_array.scope) != SUCCESS)) { FREE_OP1(); FREE_OP2(); HANDLE_EXCEPTION(); @@ -7248,7 +7222,7 @@ ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, UNUSED) object = NULL; } zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), - EG(scope), called_scope, object); + EX(func)->op_array.scope, called_scope, object); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -7781,13 +7755,14 @@ ZEND_VM_HANDLER(151, ZEND_ASSERT_CHECK, ANY, JMP_ADDR) ZEND_VM_HANDLER(157, ZEND_FETCH_CLASS_NAME, ANY, ANY, CLASS_FETCH) { uint32_t fetch_type; - zend_class_entry *called_scope; + zend_class_entry *called_scope, *scope; USE_OPLINE SAVE_OPLINE(); fetch_type = opline->extended_value; - if (UNEXPECTED(EG(scope) == NULL)) { + scope = EX(func)->op_array.scope; + if (UNEXPECTED(scope == NULL)) { zend_throw_error(NULL, "Cannot use \"%s\" when no class scope is active", fetch_type == ZEND_FETCH_CLASS_SELF ? "self" : fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static"); @@ -7796,15 +7771,15 @@ ZEND_VM_HANDLER(157, ZEND_FETCH_CLASS_NAME, ANY, ANY, CLASS_FETCH) switch (fetch_type) { case ZEND_FETCH_CLASS_SELF: - ZVAL_STR_COPY(EX_VAR(opline->result.var), EG(scope)->name); + ZVAL_STR_COPY(EX_VAR(opline->result.var), scope->name); break; case ZEND_FETCH_CLASS_PARENT: - if (UNEXPECTED(EG(scope)->parent == NULL)) { + if (UNEXPECTED(scope->parent == NULL)) { zend_throw_error(NULL, "Cannot use \"parent\" when current class scope has no parent"); HANDLE_EXCEPTION(); } - ZVAL_STR_COPY(EX_VAR(opline->result.var), EG(scope)->parent->name); + ZVAL_STR_COPY(EX_VAR(opline->result.var), scope->parent->name); break; case ZEND_FETCH_CLASS_STATIC: if (Z_TYPE(EX(This)) == IS_OBJECT) { @@ -7931,7 +7906,6 @@ ZEND_VM_C_LABEL(call_trampoline_end): zend_object *object = Z_OBJ(call->This); OBJ_RELEASE(object); } - EG(scope) = EX(func)->op_array.scope; zend_vm_stack_free_call_frame(call); if (UNEXPECTED(EG(exception) != NULL)) { @@ -8004,7 +7978,7 @@ ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, CONST, REF) if (opline->extended_value) { if (Z_CONSTANT_P(value)) { - if (UNEXPECTED(zval_update_constant_ex(value, 1, NULL) != SUCCESS)) { + if (UNEXPECTED(zval_update_constant_ex(value, EX(func)->op_array.scope) != SUCCESS)) { ZVAL_NULL(variable_ptr); HANDLE_EXCEPTION(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index bbf9213ab0..cd7965bc56 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -526,8 +526,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_ execute_data = EX(prev_execute_data); } - EG(scope) = EX(func)->op_array.scope; - if (UNEXPECTED(EG(exception) != NULL)) { const zend_op *old_opline = EX(opline); zend_throw_exception_internal(NULL); @@ -701,7 +699,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_RETVAL_UNUSED_HA SAVE_OPLINE(); EX(call) = call->prev_execute_data; - EG(scope) = NULL; ret = NULL; call->symbol_table = NULL; if (0) { @@ -725,7 +722,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_RETVAL_USED_HAND SAVE_OPLINE(); EX(call) = call->prev_execute_data; - EG(scope) = NULL; ret = NULL; call->symbol_table = NULL; if (1) { @@ -750,7 +746,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U EX(call) = call->prev_execute_data; if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { - EG(scope) = NULL; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) { if (EXPECTED(0)) { ret = EX_VAR(opline->result.var); @@ -773,7 +768,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U ZEND_VM_ENTER(); } - EG(scope) = EX(func)->op_array.scope; } else { zval retval; ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); @@ -843,7 +837,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U EX(call) = call->prev_execute_data; if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { - EG(scope) = NULL; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) { if (EXPECTED(1)) { ret = EX_VAR(opline->result.var); @@ -866,7 +859,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U ZEND_VM_ENTER(); } - EG(scope) = EX(func)->op_array.scope; } else { zval retval; ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); @@ -954,7 +946,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HA LOAD_OPLINE(); if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { - EG(scope) = fbc->common.scope; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) { if (EXPECTED(0)) { ret = EX_VAR(opline->result.var); @@ -984,14 +975,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HA } } } else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) { - int should_change_scope = 0; zval retval; - if (fbc->common.scope) { - should_change_scope = 1; - EG(scope) = fbc->common.scope; - } - call->prev_execute_data = execute_data; EG(current_execute_data) = call; @@ -1000,11 +985,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HA if (0) { ZVAL_UNDEF(EX_VAR(opline->result.var)); } - if (UNEXPECTED(should_change_scope)) { - goto fcall_end_change_scope; - } else { - goto fcall_end; - } + goto fcall_end; } ret = 0 ? EX_VAR(opline->result.var) : &retval; @@ -1033,11 +1014,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HA zval_ptr_dtor(ret); } - if (UNEXPECTED(should_change_scope)) { - goto fcall_end_change_scope; - } else { - goto fcall_end; - } } else { /* ZEND_OVERLOADED_FUNCTION */ zval retval; @@ -1054,7 +1030,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HA } } -fcall_end_change_scope: +fcall_end: if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS)) { object = Z_OBJ(call->This); #if 0 @@ -1069,9 +1045,7 @@ fcall_end_change_scope: } OBJ_RELEASE(object); } - EG(scope) = EX(func)->op_array.scope; -fcall_end: zend_vm_stack_free_call_frame(call); if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL); @@ -1114,7 +1088,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_USED_HAND LOAD_OPLINE(); if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { - EG(scope) = fbc->common.scope; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) { if (EXPECTED(1)) { ret = EX_VAR(opline->result.var); @@ -1144,14 +1117,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_USED_HAND } } } else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) { - int should_change_scope = 0; zval retval; - if (fbc->common.scope) { - should_change_scope = 1; - EG(scope) = fbc->common.scope; - } - call->prev_execute_data = execute_data; EG(current_execute_data) = call; @@ -1160,11 +1127,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_USED_HAND if (1) { ZVAL_UNDEF(EX_VAR(opline->result.var)); } - if (UNEXPECTED(should_change_scope)) { - goto fcall_end_change_scope; - } else { - goto fcall_end; - } + goto fcall_end; } ret = 1 ? EX_VAR(opline->result.var) : &retval; @@ -1193,11 +1156,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_USED_HAND zval_ptr_dtor(ret); } - if (UNEXPECTED(should_change_scope)) { - goto fcall_end_change_scope; - } else { - goto fcall_end; - } } else { /* ZEND_OVERLOADED_FUNCTION */ zval retval; @@ -1214,7 +1172,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_USED_HAND } } -fcall_end_change_scope: +fcall_end: if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS)) { object = Z_OBJ(call->This); #if 0 @@ -1229,9 +1187,7 @@ fcall_end_change_scope: } OBJ_RELEASE(object); } - EG(scope) = EX(func)->op_array.scope; -fcall_end: zend_vm_stack_free_call_frame(call); if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL); @@ -1931,13 +1887,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSERT_CHECK_SPEC_HANDLER(ZEND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_NAME_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { uint32_t fetch_type; - zend_class_entry *called_scope; + zend_class_entry *called_scope, *scope; USE_OPLINE SAVE_OPLINE(); fetch_type = opline->extended_value; - if (UNEXPECTED(EG(scope) == NULL)) { + scope = EX(func)->op_array.scope; + if (UNEXPECTED(scope == NULL)) { zend_throw_error(NULL, "Cannot use \"%s\" when no class scope is active", fetch_type == ZEND_FETCH_CLASS_SELF ? "self" : fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static"); @@ -1946,15 +1903,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_NAME_SPEC_HANDLER( switch (fetch_type) { case ZEND_FETCH_CLASS_SELF: - ZVAL_STR_COPY(EX_VAR(opline->result.var), EG(scope)->name); + ZVAL_STR_COPY(EX_VAR(opline->result.var), scope->name); break; case ZEND_FETCH_CLASS_PARENT: - if (UNEXPECTED(EG(scope)->parent == NULL)) { + if (UNEXPECTED(scope->parent == NULL)) { zend_throw_error(NULL, "Cannot use \"parent\" when current class scope has no parent"); HANDLE_EXCEPTION(); } - ZVAL_STR_COPY(EX_VAR(opline->result.var), EG(scope)->parent->name); + ZVAL_STR_COPY(EX_VAR(opline->result.var), scope->parent->name); break; case ZEND_FETCH_CLASS_STATIC: if (Z_TYPE(EX(This)) == IS_OBJECT) { @@ -2081,7 +2038,6 @@ call_trampoline_end: zend_object *object = Z_OBJ(call->This); OBJ_RELEASE(object); } - EG(scope) = EX(func)->op_array.scope; zend_vm_stack_free_call_frame(call); if (UNEXPECTED(EG(exception) != NULL)) { @@ -2289,17 +2245,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(Z arg_num = opline->op1.num; param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var); if (arg_num > EX_NUM_ARGS()) { - ZVAL_COPY_VALUE(param, EX_CONSTANT(opline->op2)); + ZVAL_COPY(param, EX_CONSTANT(opline->op2)); if (Z_OPT_CONSTANT_P(param)) { SAVE_OPLINE(); - if (UNEXPECTED(zval_update_constant_ex(param, 0, NULL) != SUCCESS)) { + if (UNEXPECTED(zval_update_constant_ex(param, EX(func)->op_array.scope) != SUCCESS)) { ZVAL_UNDEF(param); HANDLE_EXCEPTION(); } - } else { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(param))) { - Z_ADDREF_P(param); - } } } @@ -3229,7 +3181,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_ USE_OPLINE zval *obj; - zend_class_entry *ce; + zend_class_entry *ce, *scope; zend_function *clone; zend_object_clone_obj_t clone_call; @@ -3275,16 +3227,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_ if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) { /* Ensure that if we're calling a private function, we're allowed to do so. */ - if (UNEXPECTED(ce != EG(scope))) { - zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(ce->name), EG(scope) ? ZSTR_VAL(EG(scope)->name) : ""); + scope = EX(func)->op_array.scope; + if (UNEXPECTED(ce != scope)) { + zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(ce->name), scope ? ZSTR_VAL(scope->name) : ""); HANDLE_EXCEPTION(); } } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. */ - if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) { - zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(ce->name), EG(scope) ? ZSTR_VAL(EG(scope)->name) : ""); + scope = EX(func)->op_array.scope; + if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { + zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(ce->name), scope ? ZSTR_VAL(scope->name) : ""); HANDLE_EXCEPTION(); } @@ -3424,7 +3378,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HAN return_value = EX_VAR(opline->result.var); } - new_op_array->scope = EG(scope); + new_op_array->scope = EX(func)->op_array.scope; call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE, (zend_function*)new_op_array, 0, @@ -5593,7 +5547,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CONST_CONST_HANDLER( static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zend_class_entry *ce; + zend_class_entry *ce, *scope; zend_class_constant *c; zval *value; USE_OPLINE @@ -5636,15 +5590,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS } if (EXPECTED((c = zend_hash_find_ptr(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) { - if (!zend_verify_const_access(c, EG(scope))) { + scope = EX(func)->op_array.scope; + if (!zend_verify_const_access(c, scope)) { zend_throw_error(NULL, "Cannot access %s const %s::%s", zend_visibility_string(Z_ACCESS_FLAGS(c->value)), ZSTR_VAL(ce->name), Z_STRVAL_P(EX_CONSTANT(opline->op2))); HANDLE_EXCEPTION(); } value = &c->value; if (Z_CONSTANT_P(value)) { - EG(scope) = ce; - zval_update_constant_ex(value, 1, NULL); - EG(scope) = EX(func)->op_array.scope; + zval_update_constant_ex(value, ce); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -6139,7 +6092,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST ZVAL_COPY_VALUE(&c.value, val); if (Z_OPT_CONSTANT(c.value)) { - if (UNEXPECTED(zval_update_constant_ex(&c.value, 0, NULL) != SUCCESS)) { + if (UNEXPECTED(zval_update_constant_ex(&c.value, EX(func)->op_array.scope) != SUCCESS)) { HANDLE_EXCEPTION(); @@ -7832,7 +7785,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_C object = NULL; } zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), - EG(scope), called_scope, object); + EX(func)->op_array.scope, called_scope, object); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -18943,7 +18896,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zend_class_entry *ce; + zend_class_entry *ce, *scope; zend_class_constant *c; zval *value; USE_OPLINE @@ -18986,15 +18939,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ } if (EXPECTED((c = zend_hash_find_ptr(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) { - if (!zend_verify_const_access(c, EG(scope))) { + scope = EX(func)->op_array.scope; + if (!zend_verify_const_access(c, scope)) { zend_throw_error(NULL, "Cannot access %s const %s::%s", zend_visibility_string(Z_ACCESS_FLAGS(c->value)), ZSTR_VAL(ce->name), Z_STRVAL_P(EX_CONSTANT(opline->op2))); HANDLE_EXCEPTION(); } value = &c->value; if (Z_CONSTANT_P(value)) { - EG(scope) = ce; - zval_update_constant_ex(value, 1, NULL); - EG(scope) = EX(func)->op_array.scope; + zval_update_constant_ex(value, ce); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -26394,7 +26346,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND USE_OPLINE zval *obj; - zend_class_entry *ce; + zend_class_entry *ce, *scope; zend_function *clone; zend_object_clone_obj_t clone_call; @@ -26440,16 +26392,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) { /* Ensure that if we're calling a private function, we're allowed to do so. */ - if (UNEXPECTED(ce != EG(scope))) { - zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(ce->name), EG(scope) ? ZSTR_VAL(EG(scope)->name) : ""); + scope = EX(func)->op_array.scope; + if (UNEXPECTED(ce != scope)) { + zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(ce->name), scope ? ZSTR_VAL(scope->name) : ""); HANDLE_EXCEPTION(); } } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. */ - if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) { - zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(ce->name), EG(scope) ? ZSTR_VAL(EG(scope)->name) : ""); + scope = EX(func)->op_array.scope; + if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { + zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(ce->name), scope ? ZSTR_VAL(scope->name) : ""); HANDLE_EXCEPTION(); } @@ -28351,7 +28305,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CON static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - zend_class_entry *ce; + zend_class_entry *ce, *scope; zend_class_constant *c; zval *value; USE_OPLINE @@ -28394,15 +28348,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS } if (EXPECTED((c = zend_hash_find_ptr(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) { - if (!zend_verify_const_access(c, EG(scope))) { + scope = EX(func)->op_array.scope; + if (!zend_verify_const_access(c, scope)) { zend_throw_error(NULL, "Cannot access %s const %s::%s", zend_visibility_string(Z_ACCESS_FLAGS(c->value)), ZSTR_VAL(ce->name), Z_STRVAL_P(EX_CONSTANT(opline->op2))); HANDLE_EXCEPTION(); } value = &c->value; if (Z_CONSTANT_P(value)) { - EG(scope) = ce; - zval_update_constant_ex(value, 1, NULL); - EG(scope) = EX(func)->op_array.scope; + zval_update_constant_ex(value, ce); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } @@ -35301,7 +35254,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC USE_OPLINE zval *obj; - zend_class_entry *ce; + zend_class_entry *ce, *scope; zend_function *clone; zend_object_clone_obj_t clone_call; @@ -35347,16 +35300,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) { /* Ensure that if we're calling a private function, we're allowed to do so. */ - if (UNEXPECTED(ce != EG(scope))) { - zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(ce->name), EG(scope) ? ZSTR_VAL(EG(scope)->name) : ""); + scope = EX(func)->op_array.scope; + if (UNEXPECTED(ce != scope)) { + zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(ce->name), scope ? ZSTR_VAL(scope->name) : ""); HANDLE_EXCEPTION(); } } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. */ - if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) { - zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(ce->name), EG(scope) ? ZSTR_VAL(EG(scope)->name) : ""); + scope = EX(func)->op_array.scope; + if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { + zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(ce->name), scope ? ZSTR_VAL(scope->name) : ""); HANDLE_EXCEPTION(); } @@ -35496,7 +35451,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLE return_value = EX_VAR(opline->result.var); } - new_op_array->scope = EG(scope); + new_op_array->scope = EX(func)->op_array.scope; call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE, (zend_function*)new_op_array, 0, @@ -40176,7 +40131,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_STATIC_SPEC_CV_CONST_HAND if (opline->extended_value) { if (Z_CONSTANT_P(value)) { - if (UNEXPECTED(zval_update_constant_ex(value, 1, NULL) != SUCCESS)) { + if (UNEXPECTED(zval_update_constant_ex(value, EX(func)->op_array.scope) != SUCCESS)) { ZVAL_NULL(variable_ptr); HANDLE_EXCEPTION(); } @@ -50147,7 +50102,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND USE_OPLINE zend_free_op free_op1; zval *obj; - zend_class_entry *ce; + zend_class_entry *ce, *scope; zend_function *clone; zend_object_clone_obj_t clone_call; @@ -50193,16 +50148,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) { /* Ensure that if we're calling a private function, we're allowed to do so. */ - if (UNEXPECTED(ce != EG(scope))) { - zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(ce->name), EG(scope) ? ZSTR_VAL(EG(scope)->name) : ""); + scope = EX(func)->op_array.scope; + if (UNEXPECTED(ce != scope)) { + zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(ce->name), scope ? ZSTR_VAL(scope->name) : ""); zval_ptr_dtor_nogc(free_op1); HANDLE_EXCEPTION(); } } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) { /* Ensure that if we're calling a protected function, we're allowed to do so. */ - if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) { - zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(ce->name), EG(scope) ? ZSTR_VAL(EG(scope)->name) : ""); + scope = EX(func)->op_array.scope; + if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) { + zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(ce->name), scope ? ZSTR_VAL(scope->name) : ""); zval_ptr_dtor_nogc(free_op1); HANDLE_EXCEPTION(); } @@ -50243,7 +50200,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HA return_value = EX_VAR(opline->result.var); } - new_op_array->scope = EG(scope); + new_op_array->scope = EX(func)->op_array.scope; call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE, (zend_function*)new_op_array, 0, diff --git a/ext/intl/transliterator/transliterator_class.c b/ext/intl/transliterator/transliterator_class.c index ce8c7e6291..5c80b25af8 100644 --- a/ext/intl/transliterator/transliterator_class.c +++ b/ext/intl/transliterator/transliterator_class.c @@ -269,9 +269,15 @@ static zval *Transliterator_read_property( zval *object, zval *member, int type, static void Transliterator_write_property( zval *object, zval *member, zval *value, void **cache_slot ) { + zend_class_entry *scope; TRANSLITERATOR_PROPERTY_HANDLER_PROLOG; - if( ( EG( scope ) != Transliterator_ce_ptr ) && + if (EG(fake_scope)) { + scope = EG(fake_scope); + } else { + scope = zend_get_executed_scope(); + } + if( ( scope != Transliterator_ce_ptr ) && ( zend_binary_strcmp( "id", sizeof( "id" ) - 1, Z_STRVAL_P( member ), Z_STRLEN_P( member ) ) == 0 ) ) { diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c index e339e85d34..a907eed42f 100644 --- a/ext/mysqli/mysqli.c +++ b/ext/mysqli/mysqli.c @@ -1307,7 +1307,7 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags fcc.initialized = 1; fcc.function_handler = ce->constructor; - fcc.calling_scope = EG(scope); + fcc.calling_scope = zend_get_executed_scope(); fcc.called_scope = Z_OBJCE_P(return_value); fcc.object = Z_OBJ_P(return_value); diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c index 58794c79df..61c9c15d2b 100644 --- a/ext/opcache/zend_accelerator_util_funcs.c +++ b/ext/opcache/zend_accelerator_util_funcs.c @@ -40,8 +40,6 @@ typedef int (*id_function_t)(void *, void *); typedef void (*unique_copy_ctor_func_t)(void *pElement); -static zend_ast *zend_ast_clone(zend_ast *ast); - static void zend_accel_destroy_zend_function(zval *zv) { zend_function *function = Z_PTR_P(zv); @@ -169,61 +167,6 @@ static inline void zend_clone_zval(zval *src) src = Z_REFVAL_P(src); } } - if (Z_TYPE_P(src) == IS_CONSTANT_AST) { - if (Z_REFCOUNT_P(src) > 1 && (ptr = accel_xlat_get(Z_AST_P(src))) != NULL) { - Z_AST_P(src) = ptr; - } else { - zend_ast_ref *old = Z_AST_P(src); - - ZVAL_NEW_AST(src, old->ast); - Z_AST_P(src)->gc = old->gc; - if (Z_REFCOUNT_P(src) > 1) { - accel_xlat_set(old, Z_AST_P(src)); - } - Z_ASTVAL_P(src) = zend_ast_clone(Z_ASTVAL_P(src)); - } - } -} - -static zend_ast *zend_ast_clone(zend_ast *ast) -{ - uint32_t i; - - if (ast->kind == ZEND_AST_ZVAL) { - zend_ast_zval *copy = emalloc(sizeof(zend_ast_zval)); - copy->kind = ZEND_AST_ZVAL; - copy->attr = ast->attr; - ZVAL_COPY_VALUE(©->val, zend_ast_get_zval(ast)); - return (zend_ast *) copy; - } else if (zend_ast_is_list(ast)) { - zend_ast_list *list = zend_ast_get_list(ast); - zend_ast_list *copy = emalloc( - sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * list->children); - copy->kind = list->kind; - copy->attr = list->attr; - copy->children = list->children; - for (i = 0; i < list->children; i++) { - if (list->child[i]) { - copy->child[i] = zend_ast_clone(list->child[i]); - } else { - copy->child[i] = NULL; - } - } - return (zend_ast *) copy; - } else { - uint32_t children = zend_ast_get_num_children(ast); - zend_ast *copy = emalloc(sizeof(zend_ast) - sizeof(zend_ast *) + sizeof(zend_ast *) * children); - copy->kind = ast->kind; - copy->attr = ast->attr; - for (i = 0; i < children; i++) { - if (ast->child[i]) { - copy->child[i] = zend_ast_clone(ast->child[i]); - } else { - copy->child[i] = NULL; - } - } - return copy; - } } static void zend_hash_clone_constants(HashTable *ht, HashTable *source) diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index aa3b8e82f3..25a504575d 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -65,7 +65,6 @@ typedef void (*zend_persist_func_t)(zval*); static void zend_persist_zval(zval *z); -static void zend_persist_zval_const(zval *z); static const uint32_t uninitialized_bucket[-HT_MIN_MASK] = {HT_INVALID_IDX, HT_INVALID_IDX}; @@ -204,7 +203,7 @@ static void zend_hash_persist_immutable(HashTable *ht) } /* persist the data itself */ - zend_persist_zval_const(&p->val); + zend_persist_zval(&p->val); nIndex = p->h | ht->nTableMask; Z_NEXT(p->val) = HT_HASH(ht, nIndex); @@ -229,7 +228,7 @@ static void zend_hash_persist_immutable(HashTable *ht) } /* persist the data itself */ - zend_persist_zval_const(&p->val); + zend_persist_zval(&p->val); } } @@ -278,63 +277,10 @@ static void zend_persist_zval(zval *z) zend_accel_store_interned_string(Z_STR_P(z)); Z_GC_FLAGS_P(z) |= flags; Z_TYPE_FLAGS_P(z) &= ~(IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE); - break; - case IS_ARRAY: - new_ptr = zend_shared_alloc_get_xlat_entry(Z_ARR_P(z)); - if (new_ptr) { - Z_ARR_P(z) = new_ptr; - Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE; - } else { - if (Z_IMMUTABLE_P(z)) { - Z_ARR_P(z) = zend_accel_memdup(Z_ARR_P(z), sizeof(zend_array)); - zend_hash_persist_immutable(Z_ARRVAL_P(z)); - } else { - GC_REMOVE_FROM_BUFFER(Z_ARR_P(z)); - zend_accel_store(Z_ARR_P(z), sizeof(zend_array)); - zend_hash_persist(Z_ARRVAL_P(z), zend_persist_zval); - /* make immutable array */ - Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE; - GC_REFCOUNT(Z_COUNTED_P(z)) = 2; - GC_FLAGS(Z_COUNTED_P(z)) |= IS_ARRAY_IMMUTABLE; - Z_ARRVAL_P(z)->u.flags |= HASH_FLAG_STATIC_KEYS; - Z_ARRVAL_P(z)->u.flags &= ~HASH_FLAG_APPLY_PROTECTION; - } - } - break; - case IS_REFERENCE: - new_ptr = zend_shared_alloc_get_xlat_entry(Z_REF_P(z)); - if (new_ptr) { - Z_REF_P(z) = new_ptr; - } else { - zend_accel_store(Z_REF_P(z), sizeof(zend_reference)); - zend_persist_zval(Z_REFVAL_P(z)); - } - break; - case IS_CONSTANT_AST: - new_ptr = zend_shared_alloc_get_xlat_entry(Z_AST_P(z)); - if (new_ptr) { - Z_AST_P(z) = new_ptr; - } else { - zend_accel_store(Z_AST_P(z), sizeof(zend_ast_ref)); - Z_ASTVAL_P(z) = zend_persist_ast(Z_ASTVAL_P(z)); + if (Z_TYPE_P(z) == IS_CONSTANT) { + Z_TYPE_FLAGS_P(z) |= IS_TYPE_IMMUTABLE; } break; - } -} - -static void zend_persist_zval_static(zval *z) -{ - zend_uchar flags; - void *new_ptr; - - switch (Z_TYPE_P(z)) { - case IS_STRING: - case IS_CONSTANT: - flags = Z_GC_FLAGS_P(z) & ~ (IS_STR_PERSISTENT | IS_STR_INTERNED | IS_STR_PERMANENT); - zend_accel_store_interned_string(Z_STR_P(z)); - Z_GC_FLAGS_P(z) |= flags; - Z_TYPE_FLAGS_P(z) &= ~(IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE); - break; case IS_ARRAY: new_ptr = zend_shared_alloc_get_xlat_entry(Z_ARR_P(z)); if (new_ptr) { @@ -381,62 +327,6 @@ static void zend_persist_zval_static(zval *z) } } -static void zend_persist_zval_const(zval *z) -{ - zend_uchar flags; - void *new_ptr; - - switch (Z_TYPE_P(z)) { - case IS_STRING: - case IS_CONSTANT: - flags = Z_GC_FLAGS_P(z) & ~ (IS_STR_PERSISTENT | IS_STR_INTERNED | IS_STR_PERMANENT); - zend_accel_memdup_interned_string(Z_STR_P(z)); - Z_GC_FLAGS_P(z) |= flags; - Z_TYPE_FLAGS_P(z) &= ~(IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE); - break; - case IS_ARRAY: - new_ptr = zend_shared_alloc_get_xlat_entry(Z_ARR_P(z)); - if (new_ptr) { - Z_ARR_P(z) = new_ptr; - Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE; - } else { - if (Z_IMMUTABLE_P(z)) { - Z_ARR_P(z) = zend_accel_memdup(Z_ARR_P(z), sizeof(zend_array)); - zend_hash_persist_immutable(Z_ARRVAL_P(z)); - } else { - GC_REMOVE_FROM_BUFFER(Z_ARR_P(z)); - zend_accel_store(Z_ARR_P(z), sizeof(zend_array)); - zend_hash_persist(Z_ARRVAL_P(z), zend_persist_zval); - /* make immutable array */ - Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE; - GC_REFCOUNT(Z_COUNTED_P(z)) = 2; - GC_FLAGS(Z_COUNTED_P(z)) |= IS_ARRAY_IMMUTABLE; - Z_ARRVAL_P(z)->u.flags |= HASH_FLAG_STATIC_KEYS; - Z_ARRVAL_P(z)->u.flags &= ~HASH_FLAG_APPLY_PROTECTION; - } - } - break; - case IS_REFERENCE: - new_ptr = zend_shared_alloc_get_xlat_entry(Z_REF_P(z)); - if (new_ptr) { - Z_REF_P(z) = new_ptr; - } else { - zend_accel_store(Z_REF_P(z), sizeof(zend_reference)); - zend_persist_zval(Z_REFVAL_P(z)); - } - break; - case IS_CONSTANT_AST: - new_ptr = zend_shared_alloc_get_xlat_entry(Z_AST_P(z)); - if (new_ptr) { - Z_AST_P(z) = new_ptr; - } else { - zend_accel_store(Z_AST_P(z), sizeof(zend_ast_ref)); - Z_ASTVAL_P(z) = zend_persist_ast(Z_ASTVAL_P(z)); - } - break; - } -} - static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_script* main_persistent_script) { int already_stored = 0; @@ -472,7 +362,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc if (stored) { op_array->static_variables = stored; } else { - zend_hash_persist(op_array->static_variables, zend_persist_zval_static); + zend_hash_persist(op_array->static_variables, zend_persist_zval); zend_accel_store(op_array->static_variables, sizeof(HashTable)); /* make immutable array */ GC_REFCOUNT(op_array->static_variables) = 2; diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 68c9d67a6a..624281c18b 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -447,7 +447,7 @@ static void pdo_stmt_construct(zend_execute_data *execute_data, pdo_stmt_t *stmt fcc.initialized = 1; fcc.function_handler = dbstmt_ce->constructor; - fcc.calling_scope = EG(scope); + fcc.calling_scope = zend_get_executed_scope(); fcc.called_scope = Z_OBJCE_P(object); fcc.object = Z_OBJ_P(object); diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 91546c02c5..c2f3c13399 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -750,7 +750,7 @@ static int do_fetch_class_prepare(pdo_stmt_t *stmt) /* {{{ */ fcc->initialized = 1; fcc->function_handler = ce->constructor; - fcc->calling_scope = EG(scope); + fcc->calling_scope = zend_get_executed_scope(); fcc->called_scope = ce; return 1; } else if (!Z_ISUNDEF(stmt->fetch.cls.ctor_args)) { diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index 82a7503409..408802cfbf 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -2848,7 +2848,7 @@ static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, zend_long result_ fcc.initialized = 1; fcc.function_handler = ce->constructor; - fcc.calling_scope = EG(scope); + fcc.calling_scope = zend_get_executed_scope(); fcc.called_scope = Z_OBJCE_P(return_value); fcc.object = Z_OBJ_P(return_value); diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index fe89db9dee..b4bd65182a 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -456,7 +456,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in zend_class_constant *c; ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) { - zval_update_constant_ex(&c->value, 1, NULL); + zval_update_constant_ex(&c->value, NULL); _class_const_string(str, ZSTR_VAL(key), c, indent); } ZEND_HASH_FOREACH_END(); } @@ -706,14 +706,10 @@ static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg zend_op *precv = _get_recv_op((zend_op_array*)fptr, offset); if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2_type != IS_UNUSED) { zval zv; - zend_class_entry *old_scope; string_write(str, " = ", sizeof(" = ")-1); ZVAL_DUP(&zv, RT_CONSTANT(&fptr->op_array, precv->op2)); - old_scope = EG(scope); - EG(scope) = fptr->common.scope; - zval_update_constant_ex(&zv, 1, NULL); - EG(scope) = old_scope; + zval_update_constant_ex(&zv, fptr->common.scope); if (Z_TYPE(zv) == IS_TRUE) { string_write(str, "true", sizeof("true")-1); } else if (Z_TYPE(zv) == IS_FALSE) { @@ -1931,7 +1927,7 @@ ZEND_METHOD(reflection_function, getStaticVariables) fptr->op_array.static_variables = zend_array_dup(fptr->op_array.static_variables); } ZEND_HASH_FOREACH_VAL(fptr->op_array.static_variables, val) { - if (UNEXPECTED(zval_update_constant_ex(val, 1, fptr->common.scope) != SUCCESS)) { + if (UNEXPECTED(zval_update_constant_ex(val, fptr->common.scope) != SUCCESS)) { return; } } ZEND_HASH_FOREACH_END(); @@ -1969,7 +1965,7 @@ ZEND_METHOD(reflection_function, invoke) fcc.initialized = 1; fcc.function_handler = fptr; - fcc.calling_scope = EG(scope); + fcc.calling_scope = zend_get_executed_scope(); fcc.called_scope = NULL; fcc.object = NULL; @@ -2027,7 +2023,7 @@ ZEND_METHOD(reflection_function, invokeArgs) fcc.initialized = 1; fcc.function_handler = fptr; - fcc.calling_scope = EG(scope); + fcc.calling_scope = zend_get_executed_scope(); fcc.called_scope = NULL; fcc.object = NULL; @@ -2890,11 +2886,7 @@ ZEND_METHOD(reflection_parameter, getDefaultValue) ZVAL_COPY_VALUE(return_value, RT_CONSTANT(¶m->fptr->op_array, precv->op2)); if (Z_CONSTANT_P(return_value)) { - zend_class_entry *old_scope = EG(scope); - - EG(scope) = param->fptr->common.scope; - zval_update_constant_ex(return_value, 0, NULL); - EG(scope) = old_scope; + zval_update_constant_ex(return_value, param->fptr->common.scope); } else { zval_copy_ctor(return_value); } @@ -3965,7 +3957,7 @@ static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value /* this is necessary to make it able to work with default array * properties, returned to user */ if (Z_CONSTANT(prop_copy)) { - if (UNEXPECTED(zval_update_constant_ex(&prop_copy, 1, NULL) != SUCCESS)) { + if (UNEXPECTED(zval_update_constant_ex(&prop_copy, NULL) != SUCCESS)) { return; } } @@ -4621,7 +4613,7 @@ ZEND_METHOD(reflection_class, getConstants) GET_REFLECTION_OBJECT_PTR(ce); array_init(return_value); ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) { - if (UNEXPECTED(zval_update_constant_ex(&c->value, 1, ce) != SUCCESS)) { + if (UNEXPECTED(zval_update_constant_ex(&c->value, ce) != SUCCESS)) { zend_array_destroy(Z_ARRVAL_P(return_value)); return; } @@ -4669,7 +4661,7 @@ ZEND_METHOD(reflection_class, getConstant) GET_REFLECTION_OBJECT_PTR(ce); ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) { - if (UNEXPECTED(zval_update_constant_ex(&c->value, 1, ce) != SUCCESS)) { + if (UNEXPECTED(zval_update_constant_ex(&c->value, ce) != SUCCESS)) { return; } } ZEND_HASH_FOREACH_END(); @@ -4856,10 +4848,10 @@ ZEND_METHOD(reflection_class, newInstance) return; } - old_scope = EG(scope); - EG(scope) = ce; + old_scope = EG(fake_scope); + EG(fake_scope) = ce; constructor = Z_OBJ_HT_P(return_value)->get_constructor(Z_OBJ_P(return_value)); - EG(scope) = old_scope; + EG(fake_scope) = old_scope; /* Run the constructor if there is one */ if (constructor) { @@ -4893,7 +4885,7 @@ ZEND_METHOD(reflection_class, newInstance) fcc.initialized = 1; fcc.function_handler = constructor; - fcc.calling_scope = EG(scope); + fcc.calling_scope = zend_get_executed_scope();; fcc.called_scope = Z_OBJCE_P(return_value); fcc.object = Z_OBJ_P(return_value); @@ -4959,10 +4951,10 @@ ZEND_METHOD(reflection_class, newInstanceArgs) return; } - old_scope = EG(scope); - EG(scope) = ce; + old_scope = EG(fake_scope); + EG(fake_scope) = ce; constructor = Z_OBJ_HT_P(return_value)->get_constructor(Z_OBJ_P(return_value)); - EG(scope) = old_scope; + EG(fake_scope) = old_scope; /* Run the constructor if there is one */ if (constructor) { @@ -4995,7 +4987,7 @@ ZEND_METHOD(reflection_class, newInstanceArgs) fcc.initialized = 1; fcc.function_handler = constructor; - fcc.calling_scope = EG(scope); + fcc.calling_scope = zend_get_executed_scope(); fcc.called_scope = Z_OBJCE_P(return_value); fcc.object = Z_OBJ_P(return_value); diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index fc389f2365..803a5cd596 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -1164,13 +1164,8 @@ static xmlNodePtr to_xml_null(encodeTypePtr type, zval *data, int style, xmlNode static void set_zval_property(zval* object, char* name, zval* val) { - zend_class_entry *old_scope; - - old_scope = EG(scope); - EG(scope) = Z_OBJCE_P(object); - add_property_zval(object, name, val); + zend_update_property(Z_OBJCE_P(object), object, name, strlen(name), val); if (Z_REFCOUNTED_P(val)) Z_DELREF_P(val); - EG(scope) = old_scope; } static zval* get_zval_property(zval* object, char* name, zval *rv) @@ -1181,15 +1176,15 @@ static zval* get_zval_property(zval* object, char* name, zval *rv) zend_class_entry *old_scope; ZVAL_STRING(&member, name); - old_scope = EG(scope); - EG(scope) = Z_OBJCE_P(object); + old_scope = EG(fake_scope); + EG(fake_scope) = Z_OBJCE_P(object); data = Z_OBJ_HT_P(object)->read_property(object, &member, BP_VAR_IS, NULL, rv); if (data == &EG(uninitialized_zval)) { /* Hack for bug #32455 */ zend_property_info *property_info; property_info = zend_get_property_info(Z_OBJCE_P(object), Z_STR(member), 1); - EG(scope) = old_scope; + EG(fake_scope) = old_scope; if (property_info != ZEND_WRONG_PROPERTY_INFO && property_info && zend_hash_exists(Z_OBJPROP_P(object), property_info->name)) { zval_ptr_dtor(&member); @@ -1199,7 +1194,7 @@ static zval* get_zval_property(zval* object, char* name, zval *rv) return NULL; } zval_ptr_dtor(&member); - EG(scope) = old_scope; + EG(fake_scope) = old_scope; return data; } else if (Z_TYPE_P(object) == IS_ARRAY) { zval *data_ptr; @@ -1218,10 +1213,10 @@ static void unset_zval_property(zval* object, char* name) zend_class_entry *old_scope; ZVAL_STRING(&member, name); - old_scope = EG(scope); - EG(scope) = Z_OBJCE_P(object); + old_scope = EG(fake_scope); + EG(fake_scope) = Z_OBJCE_P(object); Z_OBJ_HT_P(object)->unset_property(object, &member, NULL); - EG(scope) = old_scope; + EG(fake_scope) = old_scope; zval_ptr_dtor(&member); } else if (Z_TYPE_P(object) == IS_ARRAY) { zend_hash_str_del(Z_ARRVAL_P(object), name, strlen(name)); diff --git a/ext/spl/spl_engine.h b/ext/spl/spl_engine.h index e73e0f08a0..b683c16d94 100644 --- a/ext/spl/spl_engine.h +++ b/ext/spl/spl_engine.h @@ -71,7 +71,7 @@ static inline void spl_instantiate_arg_n(zend_class_entry *pce, zval *retval, in fcc.initialized = 1; fcc.function_handler = func; - fcc.calling_scope = EG(scope); + fcc.calling_scope = zend_get_executed_scope(); fcc.called_scope = pce; fcc.object = Z_OBJ_P(retval); diff --git a/ext/standard/array.c b/ext/standard/array.c index 61ed3c0bd9..d1281c2557 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1843,8 +1843,11 @@ PHP_FUNCTION(extract) if (var_exists && ZSTR_LEN(var_name) == sizeof("GLOBALS")-1 && !strcmp(ZSTR_VAL(var_name), "GLOBALS")) { break; } - if (var_exists && ZSTR_LEN(var_name) == sizeof("this")-1 && !strcmp(ZSTR_VAL(var_name), "this") && EG(scope) && ZSTR_LEN(EG(scope)->name) != 0) { - break; + if (var_exists && ZSTR_LEN(var_name) == sizeof("this")-1 && !strcmp(ZSTR_VAL(var_name), "this")) { + zend_class_entry *scope = zend_get_executed_scope(); + if (scope && ZSTR_LEN(scope->name) != 0) { + break; + } } ZVAL_STR_COPY(&final_name, var_name); break; diff --git a/ext/standard/assert.c b/ext/standard/assert.c index 109ba3ba22..2cb6285f4e 100644 --- a/ext/standard/assert.c +++ b/ext/standard/assert.c @@ -164,7 +164,6 @@ PHP_FUNCTION(assert) if (Z_TYPE_P(assertion) == IS_STRING) { zval retval; int old_error_reporting = 0; /* shut up gcc! */ - zend_class_entry *orig_scope = EG(scope); myeval = Z_STRVAL_P(assertion); @@ -194,8 +193,6 @@ PHP_FUNCTION(assert) EG(error_reporting) = old_error_reporting; } - EG(scope) = orig_scope; - convert_to_boolean(&retval); val = Z_TYPE(retval) == IS_TRUE; } else { diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 6323d18b5f..0481e41a6e 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -3834,16 +3834,18 @@ PHP_FUNCTION(constant) { zend_string *const_name; zval *c; + zend_class_entry *scope; if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &const_name) == FAILURE) { return; } - c = zend_get_constant_ex(const_name, NULL, ZEND_FETCH_CLASS_SILENT); + scope = zend_get_executed_scope(); + c = zend_get_constant_ex(const_name, scope, ZEND_FETCH_CLASS_SILENT); if (c) { ZVAL_COPY_VALUE(return_value, c); if (Z_CONSTANT_P(return_value)) { - if (UNEXPECTED(zval_update_constant_ex(return_value, 1, NULL) != SUCCESS)) { + if (UNEXPECTED(zval_update_constant_ex(return_value, scope) != SUCCESS)) { return; } } diff --git a/ext/wddx/wddx.c b/ext/wddx/wddx.c index 330cb49f08..e848afdeb7 100644 --- a/ext/wddx/wddx.c +++ b/ext/wddx/wddx.c @@ -954,12 +954,8 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name) /* Clean up class name var entry */ zval_ptr_dtor(&ent1->data); } else if (Z_TYPE(ent2->data) == IS_OBJECT) { - zend_class_entry *old_scope = EG(scope); - - EG(scope) = Z_OBJCE(ent2->data); - add_property_zval(&ent2->data, ent1->varname, &ent1->data); + zend_update_property(Z_OBJCE(ent2->data), &ent2->data, ent1->varname, strlen(ent1->varname), &ent1->data); if Z_REFCOUNTED(ent1->data) Z_DELREF(ent1->data); - EG(scope) = old_scope; } else { zend_symtable_str_update(target_hash, ent1->varname, strlen(ent1->varname), &ent1->data); } diff --git a/main/streams/userspace.c b/main/streams/userspace.c index 5ad7dc2e64..eb8b32eed9 100644 --- a/main/streams/userspace.c +++ b/main/streams/userspace.c @@ -308,7 +308,7 @@ static void user_stream_create_object(struct php_user_stream_wrapper *uwrap, php fcc.initialized = 1; fcc.function_handler = uwrap->ce->constructor; - fcc.calling_scope = EG(scope); + fcc.calling_scope = zend_get_executed_scope(); fcc.called_scope = Z_OBJCE_P(object); fcc.object = Z_OBJ_P(object); diff --git a/sapi/phpdbg/phpdbg_frame.c b/sapi/phpdbg/phpdbg_frame.c index d6256a84af..f64d18b4bb 100644 --- a/sapi/phpdbg/phpdbg_frame.c +++ b/sapi/phpdbg/phpdbg_frame.c @@ -36,8 +36,6 @@ void phpdbg_restore_frame(void) /* {{{ */ /* move things back */ EG(current_execute_data) = PHPDBG_FRAME(execute_data); - - EG(scope) = PHPDBG_EX(func)->op_array.scope; } /* }}} */ void phpdbg_switch_frame(int frame) /* {{{ */ @@ -78,8 +76,6 @@ void phpdbg_switch_frame(int frame) /* {{{ */ /* backup things and jump back */ PHPDBG_FRAME(execute_data) = EG(current_execute_data); EG(current_execute_data) = execute_data; - - EG(scope) = PHPDBG_EX(func)->op_array.scope; } phpdbg_notice("frame", "id=\"%d\"", "Switched to frame #%d", frame); diff --git a/sapi/phpdbg/phpdbg_list.c b/sapi/phpdbg/phpdbg_list.c index e9cf1bc0b8..2e97ad4b73 100644 --- a/sapi/phpdbg/phpdbg_list.c +++ b/sapi/phpdbg/phpdbg_list.c @@ -200,11 +200,12 @@ void phpdbg_list_function_byname(const char *str, size_t len) /* {{{ */ /* search active scope if begins with period */ if (func_name[0] == '.') { - if (EG(scope)) { + zend_class_entry *scope = zend_get_executed_scope(); + if (scope) { func_name++; func_name_len--; - func_table = &EG(scope)->function_table; + func_table = &scope->function_table; } else { phpdbg_error("inactive", "type=\"noclasses\"", "No active class"); return; diff --git a/sapi/phpdbg/phpdbg_print.c b/sapi/phpdbg/phpdbg_print.c index 3725bf6083..034354a9e7 100644 --- a/sapi/phpdbg/phpdbg_print.c +++ b/sapi/phpdbg/phpdbg_print.c @@ -217,11 +217,13 @@ PHPDBG_PRINT(func) /* {{{ */ zend_string *lcname; /* search active scope if begins with period */ if (func_name[0] == '.') { - if (EG(scope)) { + zend_class_entry *scope = zend_get_executed_scope(); + + if (scope) { func_name++; func_name_len--; - func_table = &EG(scope)->function_table; + func_table = &scope->function_table; } else { phpdbg_error("inactive", "type=\"noclasses\"", "No active class"); return SUCCESS; diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index a9fd351ffd..787517dd9d 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -797,7 +797,6 @@ PHPDBG_COMMAND(ev) /* {{{ */ zval retval; zend_execute_data *original_execute_data = EG(current_execute_data); - zend_class_entry *original_scope = EG(scope); zend_vm_stack original_stack = EG(vm_stack); zend_object *ex = NULL; @@ -845,7 +844,6 @@ PHPDBG_COMMAND(ev) /* {{{ */ OBJ_RELEASE(ex); } EG(current_execute_data) = original_execute_data; - EG(scope) = original_scope; EG(vm_stack_top) = original_stack->top; EG(vm_stack_end) = original_stack->end; EG(vm_stack) = original_stack; diff --git a/sapi/phpdbg/phpdbg_watch.c b/sapi/phpdbg/phpdbg_watch.c index 2c324aa5dc..0224ff4fd1 100644 --- a/sapi/phpdbg/phpdbg_watch.c +++ b/sapi/phpdbg/phpdbg_watch.c @@ -680,7 +680,9 @@ static int phpdbg_watchpoint_parse_step(char *name, size_t namelen, char *key, s } static int phpdbg_watchpoint_parse_symtables(char *input, size_t len, int (*callback)(phpdbg_watchpoint_t *)) { - if (EG(scope) && len >= 5 && !memcmp("$this", input, 5)) { + zend_class_entry *scope = zend_get_executed_scope(); + + if (scope && len >= 5 && !memcmp("$this", input, 5)) { zend_hash_str_add(EG(current_execute_data)->symbol_table, ZEND_STRL("this"), &EG(current_execute_data)->This); } -- 2.40.0