summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--UPGRADING.INTERNALS7
-rw-r--r--Zend/tests/bug70873.phpt2
-rw-r--r--Zend/zend_builtin_functions.c13
-rw-r--r--Zend/zend_compile.h5
-rw-r--r--Zend/zend_inheritance.c50
-rw-r--r--Zend/zend_object_handlers.c241
-rw-r--r--Zend/zend_opcode.c2
-rw-r--r--ext/reflection/php_reflection.c31
-rw-r--r--ext/tidy/tests/027.phpt4
9 files changed, 189 insertions, 166 deletions
diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS
index f28e25aeca..b9126ed387 100644
--- a/UPGRADING.INTERNALS
+++ b/UPGRADING.INTERNALS
@@ -3,7 +3,7 @@ PHP 7.4 INTERNALS UPGRADE NOTES
1. Internal API changes
a. php_sys_symlink() and php_sys_link()
b. zend_lookup_class_ex() and zend_fetch_class_by_name()
- c. Function flags
+ c. Function/property flags
2. Build system changes
a. Unix build system changes
@@ -23,12 +23,15 @@ PHP 7.4 INTERNALS UPGRADE NOTES
changed to accept optional lower-case class name as zend_string*,
instead of zval*.
- c. Function flags changes
+ c. Function/property flags changes
- ZEND_ACC_CTOR and ZEND_ACC_DTOR are removed. It's possible to check if
method is a constructor/destructor using the following condition
(func->commpon.scope->constructor == func).
- ZEND_ACC_IMPLEMENTED_ABSTRACT is removed (it was used only internally
during inheritance).
+ - ZEND_ACC_SHADOW property flag is removed. Instead of creating shadow
+ clone, now we use the same private property_info, and should also
+ check property_info->ce (in the same way as with methods).
========================
2. Build system changes
diff --git a/Zend/tests/bug70873.phpt b/Zend/tests/bug70873.phpt
index 3edb7eac43..aecc0e879b 100644
--- a/Zend/tests/bug70873.phpt
+++ b/Zend/tests/bug70873.phpt
@@ -27,7 +27,7 @@ $b = new C;
$b->bar();
?>
--EXPECTF--
-Fatal error: Uncaught Error: Cannot access property B::$x in %sbug70873.php:%d
+Fatal error: Uncaught Error: Cannot access private property B::$x in %sbug70873.php:%d
Stack trace:
#0 %sbug70873.php(%d): B->bar()
#1 {main}
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index d83169cac8..88c24ba8ae 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -1097,13 +1097,10 @@ static void add_class_vars(zend_class_entry *scope, zend_class_entry *ce, int st
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 != scope) ||
- ((prop_info->flags & ZEND_ACC_PROTECTED) &&
+ if (((prop_info->flags & ZEND_ACC_PROTECTED) &&
!zend_check_protected(prop_info->ce, scope)) ||
((prop_info->flags & ZEND_ACC_PRIVATE) &&
- ce != scope &&
- prop_info->ce != scope)) {
+ prop_info->ce != scope)) {
continue;
}
prop = NULL;
@@ -1403,8 +1400,10 @@ ZEND_FUNCTION(property_exists)
RETURN_NULL();
}
- if ((property_info = zend_hash_find_ptr(&ce->properties_info, property)) != NULL
- && (property_info->flags & ZEND_ACC_SHADOW) == 0) {
+ property_info = zend_hash_find_ptr(&ce->properties_info, property);
+ if (property_info != NULL
+ && (!(property_info->flags & ZEND_ACC_PRIVATE)
+ || property_info->ce == ce)) {
RETURN_TRUE;
}
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index b7f7014281..ba4550579e 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -212,15 +212,12 @@ typedef struct _zend_oparray_context {
#define ZEND_ACC_PROTECTED (1 << 9) /* | X | X | X */
#define ZEND_ACC_PRIVATE (1 << 10) /* | X | X | X */
/* | | | */
-/* TODO: explain the name ??? | | | */
+/* Property or method overrides private one | | | */
#define ZEND_ACC_CHANGED (1 << 11) /* | X | X | */
/* | | | */
/* TODO: used only by ext/reflection ??? | | | */
#define ZEND_ACC_IMPLICIT_PUBLIC (1 << 12) /* | ? | ? | ? */
/* | | | */
-/* Shadow of parent's private method/property | | | */
-#define ZEND_ACC_SHADOW (1 << 17) /* | ? | X | */
-/* | | | */
/* Class Flags (unused: 0, 1, 3, 11-18, 21, 25...) | | | */
/* =========== | | | */
/* | | | */
diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c
index c6a89754c9..eef6c5b3a5 100644
--- a/Zend/zend_inheritance.c
+++ b/Zend/zend_inheritance.c
@@ -31,20 +31,6 @@ static void overridden_ptr_dtor(zval *zv) /* {{{ */
}
/* }}} */
-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);
@@ -171,16 +157,14 @@ static void do_inherit_parent_constructor(zend_class_entry *ce) /* {{{ */
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 "";
}
/* }}} */
@@ -684,7 +668,7 @@ static void do_inherit_property(zend_property_info *parent_info, zend_string *ke
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))) {
@@ -711,20 +695,10 @@ static void do_inherit_property(zend_property_info *parent_info, zend_string *ke
}
}
} 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);
}
@@ -1681,11 +1655,7 @@ static void zend_do_traits_property_binding(zend_class_entry *ce, zend_class_ent
/* 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 {
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c
index 29fd0b29bc..a7a863ff12 100644
--- a/Zend/zend_object_handlers.c
+++ b/Zend/zend_object_handlers.c
@@ -325,22 +325,19 @@ static zend_always_inline int zend_verify_property_access(zend_property_info *pr
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;
}
/* }}} */
@@ -377,39 +374,62 @@ static zend_always_inline uintptr_t zend_get_property_offset(zend_class_entry *c
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;
@@ -457,38 +477,61 @@ ZEND_API zend_property_info *zend_get_property_info(zend_class_entry *ce, zend_s
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:
@@ -519,35 +562,43 @@ ZEND_API int zend_check_property_access(zend_object *zobj, zend_string *prop_inf
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;
}
/* }}} */
@@ -1457,40 +1508,38 @@ ZEND_API zend_function *zend_std_get_constructor(zend_object *zobj) /* {{{ */
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;
+ }
}
}
}
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c
index 46f9508b95..3019174ff2 100644
--- a/Zend/zend_opcode.c
+++ b/Zend/zend_opcode.c
@@ -242,7 +242,7 @@ ZEND_API void destroy_zend_class(zval *zv)
efree(ce->default_static_members_table);
}
ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
- if (prop_info->ce == ce || (prop_info->flags & ZEND_ACC_SHADOW)) {
+ if (prop_info->ce == ce) {
zend_string_release_ex(prop_info->name, 0);
if (prop_info->doc_comment) {
zend_string_release_ex(prop_info->doc_comment, 0);
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index eeb3ac66b8..fbacb9e92e 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -366,7 +366,7 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char
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++;
@@ -380,7 +380,7 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char
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();
@@ -427,7 +427,8 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char
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();
@@ -1242,7 +1243,7 @@ static void reflection_property_factory(zend_class_entry *ce, zend_string *name,
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;
@@ -3764,9 +3765,7 @@ static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value
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)) {
@@ -4220,7 +4219,7 @@ ZEND_METHOD(reflection_class, hasProperty)
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;
@@ -4255,7 +4254,7 @@ ZEND_METHOD(reflection_class, getProperty)
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;
}
@@ -4297,7 +4296,10 @@ ZEND_METHOD(reflection_class, getProperty)
}
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;
}
@@ -4316,7 +4318,7 @@ static int _addproperty(zval *el, int num_args, va_list args, zend_hash_key *has
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;
}
@@ -5278,7 +5280,10 @@ ZEND_METHOD(reflection_property, __construct)
/* 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)) {
@@ -5530,7 +5535,7 @@ ZEND_METHOD(reflection_property, getDeclaringClass)
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;
}
diff --git a/ext/tidy/tests/027.phpt b/ext/tidy/tests/027.phpt
index cd984dd9e7..fb26a70f86 100644
--- a/ext/tidy/tests/027.phpt
+++ b/ext/tidy/tests/027.phpt
@@ -11,7 +11,7 @@ abstract class BaseClass {
private static $tidyconfig;
public function __construct() {
- $this->tidyconfig = array(
+ self::$tidyconfig = array(
'indent' => false,
'clean' => true,
'merge-divs' => false,
@@ -29,7 +29,7 @@ abstract class BaseClass {
$data = "awerawer"; // in my code, $data is downloaded from a site
$tidy = new tidy;
- $tidy->parseString($data, $this->tidyconfig, 'utf8');
+ $tidy->parseString($data, self::$tidyconfig, 'utf8');
$tidy->cleanRepair();
return $tidy;