Skip to content

Commit dd9ad09

Browse files
committed
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.
1 parent c31396f commit dd9ad09

File tree

3 files changed

+39
-27
lines changed

3 files changed

+39
-27
lines changed

Zend/zend_builtin_functions.c

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,6 +1231,7 @@ ZEND_FUNCTION(get_object_vars)
12311231
HashTable *properties;
12321232
zend_string *key;
12331233
zend_object *zobj;
1234+
zend_ulong num_key;
12341235

12351236
ZEND_PARSE_PARAMETERS_START(1, 1)
12361237
Z_PARAM_OBJECT(obj)
@@ -1257,33 +1258,44 @@ ZEND_FUNCTION(get_object_vars)
12571258
} else {
12581259
array_init_size(return_value, zend_hash_num_elements(properties));
12591260

1260-
ZEND_HASH_FOREACH_STR_KEY_VAL_IND(properties, key, value) {
1261-
if (key) {
1262-
if (zend_check_property_access(zobj, key) == SUCCESS) {
1263-
if (Z_ISREF_P(value) && Z_REFCOUNT_P(value) == 1) {
1264-
value = Z_REFVAL_P(value);
1265-
}
1266-
if (Z_REFCOUNTED_P(value)) {
1267-
Z_ADDREF_P(value);
1268-
}
1269-
if (ZSTR_VAL(key)[0] == 0) {
1270-
const char *prop_name, *class_name;
1271-
size_t prop_len;
1272-
zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_len);
1273-
/* We assume here that a mangled property name is never
1274-
* numeric. This is probably a safe assumption, but
1275-
* theoretically someone might write an extension with
1276-
* private, numeric properties. Well, too bad.
1277-
*/
1278-
zend_hash_str_add_new(Z_ARRVAL_P(return_value), prop_name, prop_len, value);
1279-
} else {
1280-
zend_ulong num_key;
1281-
if (ZEND_HANDLE_NUMERIC(key, num_key)) {
1282-
zend_hash_index_add_new(Z_ARRVAL_P(return_value), num_key, value);
1283-
} else {
1284-
zend_hash_add_new(Z_ARRVAL_P(return_value), key, value);
1285-
}
1286-
}
1261+
ZEND_HASH_FOREACH_KEY_VAL(properties, num_key, key, value) {
1262+
zend_bool unmangle = 0;
1263+
if (Z_TYPE_P(value) == IS_INDIRECT) {
1264+
value = Z_INDIRECT_P(value);
1265+
if (UNEXPECTED(Z_ISUNDEF_P(value))) {
1266+
continue;
1267+
}
1268+
1269+
ZEND_ASSERT(key);
1270+
if (zend_check_property_access(zobj, key) == FAILURE) {
1271+
continue;
1272+
}
1273+
unmangle = 1;
1274+
}
1275+
1276+
if (Z_ISREF_P(value) && Z_REFCOUNT_P(value) == 1) {
1277+
value = Z_REFVAL_P(value);
1278+
}
1279+
Z_TRY_ADDREF_P(value);
1280+
1281+
if (UNEXPECTED(!key)) {
1282+
/* This case is only possible due to loopholes, e.g. ArrayObject */
1283+
zend_hash_index_add(Z_ARRVAL_P(return_value), num_key, value);
1284+
} else if (unmangle && ZSTR_VAL(key)[0] == 0) {
1285+
const char *prop_name, *class_name;
1286+
size_t prop_len;
1287+
zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_len);
1288+
/* We assume here that a mangled property name is never
1289+
* numeric. This is probably a safe assumption, but
1290+
* theoretically someone might write an extension with
1291+
* private, numeric properties. Well, too bad.
1292+
*/
1293+
zend_hash_str_add_new(Z_ARRVAL_P(return_value), prop_name, prop_len, value);
1294+
} else {
1295+
if (ZEND_HANDLE_NUMERIC(key, num_key)) {
1296+
zend_hash_index_add(Z_ARRVAL_P(return_value), num_key, value);
1297+
} else {
1298+
zend_hash_add_new(Z_ARRVAL_P(return_value), key, value);
12871299
}
12881300
}
12891301
} ZEND_HASH_FOREACH_END();
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)