Skip to content

Commit d8c4890

Browse files
committed
Merge branch 'PHP-8.4'
* PHP-8.4: Fix phpGH-14082: Segmentation fault on unknown address 0x600000000018 in ext/opcache/jit/zend_jit.c
2 parents 591b324 + 3664f4a commit d8c4890

File tree

3 files changed

+79
-0
lines changed

3 files changed

+79
-0
lines changed

ext/opcache/ZendAccelerator.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757

5858
#ifdef HAVE_JIT
5959
# include "jit/zend_jit.h"
60+
# include "Optimizer/zend_func_info.h"
61+
# include "Optimizer/zend_call_graph.h"
6062
#endif
6163

6264
#ifndef ZEND_WIN32
@@ -4537,6 +4539,39 @@ static void preload_load(size_t orig_map_ptr_static_last)
45374539
}
45384540
}
45394541

4542+
#if HAVE_JIT
4543+
static void zend_accel_clear_call_graph_ptrs(zend_op_array *op_array)
4544+
{
4545+
ZEND_ASSERT(ZEND_USER_CODE(op_array->type));
4546+
zend_func_info *info = ZEND_FUNC_INFO(op_array);
4547+
if (info) {
4548+
info->caller_info = NULL;
4549+
info->callee_info = NULL;
4550+
}
4551+
}
4552+
4553+
static void accel_reset_arena_info(zend_persistent_script *script)
4554+
{
4555+
zend_op_array *op_array;
4556+
zend_class_entry *ce;
4557+
4558+
zend_accel_clear_call_graph_ptrs(&script->script.main_op_array);
4559+
ZEND_HASH_MAP_FOREACH_PTR(&script->script.function_table, op_array) {
4560+
zend_accel_clear_call_graph_ptrs(op_array);
4561+
} ZEND_HASH_FOREACH_END();
4562+
ZEND_HASH_MAP_FOREACH_PTR(&script->script.class_table, ce) {
4563+
ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) {
4564+
if (op_array->scope == ce
4565+
&& op_array->type == ZEND_USER_FUNCTION
4566+
&& !(op_array->fn_flags & ZEND_ACC_ABSTRACT)
4567+
&& !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) {
4568+
zend_accel_clear_call_graph_ptrs(op_array);
4569+
}
4570+
} ZEND_HASH_FOREACH_END();
4571+
} ZEND_HASH_FOREACH_END();
4572+
}
4573+
#endif
4574+
45404575
static zend_result accel_preload(const char *config, bool in_child)
45414576
{
45424577
zend_file_handle file_handle;
@@ -4749,6 +4784,18 @@ static zend_result accel_preload(const char *config, bool in_child)
47494784
} ZEND_HASH_FOREACH_END();
47504785
ZCSG(saved_scripts)[i] = NULL;
47514786

4787+
#if HAVE_JIT
4788+
/* During persisting, the JIT may trigger and fill in the call graph.
4789+
* The call graph info is allocated on the arena which will be gone after preloading.
4790+
* To prevent invalid accesses during normal requests, the arena data should be cleared.
4791+
* This has to be done after all scripts have been persisted because shared op arrays between
4792+
* scripts can change the call graph. */
4793+
accel_reset_arena_info(ZCSG(preload_script));
4794+
for (zend_persistent_script **scripts = ZCSG(saved_scripts); *scripts; scripts++) {
4795+
accel_reset_arena_info(*scripts);
4796+
}
4797+
#endif
4798+
47524799
zend_shared_alloc_save_state();
47534800
accel_interned_strings_save_state();
47544801

ext/opcache/tests/jit/gh14082.phpt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
GH-14082 (Segmentation fault on unknown address 0x600000000018 in ext/opcache/jit/zend_jit.c)
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.jit=1235
7+
opcache.jit_buffer_size=16M
8+
opcache.preload={PWD}/preload_gh14082.inc
9+
--EXTENSIONS--
10+
opcache
11+
--SKIPIF--
12+
<?php
13+
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
14+
?>
15+
--FILE--
16+
<?php
17+
Foo::test();
18+
echo "ok\n";
19+
?>
20+
--EXPECT--
21+
int(1)
22+
int(1)
23+
ok
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
class Foo {
3+
public static function test() {
4+
static $i = 0;
5+
var_dump(++$i);
6+
}
7+
}
8+
9+
Foo::test();

0 commit comments

Comments
 (0)