summaryrefslogtreecommitdiff
path: root/Zend/zend_object_handlers.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_object_handlers.c')
-rw-r--r--Zend/zend_object_handlers.c259
1 files changed, 165 insertions, 94 deletions
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c
index 70dab660b3..434102035c 100644
--- a/Zend/zend_object_handlers.c
+++ b/Zend/zend_object_handlers.c
@@ -191,6 +191,9 @@ ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp) /* {{{ *
static void zend_std_call_getter(zval *object, zval *member, zval *retval) /* {{{ */
{
zend_class_entry *ce = Z_OBJCE_P(object);
+ zend_class_entry *orig_fake_scope = EG(fake_scope);
+
+ EG(fake_scope) = NULL;
/* __get handler is called with one argument:
property name
@@ -198,6 +201,8 @@ static void zend_std_call_getter(zval *object, zval *member, zval *retval) /* {{
it should return whether the call was successful or not
*/
zend_call_method_with_1_params(object, ce, &ce->__get, ZEND_GET_FUNC_NAME, retval, member);
+
+ EG(fake_scope) = orig_fake_scope;
}
/* }}} */
@@ -206,6 +211,9 @@ static int zend_std_call_setter(zval *object, zval *member, zval *value) /* {{{
zval retval;
int result;
zend_class_entry *ce = Z_OBJCE_P(object);
+ zend_class_entry *orig_fake_scope = EG(fake_scope);
+
+ EG(fake_scope) = NULL;
/* __set handler is called with two arguments:
property name
@@ -218,8 +226,10 @@ static int zend_std_call_setter(zval *object, zval *member, zval *value) /* {{{
if (Z_TYPE(retval) != IS_UNDEF) {
result = i_zend_is_true(&retval) ? SUCCESS : FAILURE;
zval_ptr_dtor(&retval);
+ EG(fake_scope) = orig_fake_scope;
return result;
} else {
+ EG(fake_scope) = orig_fake_scope;
return FAILURE;
}
}
@@ -228,6 +238,9 @@ static int zend_std_call_setter(zval *object, zval *member, zval *value) /* {{{
static void zend_std_call_unsetter(zval *object, zval *member) /* {{{ */
{
zend_class_entry *ce = Z_OBJCE_P(object);
+ zend_class_entry *orig_fake_scope = EG(fake_scope);
+
+ EG(fake_scope) = NULL;
/* __unset handler is called with one argument:
property name
@@ -238,12 +251,17 @@ static void zend_std_call_unsetter(zval *object, zval *member) /* {{{ */
zend_call_method_with_1_params(object, ce, &ce->__unset, ZEND_UNSET_FUNC_NAME, NULL, member);
zval_ptr_dtor(member);
+
+ EG(fake_scope) = orig_fake_scope;
}
/* }}} */
static void zend_std_call_issetter(zval *object, zval *member, zval *retval) /* {{{ */
{
zend_class_entry *ce = Z_OBJCE_P(object);
+ zend_class_entry *orig_fake_scope = EG(fake_scope);
+
+ EG(fake_scope) = NULL;
/* __isset handler is called with one argument:
property name
@@ -256,17 +274,31 @@ static void zend_std_call_issetter(zval *object, zval *member, zval *retval) /*
zend_call_method_with_1_params(object, ce, &ce->__isset, ZEND_ISSET_FUNC_NAME, retval, member);
zval_ptr_dtor(member);
+
+ EG(fake_scope) = orig_fake_scope;
}
/* }}} */
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;
}
@@ -291,18 +323,15 @@ 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);
}
- if (UNEXPECTED(ZSTR_VAL(member)[0] == '\0')) {
+ if (UNEXPECTED(ZSTR_VAL(member)[0] == '\0' && ZSTR_LEN(member) != 0)) {
if (!silent) {
- if (ZSTR_LEN(member) == 0) {
- zend_throw_error(NULL, "Cannot access empty property");
- } else {
- zend_throw_error(NULL, "Cannot access property started with '\\0'");
- }
+ zend_throw_error(NULL, "Cannot access property started with '\\0'");
}
return ZEND_WRONG_PROPERTY_OFFSET;
}
@@ -337,10 +366,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)) {
@@ -373,14 +408,11 @@ 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 (UNEXPECTED(ZSTR_VAL(member)[0] == '\0' && ZSTR_LEN(member) != 0)) {
if (!silent) {
- if (ZSTR_LEN(member) == 0) {
- zend_throw_error(NULL, "Cannot access empty property");
- } else {
- zend_throw_error(NULL, "Cannot access property started with '\\0'");
- }
+ zend_throw_error(NULL, "Cannot access property started with '\\0'");
}
return ZEND_WRONG_PROPERTY_INFO;
}
@@ -414,10 +446,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)) {
@@ -476,31 +514,60 @@ ZEND_API int zend_check_property_access(zend_object *zobj, zend_string *prop_inf
/* }}} */
static void zend_property_guard_dtor(zval *el) /* {{{ */ {
- efree_size(Z_PTR_P(el), sizeof(zend_ulong));
+ uint32_t *ptr = (uint32_t*)Z_PTR_P(el);
+ if (EXPECTED(!(((zend_uintptr_t)ptr) & 1))) {
+ efree_size(ptr, sizeof(uint32_t));
+ }
}
/* }}} */
-static zend_long *zend_get_property_guard(zend_object *zobj, zend_string *member) /* {{{ */
+ZEND_API uint32_t *zend_get_property_guard(zend_object *zobj, zend_string *member) /* {{{ */
{
HashTable *guards;
- zend_long stub, *guard;
+ zval *zv;
+ uint32_t *ptr;
ZEND_ASSERT(GC_FLAGS(zobj) & IS_OBJ_USE_GUARDS);
- if (GC_FLAGS(zobj) & IS_OBJ_HAS_GUARDS) {
- guards = Z_PTR(zobj->properties_table[zobj->ce->default_properties_count]);
+ zv = zobj->properties_table + zobj->ce->default_properties_count;
+ if (EXPECTED(Z_TYPE_P(zv) == IS_STRING)) {
+ zend_string *str = Z_STR_P(zv);
+ if (EXPECTED(str == member) ||
+ /* hash values are always pred-calculated here */
+ (EXPECTED(ZSTR_H(str) == ZSTR_H(member)) &&
+ EXPECTED(ZSTR_LEN(str) == ZSTR_LEN(member)) &&
+ EXPECTED(memcmp(ZSTR_VAL(str), ZSTR_VAL(member), ZSTR_LEN(member)) == 0))) {
+ return &zv->u2.property_guard;
+ } else if (EXPECTED(zv->u2.property_guard == 0)) {
+ zend_string_release(Z_STR_P(zv));
+ ZVAL_STR_COPY(zv, member);
+ return &zv->u2.property_guard;
+ } else {
+ ALLOC_HASHTABLE(guards);
+ zend_hash_init(guards, 8, NULL, zend_property_guard_dtor, 0);
+ /* mark pointer as "special" using low bit */
+ zend_hash_add_new_ptr(guards, member,
+ (void*)(((zend_uintptr_t)&zv->u2.property_guard) | 1));
+ zend_string_release(Z_STR_P(zv));
+ ZVAL_ARR(zv, guards);
+ }
+ } else if (EXPECTED(Z_TYPE_P(zv) == IS_ARRAY)) {
+ guards = Z_ARRVAL_P(zv);
ZEND_ASSERT(guards != NULL);
- if ((guard = (zend_long *)zend_hash_find_ptr(guards, member)) != NULL) {
- return guard;
+ zv = zend_hash_find(guards, member);
+ if (zv != NULL) {
+ return (uint32_t*)(((zend_uintptr_t)Z_PTR_P(zv)) & ~1);
}
} else {
- ALLOC_HASHTABLE(guards);
- zend_hash_init(guards, 8, NULL, zend_property_guard_dtor, 0);
- Z_PTR(zobj->properties_table[zobj->ce->default_properties_count]) = guards;
+ ZEND_ASSERT(Z_TYPE_P(zv) == IS_UNDEF);
GC_FLAGS(zobj) |= IS_OBJ_HAS_GUARDS;
- }
-
- stub = 0;
- return (zend_long *)zend_hash_add_mem(guards, member, &stub, sizeof(zend_ulong));
+ ZVAL_STR_COPY(zv, member);
+ zv->u2.property_guard = 0;
+ return &zv->u2.property_guard;
+ }
+ /* we have to allocate uint32_t separately because ht->arData may be reallocated */
+ ptr = (uint32_t*)emalloc(sizeof(uint32_t));
+ *ptr = 0;
+ return (uint32_t*)zend_hash_add_new_ptr(guards, member, ptr);
}
/* }}} */
@@ -545,7 +612,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_
/* magic isset */
if ((type == BP_VAR_IS) && zobj->ce->__isset) {
zval tmp_object, tmp_result;
- zend_long *guard = zend_get_property_guard(zobj, Z_STR_P(member));
+ uint32_t *guard = zend_get_property_guard(zobj, Z_STR_P(member));
if (!((*guard) & IN_ISSET)) {
ZVAL_COPY(&tmp_object, object);
@@ -569,7 +636,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_
/* magic get */
if (zobj->ce->__get) {
- zend_long *guard = zend_get_property_guard(zobj, Z_STR_P(member));
+ uint32_t *guard = zend_get_property_guard(zobj, Z_STR_P(member));
if (!((*guard) & IN_GET)) {
zval tmp_object;
@@ -594,16 +661,10 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_
zval_ptr_dtor(&tmp_object);
goto exit;
} else {
- if (Z_STRVAL_P(member)[0] == '\0') {
- if (Z_STRLEN_P(member) == 0) {
- zend_throw_error(NULL, "Cannot access empty property");
- retval = &EG(uninitialized_zval);
- goto exit;
- } else {
- zend_throw_error(NULL, "Cannot access property started with '\\0'");
- retval = &EG(uninitialized_zval);
- goto exit;
- }
+ if (Z_STRVAL_P(member)[0] == '\0' && Z_STRLEN_P(member) != 0) {
+ zend_throw_error(NULL, "Cannot access property started with '\\0'");
+ retval = &EG(uninitialized_zval);
+ goto exit;
}
}
}
@@ -664,7 +725,7 @@ found:
/* magic set */
if (zobj->ce->__set) {
- zend_long *guard = zend_get_property_guard(zobj, Z_STR_P(member));
+ uint32_t *guard = zend_get_property_guard(zobj, Z_STR_P(member));
if (!((*guard) & IN_SET)) {
zval tmp_object;
@@ -679,14 +740,9 @@ found:
} else if (EXPECTED(property_offset != ZEND_WRONG_PROPERTY_OFFSET)) {
goto write_std_property;
} else {
- if (Z_STRVAL_P(member)[0] == '\0') {
- if (Z_STRLEN_P(member) == 0) {
- zend_throw_error(NULL, "Cannot access empty property");
- goto exit;
- } else {
- zend_throw_error(NULL, "Cannot access property started with '\\0'");
- goto exit;
- }
+ if (Z_STRVAL_P(member)[0] == '\0' && Z_STRLEN_P(member) != 0) {
+ zend_throw_error(NULL, "Cannot access property started with '\\0'");
+ goto exit;
}
}
} else if (EXPECTED(property_offset != ZEND_WRONG_PROPERTY_OFFSET)) {
@@ -934,7 +990,7 @@ static void zend_std_unset_property(zval *object, zval *member, void **cache_slo
/* magic unset */
if (zobj->ce->__unset) {
- zend_long *guard = zend_get_property_guard(zobj, Z_STR_P(member));
+ uint32_t *guard = zend_get_property_guard(zobj, Z_STR_P(member));
if (!((*guard) & IN_UNSET)) {
zval tmp_object;
@@ -945,14 +1001,9 @@ static void zend_std_unset_property(zval *object, zval *member, void **cache_slo
(*guard) &= ~IN_UNSET;
zval_ptr_dtor(&tmp_object);
} else {
- if (Z_STRVAL_P(member)[0] == '\0') {
- if (Z_STRLEN_P(member) == 0) {
- zend_throw_error(NULL, "Cannot access empty property");
- goto exit;
- } else {
- zend_throw_error(NULL, "Cannot access property started with '\\0'");
- goto exit;
- }
+ if (Z_STRVAL_P(member)[0] == '\0' && Z_STRLEN_P(member) != 0) {
+ zend_throw_error(NULL, "Cannot access property started with '\\0'");
+ goto exit;
}
}
}
@@ -985,6 +1036,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;
@@ -996,7 +1048,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;
}
@@ -1005,11 +1058,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;
}
}
@@ -1078,7 +1131,6 @@ ZEND_API zend_function *zend_get_call_trampoline_func(zend_class_entry *ce, zend
if (is_static) {
func->fn_flags |= ZEND_ACC_STATIC;
}
- func->this_var = -1;
func->opcodes = &EG(call_trampoline_op);
func->prototype = fbc;
@@ -1113,6 +1165,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)) {
@@ -1151,7 +1204,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;
}
}
@@ -1159,26 +1213,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;
}
}
@@ -1204,6 +1261,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);
@@ -1264,25 +1322,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;
}
}
@@ -1346,6 +1406,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) {
@@ -1353,9 +1414,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));
@@ -1367,9 +1433,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));
@@ -1498,7 +1569,7 @@ found:
result = 0;
if ((has_set_exists != 2) && zobj->ce->__isset) {
- zend_long *guard = zend_get_property_guard(zobj, Z_STR_P(member));
+ uint32_t *guard = zend_get_property_guard(zobj, Z_STR_P(member));
if (!((*guard) & IN_ISSET)) {
zval rv;
@@ -1626,7 +1697,7 @@ int zend_std_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function **f
ce = Z_OBJCE_P(obj);
- if ((func = zend_hash_str_find(&ce->function_table, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1)) == NULL) {
+ if ((func = zend_hash_find(&ce->function_table, CG(known_strings)[ZEND_STR_MAGIC_INVOKE])) == NULL) {
return FAILURE;
}
*fptr_ptr = Z_FUNC_P(func);