Skip to content

Commit 58699ff

Browse files
committed
Fix constant update for shadowed private property
Updating based on the properties info HT will miss private parent properties that have been shadowed in the child class. Instead, perform updating directly on the default properties table. We can't do the same for static properties, because those don't have a convenient way to look up the property type from the property offset. However, I don't believe the problem exists for static properties, because we're always going to be using the property on the class it was declared on, while children only hold INDIRECT references. As such, this should be covered by parent class const updating. Fixes oss-fuzz #35906.
1 parent 62ecf54 commit 58699ff

File tree

2 files changed

+60
-22
lines changed

2 files changed

+60
-22
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Constant updating for shadowed private property
3+
--FILE--
4+
<?php
5+
class Foo {
6+
private $prop = X;
7+
function test() {
8+
var_dump($this->prop);
9+
}
10+
}
11+
12+
class Bar extends Foo {
13+
protected $prop;
14+
}
15+
16+
define('X', 1);
17+
$bar = new Bar;
18+
$bar->test();
19+
20+
?>
21+
--EXPECT--
22+
int(1)

Zend/zend_API.c

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,6 +1213,27 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */
12131213
}
12141214
/* }}} */
12151215

1216+
static zend_result update_property(zval *val, zend_property_info *prop_info) {
1217+
if (ZEND_TYPE_IS_SET(prop_info->type)) {
1218+
zval tmp;
1219+
1220+
ZVAL_COPY(&tmp, val);
1221+
if (UNEXPECTED(zval_update_constant_ex(&tmp, prop_info->ce) != SUCCESS)) {
1222+
zval_ptr_dtor(&tmp);
1223+
return FAILURE;
1224+
}
1225+
/* property initializers must always be evaluated with strict types */;
1226+
if (UNEXPECTED(!zend_verify_property_type(prop_info, &tmp, /* strict */ 1))) {
1227+
zval_ptr_dtor(&tmp);
1228+
return FAILURE;
1229+
}
1230+
zval_ptr_dtor(val);
1231+
ZVAL_COPY_VALUE(val, &tmp);
1232+
return SUCCESS;
1233+
}
1234+
return zval_update_constant_ex(val, prop_info->ce);
1235+
}
1236+
12161237
ZEND_API zend_result zend_update_class_constants(zend_class_entry *class_type) /* {{{ */
12171238
{
12181239
if (!(class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
@@ -1241,33 +1262,28 @@ ZEND_API zend_result zend_update_class_constants(zend_class_entry *class_type) /
12411262
}
12421263
}
12431264

1244-
ZEND_HASH_FOREACH_PTR(&class_type->properties_info, prop_info) {
1245-
if (prop_info->flags & ZEND_ACC_STATIC) {
1246-
val = CE_STATIC_MEMBERS(class_type) + prop_info->offset;
1247-
} else {
1248-
val = (zval*)((char*)class_type->default_properties_table + prop_info->offset - OBJ_PROP_TO_OFFSET(0));
1265+
/* Use the default properties table to also update initializers of private properties
1266+
* that have been shadowed in a child class. */
1267+
for (uint32_t i = 0; i < class_type->default_properties_count; i++) {
1268+
val = &class_type->default_properties_table[i];
1269+
prop_info = class_type->properties_info_table[i];
1270+
if (Z_TYPE_P(val) == IS_CONSTANT_AST
1271+
&& UNEXPECTED(update_property(val, prop_info) != SUCCESS)) {
1272+
return FAILURE;
12491273
}
1250-
if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
1251-
if (ZEND_TYPE_IS_SET(prop_info->type)) {
1252-
zval tmp;
1274+
}
12531275

1254-
ZVAL_COPY(&tmp, val);
1255-
if (UNEXPECTED(zval_update_constant_ex(&tmp, prop_info->ce) != SUCCESS)) {
1256-
zval_ptr_dtor(&tmp);
1257-
return FAILURE;
1258-
}
1259-
/* property initializers must always be evaluated with strict types */;
1260-
if (UNEXPECTED(!zend_verify_property_type(prop_info, &tmp, /* strict */ 1))) {
1261-
zval_ptr_dtor(&tmp);
1276+
if (class_type->default_static_members_count) {
1277+
ZEND_HASH_FOREACH_PTR(&class_type->properties_info, prop_info) {
1278+
if (prop_info->flags & ZEND_ACC_STATIC) {
1279+
val = CE_STATIC_MEMBERS(class_type) + prop_info->offset;
1280+
if (Z_TYPE_P(val) == IS_CONSTANT_AST
1281+
&& UNEXPECTED(update_property(val, prop_info) != SUCCESS)) {
12621282
return FAILURE;
12631283
}
1264-
zval_ptr_dtor(val);
1265-
ZVAL_COPY_VALUE(val, &tmp);
1266-
} else if (UNEXPECTED(zval_update_constant_ex(val, prop_info->ce) != SUCCESS)) {
1267-
return FAILURE;
12681284
}
1269-
}
1270-
} ZEND_HASH_FOREACH_END();
1285+
} ZEND_HASH_FOREACH_END();
1286+
}
12711287

12721288
class_type->ce_flags |= ZEND_ACC_CONSTANTS_UPDATED;
12731289
}

0 commit comments

Comments
 (0)