diff --git a/NEWS b/NEWS index d4723eb480e..e24c308c860 100644 --- a/NEWS +++ b/NEWS @@ -29,6 +29,8 @@ PHP NEWS (ilutov) . Fix bug GH-10168, GH-10582 (Various segfaults with destructors and VM return values). (dstogov, nielsdos, ilutov) + . Fix bug GH-10935 (Use of trait doesn't redeclare static property if class + has inherited it from its parent). (ilutov) - Date: . Implement More Appropriate Date/Time Exceptions RFC. (Derick) diff --git a/UPGRADING b/UPGRADING index eff0b3d7016..5c74afb6674 100644 --- a/UPGRADING +++ b/UPGRADING @@ -35,6 +35,10 @@ PHP 8.3 UPGRADE NOTES proc_get_status() to check whether the result was cached. . Zend Max Execution Timers is now enabled by default for ZTS builds on Linux. + . Uses of traits with static properties will now redeclare static properties + inherited from the parent class. This will create a separate static property + storage for the current class. This is analogous to adding the static + property to the class directly without traits. - FFI: . C functions that have a return type of void now return null instead of diff --git a/Zend/tests/gh10935.phpt b/Zend/tests/gh10935.phpt new file mode 100644 index 00000000000..e84a9e5fdd2 --- /dev/null +++ b/Zend/tests/gh10935.phpt @@ -0,0 +1,83 @@ +--TEST-- +GH-1093: Add separate static property through trait if parent already declares it +--FILE-- + +--EXPECT-- +A::$test: A +A::getASelf(): A +A::getAStatic(): A +A::getFooSelf(): A +A::getFooStatic(): A +B::$test: B +B::getASelf(): A +B::getAStatic(): B +B::getBSelf(): B +B::getBStatic(): B +B::getFooSelf(): B +B::getFooStatic(): B +B::getBarSelf(): A +B::getBarStatic(): B diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 028bdebbfb8..5a689408263 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -2377,7 +2377,9 @@ static void zend_do_traits_property_binding(zend_class_entry *ce, zend_class_ent ZSTR_VAL(prop_name), ZSTR_VAL(ce->name)); } - continue; + if (!(flags & ZEND_ACC_STATIC)) { + continue; + } } } diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index cca90bb41e9..d7c2d633391 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -1082,7 +1082,15 @@ void zend_update_parent_ce(zend_class_entry *ce) end = parent->parent ? parent->parent->default_static_members_count : 0; for (; i >= end; i--) { zval *p = &ce->default_static_members_table[i]; - ZVAL_INDIRECT(p, &parent->default_static_members_table[i]); + /* The static property may have been overridden by a trait + * during inheritance. In that case, the property default + * value is replaced by zend_declare_typed_property() at the + * property index of the parent property. Make sure we only + * point to the parent property value if the child value was + * already indirect. */ + if (Z_TYPE_P(p) == IS_INDIRECT) { + ZVAL_INDIRECT(p, &parent->default_static_members_table[i]); + } } parent = parent->parent;