Skip to content

Commit 10d912d

Browse files
authored
Fix GH-13712: Segmentation fault for enabled observers when calling trait method of internal trait when opcache is loaded (#13735)
Inherited methods regardless of source must share the original runtime cache. Traits were missed. This adds ZEND_ACC_TRAIT_CLONE to internal functions as well to allow easy distinction of these.
1 parent 6fb8b9d commit 10d912d

File tree

4 files changed

+27
-2
lines changed

4 files changed

+27
-2
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ PHP NEWS
2323
- Opcache:
2424
. Fixed GH-13508 (JITed QM_ASSIGN may be optimized out when op1 is null).
2525
(Arnaud, Dmitry)
26+
. Fixed GH-13712 (Segmentation fault for enabled observers when calling trait
27+
method of internal trait when opcache is loaded). (Bob)
2628

2729
- PDO:
2830
. Fix various PDORow bugs. (Girgias)

Zend/zend_inheritance.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1917,9 +1917,9 @@ static void zend_add_trait_method(zend_class_entry *ce, zend_string *name, zend_
19171917
} else {
19181918
new_fn = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
19191919
memcpy(new_fn, fn, sizeof(zend_op_array));
1920-
new_fn->op_array.fn_flags |= ZEND_ACC_TRAIT_CLONE;
19211920
new_fn->op_array.fn_flags &= ~ZEND_ACC_IMMUTABLE;
19221921
}
1922+
new_fn->common.fn_flags |= ZEND_ACC_TRAIT_CLONE;
19231923

19241924
/* Reassign method name, in case it is an alias. */
19251925
new_fn->common.function_name = name;

ext/opcache/tests/gh13712.phpt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
GH-13712 (Segmentation fault for enabled observers when calling trait method of internal trait when opcache is loaded)
3+
--EXTENSIONS--
4+
opcache
5+
zend_test
6+
--INI--
7+
zend_test.observer.enabled=1
8+
opcache.enable=1
9+
opcache.enable_cli=1
10+
--FILE--
11+
<?php
12+
class Foo {
13+
use _ZendTestTrait;
14+
}
15+
16+
$f = new Foo();
17+
var_dump($f->testMethod());
18+
?>
19+
--EXPECTF--
20+
<!-- init '%s' -->
21+
<!-- init Foo::testMethod() -->
22+
<!-- init var_dump() -->
23+
bool(true)

ext/opcache/zend_persist.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,7 @@ static void zend_persist_class_method(zval *zv, zend_class_entry *ce)
726726
}
727727
// Real dynamically created internal functions like enum methods must have their own run_time_cache pointer. They're always on the same scope as their defining class.
728728
// However, copies - as caused by inheritance of internal methods - must retain the original run_time_cache pointer, shared with the source function.
729-
if (!op_array->scope || op_array->scope == ce) {
729+
if (!op_array->scope || (op_array->scope == ce && !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE))) {
730730
ZEND_MAP_PTR_NEW(op_array->run_time_cache);
731731
}
732732
}

0 commit comments

Comments
 (0)