summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2016-04-28 04:13:34 +0300
committerDmitry Stogov <dmitry@zend.com>2016-04-28 04:13:34 +0300
commit6499162ff0d8aa6e862d3e3cdd2288b87636b8a1 (patch)
treeb1de28564ceb5249bd207a6291fff0ab3dac877f
parent8339222106ac38090e9790f1abbbe2c70c1840fd (diff)
downloadphp-git-6499162ff0d8aa6e862d3e3cdd2288b87636b8a1.tar.gz
- 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.
-rw-r--r--Zend/tests/constant_expressions_self_referencing_array.phpt2
-rw-r--r--Zend/zend_API.c108
-rw-r--r--Zend/zend_ast.c20
-rw-r--r--Zend/zend_builtin_functions.c44
-rw-r--r--Zend/zend_constants.c26
-rw-r--r--Zend/zend_execute.c11
-rw-r--r--Zend/zend_execute.h5
-rw-r--r--Zend/zend_execute_API.c73
-rw-r--r--Zend/zend_generators.c5
-rw-r--r--Zend/zend_globals.h2
-rw-r--r--Zend/zend_ini_parser.y2
-rw-r--r--Zend/zend_object_handlers.c117
-rw-r--r--Zend/zend_objects.c40
-rw-r--r--Zend/zend_types.h5
-rw-r--r--Zend/zend_vm_def.h76
-rw-r--r--Zend/zend_vm_execute.h159
-rw-r--r--ext/intl/transliterator/transliterator_class.c8
-rw-r--r--ext/mysqli/mysqli.c2
-rw-r--r--ext/opcache/zend_accelerator_util_funcs.c57
-rw-r--r--ext/opcache/zend_persist.c120
-rw-r--r--ext/pdo/pdo_dbh.c2
-rw-r--r--ext/pdo/pdo_stmt.c2
-rw-r--r--ext/pgsql/pgsql.c2
-rw-r--r--ext/reflection/php_reflection.c42
-rw-r--r--ext/soap/php_encoding.c21
-rw-r--r--ext/spl/spl_engine.h2
-rw-r--r--ext/standard/array.c7
-rw-r--r--ext/standard/assert.c3
-rw-r--r--ext/standard/basic_functions.c6
-rw-r--r--ext/wddx/wddx.c6
-rw-r--r--main/streams/userspace.c2
-rw-r--r--sapi/phpdbg/phpdbg_frame.c4
-rw-r--r--sapi/phpdbg/phpdbg_list.c5
-rw-r--r--sapi/phpdbg/phpdbg_print.c6
-rw-r--r--sapi/phpdbg/phpdbg_prompt.c2
-rw-r--r--sapi/phpdbg/phpdbg_watch.c4
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(&copy->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(&param->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);
}