Skip to content

Commit 55e6176

Browse files
committed
Fix GH-13433: Segmentation Fault in zend_class_init_statics when using opcache.preload
This regressed in 9a250cc, 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 2543e61 we can check for IS_INDIRECT to see if it should be persisted or not. Closes GH-13794.
1 parent 9381129 commit 55e6176

File tree

7 files changed

+56
-4
lines changed

7 files changed

+56
-4
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? ????, PHP 8.3.6
44

5+
- Opcache:
6+
. Fixed bug GH-13433 (Segmentation Fault in zend_class_init_statics when
7+
using opcache.preload). (nielsdos)
58

69
28 Mar 2024, PHP 8.3.5RC1
710

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?php
2+
abstract class ParentClass {
3+
use TraitA;
4+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
class TheClass extends ParentClass {
3+
use TraitA;
4+
5+
public function test() {
6+
return self::$non_empty_array;
7+
}
8+
}

ext/opcache/tests/gh13433/TraitA.inc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?php
2+
trait TraitA {
3+
protected static $non_empty_array = ['non-empty'];
4+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--TEST--
2+
GH-13433 (Segmentation Fault in zend_class_init_statics when using opcache.preload)
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.optimization_level=0
7+
opcache.preload={PWD}/preload.inc
8+
--EXTENSIONS--
9+
opcache
10+
--SKIPIF--
11+
<?php
12+
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
13+
?>
14+
--FILE--
15+
<?php
16+
$instance = new TheClass;
17+
var_dump($instance);
18+
var_dump($instance->test());
19+
?>
20+
OK
21+
--EXPECT--
22+
object(TheClass)#1 (0) {
23+
}
24+
array(1) {
25+
[0]=>
26+
string(9) "non-empty"
27+
}
28+
OK

ext/opcache/tests/gh13433/preload.inc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?php
2+
require __DIR__.'/TraitA.inc';
3+
require __DIR__.'/ParentClass.inc';
4+
require __DIR__.'/TheClass.inc';

ext/opcache/zend_persist.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -903,10 +903,11 @@ zend_class_entry *zend_persist_class_entry(zend_class_entry *orig_ce)
903903
ce->default_static_members_table = zend_shared_memdup_free(ce->default_static_members_table, sizeof(zval) * ce->default_static_members_count);
904904

905905
/* Persist only static properties in this class.
906-
* Static properties from parent classes will be handled in class_copy_ctor */
907-
i = (ce->parent && (ce->ce_flags & ZEND_ACC_LINKED)) ? ce->parent->default_static_members_count : 0;
908-
for (; i < ce->default_static_members_count; i++) {
909-
zend_persist_zval(&ce->default_static_members_table[i]);
906+
* Static properties from parent classes will be handled in class_copy_ctor and are marked with IS_INDIRECT */
907+
for (i = 0; i < ce->default_static_members_count; i++) {
908+
if (Z_TYPE(ce->default_static_members_table[i]) != IS_INDIRECT) {
909+
zend_persist_zval(&ce->default_static_members_table[i]);
910+
}
910911
}
911912
if (ce->ce_flags & ZEND_ACC_IMMUTABLE) {
912913
if (ce->ce_flags & ZEND_ACC_LINKED) {

0 commit comments

Comments
 (0)