mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
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.
This commit is contained in:
parent
c31396f85e
commit
dd9ad0940a
3 changed files with 39 additions and 27 deletions
|
@ -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();
|
||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue