}
/* }}} */
-static zend_property_info *zend_duplicate_property_info(zend_property_info *property_info) /* {{{ */
-{
- zend_property_info* new_property_info;
-
- new_property_info = zend_arena_alloc(&CG(arena), sizeof(zend_property_info));
- memcpy(new_property_info, property_info, sizeof(zend_property_info));
- zend_string_addref(new_property_info->name);
- if (new_property_info->doc_comment) {
- zend_string_addref(new_property_info->doc_comment);
- }
- return new_property_info;
-}
-/* }}} */
-
static zend_property_info *zend_duplicate_property_info_internal(zend_property_info *property_info) /* {{{ */
{
zend_property_info* new_property_info = pemalloc(sizeof(zend_property_info), 1);
char *zend_visibility_string(uint32_t fn_flags) /* {{{ */
{
- if (fn_flags & ZEND_ACC_PRIVATE) {
- return "private";
- }
- if (fn_flags & ZEND_ACC_PROTECTED) {
- return "protected";
- }
if (fn_flags & ZEND_ACC_PUBLIC) {
return "public";
+ } else if (fn_flags & ZEND_ACC_PRIVATE) {
+ return "private";
+ } else {
+ ZEND_ASSERT(fn_flags & ZEND_ACC_PROTECTED);
+ return "protected";
}
- return "";
}
/* }}} */
if (UNEXPECTED(child)) {
child_info = Z_PTR_P(child);
- if (UNEXPECTED(parent_info->flags & (ZEND_ACC_PRIVATE|ZEND_ACC_SHADOW))) {
+ if (UNEXPECTED(parent_info->flags & ZEND_ACC_PRIVATE)) {
child_info->flags |= ZEND_ACC_CHANGED;
} else {
if (UNEXPECTED((parent_info->flags & ZEND_ACC_STATIC) != (child_info->flags & ZEND_ACC_STATIC))) {
}
}
} else {
- if (UNEXPECTED(parent_info->flags & ZEND_ACC_PRIVATE)) {
- if (UNEXPECTED(ce->type & ZEND_INTERNAL_CLASS)) {
- child_info = zend_duplicate_property_info_internal(parent_info);
- } else {
- child_info = zend_duplicate_property_info(parent_info);
- }
- child_info->flags &= ~ZEND_ACC_PRIVATE; /* it's not private anymore */
- child_info->flags |= ZEND_ACC_SHADOW; /* but it's a shadow of private */
+ if (UNEXPECTED(ce->type & ZEND_INTERNAL_CLASS)) {
+ child_info = zend_duplicate_property_info_internal(parent_info);
} else {
- if (UNEXPECTED(ce->type & ZEND_INTERNAL_CLASS)) {
- child_info = zend_duplicate_property_info_internal(parent_info);
- } else {
- child_info = parent_info;
- }
+ child_info = parent_info;
}
_zend_hash_append_ptr(&ce->properties_info, key, child_info);
}
/* next: check for conflicts with current class */
if ((coliding_prop = zend_hash_find_ptr(&ce->properties_info, prop_name)) != NULL) {
- if (coliding_prop->flags & ZEND_ACC_SHADOW) {
- zend_string_release_ex(coliding_prop->name, 0);
- if (coliding_prop->doc_comment) {
- zend_string_release_ex(coliding_prop->doc_comment, 0);
- }
+ if ((coliding_prop->flags & ZEND_ACC_PRIVATE) && coliding_prop->ce != ce) {
zend_hash_del(&ce->properties_info, prop_name);
flags |= ZEND_ACC_CHANGED;
} else {
if (property_info->flags & ZEND_ACC_PUBLIC) {
return 1;
- } else if (property_info->flags & ZEND_ACC_PRIVATE) {
+ } else {
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) {
- if (EG(fake_scope)) {
- scope = EG(fake_scope);
+ if (property_info->flags & ZEND_ACC_PRIVATE) {
+ return property_info->ce == scope;
} else {
- scope = zend_get_executed_scope();
+ ZEND_ASSERT(property_info->flags & ZEND_ACC_PROTECTED);
+ return zend_check_protected(property_info->ce, scope);
}
- return zend_check_protected(property_info->ce, scope);
}
- return 0;
}
/* }}} */
if (EXPECTED(zv != NULL)) {
property_info = (zend_property_info*)Z_PTR_P(zv);
flags = property_info->flags;
- if (UNEXPECTED((flags & ZEND_ACC_SHADOW) != 0)) {
- /* if it's a shadow - go to access it's private */
- property_info = NULL;
- } else {
- if (EXPECTED(zend_verify_property_access(property_info, ce) != 0)) {
- if (UNEXPECTED(!(flags & ZEND_ACC_CHANGED))
- || UNEXPECTED((flags & ZEND_ACC_PRIVATE))) {
- if (UNEXPECTED((flags & ZEND_ACC_STATIC) != 0)) {
- if (!silent) {
- zend_error(E_NOTICE, "Accessing static property %s::$%s as non static", ZSTR_VAL(ce->name), ZSTR_VAL(member));
- }
- return ZEND_DYNAMIC_PROPERTY_OFFSET;
+
+ if (flags & ZEND_ACC_PUBLIC) {
+ if (!(flags & ZEND_ACC_CHANGED)) {
+no_changed:
+ if (UNEXPECTED((flags & ZEND_ACC_STATIC) != 0)) {
+ if (!silent) {
+ zend_error(E_NOTICE, "Accessing static property %s::$%s as non static", ZSTR_VAL(ce->name), ZSTR_VAL(member));
}
- goto exit;
+ return ZEND_DYNAMIC_PROPERTY_OFFSET;
+ }
+ goto exit;
+ }
+ goto check_scope;
+ } else {
+ if (EG(fake_scope)) {
+ scope = EG(fake_scope);
+ } else {
+ scope = zend_get_executed_scope();
+ }
+ if (flags & ZEND_ACC_PRIVATE) {
+ if (property_info->ce == scope) {
+ goto no_changed;
+ } else if (property_info->ce != ce) {
+ /* if it's a shadow - go to access it's private */
+ property_info = NULL;
+ } else {
+ /* Try to look in the scope instead */
+ property_info = ZEND_WRONG_PROPERTY_INFO;
}
} else {
- /* Try to look in the scope instead */
- property_info = ZEND_WRONG_PROPERTY_INFO;
+ ZEND_ASSERT(flags & ZEND_ACC_PROTECTED);
+ if (zend_check_protected(property_info->ce, scope)) {
+ if (!(flags & ZEND_ACC_CHANGED)) {
+ goto no_changed;
+ }
+ } else {
+ /* Try to look in the scope instead */
+ property_info = ZEND_WRONG_PROPERTY_INFO;
+ }
}
}
- }
-
- if (EG(fake_scope)) {
- scope = EG(fake_scope);
} else {
- scope = zend_get_executed_scope();
+check_scope:
+ 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) {
+ && ((zend_property_info*)Z_PTR_P(zv))->flags & ZEND_ACC_PRIVATE
+ && ((zend_property_info*)Z_PTR_P(zv))->ce == scope) {
property_info = (zend_property_info*)Z_PTR_P(zv);
if (UNEXPECTED((property_info->flags & ZEND_ACC_STATIC) != 0)) {
return ZEND_DYNAMIC_PROPERTY_OFFSET;
if (EXPECTED(zv != NULL)) {
property_info = (zend_property_info*)Z_PTR_P(zv);
flags = property_info->flags;
- if (UNEXPECTED((flags & ZEND_ACC_SHADOW) != 0)) {
- /* if it's a shadow - go to access it's private */
- property_info = NULL;
- } else {
- if (EXPECTED(zend_verify_property_access(property_info, ce) != 0)) {
- if (UNEXPECTED(!(flags & ZEND_ACC_CHANGED))
- || UNEXPECTED((flags & ZEND_ACC_PRIVATE))) {
- if (UNEXPECTED((flags & ZEND_ACC_STATIC) != 0)) {
- if (!silent) {
- zend_error(E_NOTICE, "Accessing static property %s::$%s as non static", ZSTR_VAL(ce->name), ZSTR_VAL(member));
- }
+
+ if (flags & ZEND_ACC_PUBLIC) {
+ if (!(flags & ZEND_ACC_CHANGED)) {
+no_changed:
+ if (UNEXPECTED((flags & ZEND_ACC_STATIC) != 0)) {
+ if (!silent) {
+ zend_error(E_NOTICE, "Accessing static property %s::$%s as non static", ZSTR_VAL(ce->name), ZSTR_VAL(member));
}
- goto exit;
+ }
+ goto exit;
+ }
+ goto check_scope;
+ } else {
+ if (EG(fake_scope)) {
+ scope = EG(fake_scope);
+ } else {
+ scope = zend_get_executed_scope();
+ }
+ if (flags & ZEND_ACC_PRIVATE) {
+ if (property_info->ce == scope) {
+ goto no_changed;
+ } else if (property_info->ce != ce) {
+ /* if it's a shadow - go to access it's private */
+ property_info = NULL;
+ } else {
+ /* Try to look in the scope instead */
+ property_info = ZEND_WRONG_PROPERTY_INFO;
}
} else {
- /* Try to look in the scope instead */
- property_info = ZEND_WRONG_PROPERTY_INFO;
+ ZEND_ASSERT(flags & ZEND_ACC_PROTECTED);
+ if (zend_check_protected(property_info->ce, scope)) {
+ if (!(flags & ZEND_ACC_CHANGED)) {
+ goto no_changed;
+ }
+ } else {
+ /* Try to look in the scope instead */
+ property_info = ZEND_WRONG_PROPERTY_INFO;
+ }
}
}
- }
-
- if (EG(fake_scope)) {
- scope = EG(fake_scope);
} else {
- scope = zend_get_executed_scope();
+check_scope:
+ 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) {
+ && ((zend_property_info*)Z_PTR_P(zv))->flags & ZEND_ACC_PRIVATE
+ && ((zend_property_info*)Z_PTR_P(zv))->ce == scope) {
property_info = (zend_property_info*)Z_PTR_P(zv);
} else if (UNEXPECTED(property_info == NULL)) {
exit_dynamic:
const char *prop_name;
zend_string *member;
size_t prop_name_len;
+ zend_class_entry *scope;
if (ZSTR_VAL(prop_info_name)[0] == 0) {
zend_unmangle_property_name_ex(prop_info_name, &class_name, &prop_name, &prop_name_len);
member = zend_string_init(prop_name, prop_name_len, 0);
- } else {
- member = zend_string_copy(prop_info_name);
- }
- property_info = zend_get_property_info(zobj->ce, member, 1);
- zend_string_release_ex(member, 0);
- if (property_info == NULL) {
- /* undefined public property */
- if (class_name && class_name[0] != '*') {
- /* we we're looking for a private prop */
+ property_info = zend_get_property_info(zobj->ce, member, 1);
+ zend_string_release_ex(member, 0);
+ if (property_info == NULL) {
+ if (class_name[0] != '*') {
+ /* we we're looking for a private prop */
+ return FAILURE;
+ }
+ return SUCCESS;
+ } else if (property_info == ZEND_WRONG_PROPERTY_INFO) {
return FAILURE;
}
- return SUCCESS;
- } else if (property_info == ZEND_WRONG_PROPERTY_INFO) {
- return FAILURE;
- }
- if (class_name && class_name[0] != '*') {
- if (!(property_info->flags & ZEND_ACC_PRIVATE)) {
- /* we we're looking for a private prop but found a non private one of the same name */
- return FAILURE;
- } else if (strcmp(ZSTR_VAL(prop_info_name)+1, ZSTR_VAL(property_info->name)+1)) {
- /* we we're looking for a private prop but found a private one of the same name but another class */
+ if (class_name[0] != '*') {
+ if (!(property_info->flags & ZEND_ACC_PRIVATE)) {
+ /* we we're looking for a private prop but found a non private one of the same name */
+ return FAILURE;
+ } else if (strcmp(ZSTR_VAL(prop_info_name)+1, ZSTR_VAL(property_info->name)+1)) {
+ /* we we're looking for a private prop but found a private one of the same name but another class */
+ return FAILURE;
+ }
+ } else {
+ ZEND_ASSERT(property_info->flags & ZEND_ACC_PROTECTED);
+ }
+ } else {
+ property_info = zend_get_property_info(zobj->ce, prop_info_name, 1);
+ if (property_info == NULL) {
+ return SUCCESS;
+ } else if (property_info == ZEND_WRONG_PROPERTY_INFO) {
return FAILURE;
}
+ ZEND_ASSERT(property_info->flags & ZEND_ACC_PUBLIC);
}
- return zend_verify_property_access(property_info, zobj->ce) ? SUCCESS : FAILURE;
+ return SUCCESS;
}
/* }}} */
if (constructor) {
if (constructor->op_array.fn_flags & ZEND_ACC_PUBLIC) {
/* No further checks necessary */
- } 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.
- */
+ } else {
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));
- constructor = NULL;
+ 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 != 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));
+ constructor = NULL;
+ }
}
- }
- } else if ((constructor->common.fn_flags & ZEND_ACC_PROTECTED)) {
- /* Ensure that if we're calling a protected function, we're allowed to do so.
- * Constructors only have prototype if they are defined by an interface but
- * it is the compilers responsibility to take care of the prototype.
- */
- 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));
- constructor = NULL;
+ ZEND_ASSERT(constructor->common.fn_flags & ZEND_ACC_PROTECTED);
+ /* Ensure that if we're calling a protected function, we're allowed to do so.
+ * 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), 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));
+ constructor = NULL;
+ }
}
}
}
zend_property_info *prop;
ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
- if(prop->flags & ZEND_ACC_SHADOW) {
+ if ((prop->flags & ZEND_ACC_PRIVATE) && prop->ce != ce) {
count_shadow_props++;
} else if (prop->flags & ZEND_ACC_STATIC) {
count_static_props++;
zend_property_info *prop;
ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
- if ((prop->flags & ZEND_ACC_STATIC) && !(prop->flags & ZEND_ACC_SHADOW)) {
+ if ((prop->flags & ZEND_ACC_STATIC) && (!(prop->flags & ZEND_ACC_PRIVATE) || prop->ce == ce)) {
_property_string(str, prop, NULL, ZSTR_VAL(sub_indent));
}
} ZEND_HASH_FOREACH_END();
zend_property_info *prop;
ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
- if (!(prop->flags & (ZEND_ACC_STATIC|ZEND_ACC_SHADOW))) {
+ if (!(prop->flags & ZEND_ACC_STATIC)
+ && (!(prop->flags & ZEND_ACC_PRIVATE) || prop->ce == ce)) {
_property_string(str, prop, NULL, ZSTR_VAL(sub_indent));
}
} ZEND_HASH_FOREACH_END();
tmp_ce = tmp_ce->parent;
}
- if (tmp_info && !(tmp_info->flags & ZEND_ACC_SHADOW)) { /* found something and it's not a parent's private */
+ if (tmp_info && (!(tmp_info->flags & ZEND_ACC_PRIVATE) || tmp_info->ce == tmp_ce)) { /* found something and it's not a parent's private */
prop = tmp_info;
} else { /* not found, use initial value */
ce = store_ce;
zend_string *key;
ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) {
- if (((prop_info->flags & ZEND_ACC_SHADOW) &&
- prop_info->ce != ce) ||
- ((prop_info->flags & ZEND_ACC_PROTECTED) &&
+ if (((prop_info->flags & ZEND_ACC_PROTECTED) &&
!zend_check_protected(prop_info->ce, ce)) ||
((prop_info->flags & ZEND_ACC_PRIVATE) &&
prop_info->ce != ce)) {
GET_REFLECTION_OBJECT_PTR(ce);
if ((property_info = zend_hash_find_ptr(&ce->properties_info, name)) != NULL) {
- if (property_info->flags & ZEND_ACC_SHADOW) {
+ if ((property_info->flags & ZEND_ACC_PRIVATE) && property_info->ce != ce) {
RETURN_FALSE;
}
RETURN_TRUE;
GET_REFLECTION_OBJECT_PTR(ce);
if ((property_info = zend_hash_find_ptr(&ce->properties_info, name)) != NULL) {
- if ((property_info->flags & ZEND_ACC_SHADOW) == 0) {
+ if (!(property_info->flags & ZEND_ACC_PRIVATE) || property_info->ce == ce) {
reflection_property_factory(ce, name, property_info, return_value);
return;
}
}
ce = ce2;
- if ((property_info = zend_hash_str_find_ptr(&ce->properties_info, str_name, str_name_len)) != NULL && (property_info->flags & ZEND_ACC_SHADOW) == 0) {
+ property_info = zend_hash_str_find_ptr(&ce->properties_info, str_name, str_name_len);
+ if (property_info != NULL
+ && (!(property_info->flags & ZEND_ACC_PRIVATE)
+ || property_info->ce == ce)) {
reflection_property_factory_str(ce, str_name, str_name_len, property_info, return_value);
return;
}
zval *retval = va_arg(args, zval*);
long filter = va_arg(args, long);
- if (pptr->flags & ZEND_ACC_SHADOW) {
+ if ((pptr->flags & ZEND_ACC_PRIVATE) && pptr->ce != ce) {
return 0;
}
/* returns out of this function */
}
- if ((property_info = zend_hash_find_ptr(&ce->properties_info, name)) == NULL || (property_info->flags & ZEND_ACC_SHADOW)) {
+ property_info = zend_hash_find_ptr(&ce->properties_info, name);
+ if (property_info == NULL
+ || ((property_info->flags & ZEND_ACC_PRIVATE)
+ && property_info->ce != ce)) {
/* Check for dynamic properties */
if (property_info == NULL && Z_TYPE_P(classname) == IS_OBJECT && Z_OBJ_HT_P(classname)->get_properties) {
if (zend_hash_exists(Z_OBJ_HT_P(classname)->get_properties(classname), name)) {
ce = tmp_ce = ref->ce;
while (tmp_ce && (tmp_info = zend_hash_find_ptr(&tmp_ce->properties_info, ref->unmangled_name)) != NULL) {
- if (tmp_info->flags & ZEND_ACC_PRIVATE || tmp_info->flags & ZEND_ACC_SHADOW) {
+ if (tmp_info->flags & ZEND_ACC_PRIVATE) {
/* it's a private property, so it can't be inherited */
break;
}