From 5de11d1e34f1150468d176168f17453ecc998aba Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 23 Mar 2024 17:19:54 +0100 Subject: [PATCH] Fix GH-13433: Segmentation Fault in zend_class_init_statics when using opcache.preload This regressed in 9a250cc9d6, which allowed static properties to get overridden by a trait during inheritance. In particular, because of the change to the loop in zend_update_parent_ce(), it's not guaranteed that all indirects are after one another. This means that during persisting the zvals of the static members table, some static properties may be skipped. In case of the test code, this means that the array in the trait will keep referring to the old, new freed, stale value. To solve this, we check the type for IS_INDIRECT, which is the same as what zend_persist_calc() is already doing anyway. Since 2543e61aed we can check for IS_INDIRECT to see if it should be persisted or not. --- ext/opcache/tests/gh13433/ParentClass.inc | 4 +++ ext/opcache/tests/gh13433/TheClass.inc | 8 ++++++ ext/opcache/tests/gh13433/TraitA.inc | 4 +++ ext/opcache/tests/gh13433/gh13433.phpt | 32 +++++++++++++++++++++++ ext/opcache/tests/gh13433/preload.inc | 4 +++ ext/opcache/zend_persist.c | 9 ++++--- 6 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 ext/opcache/tests/gh13433/ParentClass.inc create mode 100644 ext/opcache/tests/gh13433/TheClass.inc create mode 100644 ext/opcache/tests/gh13433/TraitA.inc create mode 100644 ext/opcache/tests/gh13433/gh13433.phpt create mode 100644 ext/opcache/tests/gh13433/preload.inc diff --git a/ext/opcache/tests/gh13433/ParentClass.inc b/ext/opcache/tests/gh13433/ParentClass.inc new file mode 100644 index 0000000000000..540f9f5d6f40c --- /dev/null +++ b/ext/opcache/tests/gh13433/ParentClass.inc @@ -0,0 +1,4 @@ + +--FILE-- +test()); +?> +OK +--EXPECT-- +object(TheClass)#1 (0) { +} +array(1) { + [0]=> + string(9) "non-empty" +} +OK diff --git a/ext/opcache/tests/gh13433/preload.inc b/ext/opcache/tests/gh13433/preload.inc new file mode 100644 index 0000000000000..d73773af1a7a4 --- /dev/null +++ b/ext/opcache/tests/gh13433/preload.inc @@ -0,0 +1,4 @@ +default_static_members_table = zend_shared_memdup_free(ce->default_static_members_table, sizeof(zval) * ce->default_static_members_count); /* Persist only static properties in this class. - * Static properties from parent classes will be handled in class_copy_ctor */ - i = (ce->parent && (ce->ce_flags & ZEND_ACC_LINKED)) ? ce->parent->default_static_members_count : 0; - for (; i < ce->default_static_members_count; i++) { - zend_persist_zval(&ce->default_static_members_table[i]); + * Static properties from parent classes will be handled in class_copy_ctor and are marked with IS_INDIRECT */ + for (i = 0; i < ce->default_static_members_count; i++) { + if (Z_TYPE(ce->default_static_members_table[i]) != IS_INDIRECT) { + zend_persist_zval(&ce->default_static_members_table[i]); + } } if (ce->ce_flags & ZEND_ACC_IMMUTABLE) { if (ce->ce_flags & ZEND_ACC_LINKED) {