summaryrefslogtreecommitdiff
path: root/Zend/zend_builtin_functions.c
diff options
context:
space:
mode:
authorNikita Popov <nikic@php.net>2016-11-22 20:49:12 +0100
committerNikita Popov <nikic@php.net>2016-11-22 20:49:12 +0100
commitdd9ad0940a4230c12aee78bc0f53fa1929881b35 (patch)
treeab8c728911c54f86f3c69e2ae359078f5c66e7f8 /Zend/zend_builtin_functions.c
parentc31396f85ea2c986bb2d828a8321b73d778000dc (diff)
downloadphp-git-dd9ad0940a4230c12aee78bc0f53fa1929881b35.tar.gz
Fix get_class_vars() fast-path/slow-path discrepancies
Normalize to the fast-path behavior. In particular, make sure that the the property visibility check is correct for property names that are formatted like mangled private properties (but are not). This is done by only calling zend_check_property_access() for INDIRECT properties.
Diffstat (limited to 'Zend/zend_builtin_functions.c')
-rw-r--r--Zend/zend_builtin_functions.c66
1 files changed, 39 insertions, 27 deletions
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index 51716a096e..1faf57cf31 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -1231,6 +1231,7 @@ ZEND_FUNCTION(get_object_vars)
HashTable *properties;
zend_string *key;
zend_object *zobj;
+ zend_ulong num_key;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_OBJECT(obj)
@@ -1257,33 +1258,44 @@ ZEND_FUNCTION(get_object_vars)
} else {
array_init_size(return_value, zend_hash_num_elements(properties));
- ZEND_HASH_FOREACH_STR_KEY_VAL_IND(properties, key, value) {
- if (key) {
- if (zend_check_property_access(zobj, key) == SUCCESS) {
- if (Z_ISREF_P(value) && Z_REFCOUNT_P(value) == 1) {
- value = Z_REFVAL_P(value);
- }
- if (Z_REFCOUNTED_P(value)) {
- Z_ADDREF_P(value);
- }
- if (ZSTR_VAL(key)[0] == 0) {
- const char *prop_name, *class_name;
- size_t prop_len;
- zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_len);
- /* We assume here that a mangled property name is never
- * numeric. This is probably a safe assumption, but
- * theoretically someone might write an extension with
- * private, numeric properties. Well, too bad.
- */
- zend_hash_str_add_new(Z_ARRVAL_P(return_value), prop_name, prop_len, value);
- } else {
- zend_ulong num_key;
- if (ZEND_HANDLE_NUMERIC(key, num_key)) {
- zend_hash_index_add_new(Z_ARRVAL_P(return_value), num_key, value);
- } else {
- zend_hash_add_new(Z_ARRVAL_P(return_value), key, value);
- }
- }
+ ZEND_HASH_FOREACH_KEY_VAL(properties, num_key, key, value) {
+ zend_bool unmangle = 0;
+ if (Z_TYPE_P(value) == IS_INDIRECT) {
+ value = Z_INDIRECT_P(value);
+ if (UNEXPECTED(Z_ISUNDEF_P(value))) {
+ continue;
+ }
+
+ ZEND_ASSERT(key);
+ if (zend_check_property_access(zobj, key) == FAILURE) {
+ continue;
+ }
+ unmangle = 1;
+ }
+
+ if (Z_ISREF_P(value) && Z_REFCOUNT_P(value) == 1) {
+ value = Z_REFVAL_P(value);
+ }
+ Z_TRY_ADDREF_P(value);
+
+ if (UNEXPECTED(!key)) {
+ /* This case is only possible due to loopholes, e.g. ArrayObject */
+ zend_hash_index_add(Z_ARRVAL_P(return_value), num_key, value);
+ } else if (unmangle && ZSTR_VAL(key)[0] == 0) {
+ const char *prop_name, *class_name;
+ size_t prop_len;
+ zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_len);
+ /* We assume here that a mangled property name is never
+ * numeric. This is probably a safe assumption, but
+ * theoretically someone might write an extension with
+ * private, numeric properties. Well, too bad.
+ */
+ zend_hash_str_add_new(Z_ARRVAL_P(return_value), prop_name, prop_len, value);
+ } else {
+ if (ZEND_HANDLE_NUMERIC(key, num_key)) {
+ zend_hash_index_add(Z_ARRVAL_P(return_value), num_key, value);
+ } else {
+ zend_hash_add_new(Z_ARRVAL_P(return_value), key, value);
}
}
} ZEND_HASH_FOREACH_END();