diff options
Diffstat (limited to 'Zend/zend_object_handlers.c')
-rw-r--r-- | Zend/zend_object_handlers.c | 259 |
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); |