Skip to content

Commit 740d1f5

Browse files
authored
Fix const expr support in preloading (#22783)
Preloading will try to evaluate class constants during compilation but evaluated FCCs are objects, which can not be persisted. Apply the same fix as for enums: Fail evaluation when compiling. Preloading will also reset CG(map_ptr_last) after compilation, which results in collisions if map ptrs were allocated during compilation. Move the ZEND_MAP_PTR_NEW() to the persist phase, as a shared map ptr is not necessary before that. Fixes GH-22782.
1 parent 853b89c commit 740d1f5

7 files changed

Lines changed: 72 additions & 4 deletions

File tree

NEWS

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? ????, PHP 8.5.10
44

5+
- Core:
6+
. Fixed bug GH-22782 (Const expr FCC crashes under preloading). (Arnaud)
7+
58
- Date:
69
. Fixed leak on double DatePeriod::__construct() call. (ilutov)
710

@@ -12,6 +15,8 @@ PHP NEWS
1215
- Opcache:
1316
. Fixed GH-22693 (DT_TEXTREL in JIT-generated TLS access on x86_64).
1417
(David Carlier)
18+
. Fixed bug GH-22763 (JIT fails to clear ZREG_TYPE_ONLY after setting reg).
19+
(Arnaud)
1520

1621
- Sockets:
1722
. Fixed socket_set_option() validation error messages for UDP_SEGMENT and
@@ -126,7 +131,7 @@ PHP NEWS
126131
PHP 8.3 and PHP 8.5). (jorgsowa)
127132

128133
- SPL:
129-
. Fix class_parents for classes with leading slash in non-autoload mode.
134+
. Fix class_parents for classes with leading slash in non-autoload mode.
130135
(jorgsowa)
131136
. Ignore leading back-slash in class_parents(), class_implements(), and
132137
class_uses(). (jorgsowa)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
#[Attribute]
4+
class A {
5+
function __construct(public mixed $fn) {}
6+
}
7+
8+
#[A(strlen(...))]
9+
class C {
10+
const CC = strlen(...);
11+
12+
#[A(strlen(...))]
13+
function f($arg = strlen(...)) {
14+
return $arg;
15+
}
16+
}
17+
18+
const CC = strlen(...);
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
GH-22782: FCC preloading
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.enable=1
7+
opcache.enable_cli=1
8+
opcache.optimization_level=-1
9+
opcache.preload={PWD}/gh22782.inc
10+
--SKIPIF--
11+
<?php
12+
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
13+
?>
14+
--FILE--
15+
<?php
16+
17+
echo "# Class const\n";
18+
var_dump((C::CC)('hello'));
19+
echo "# Class attr\n";
20+
var_dump((new ReflectionClass(C::class)->getAttributes(A::class)[0]->newInstance()->fn)('hello'));
21+
echo "# Method attr\n";
22+
var_dump((new ReflectionMethod(C::class, 'f')->getAttributes(A::class)[0]->newInstance()->fn)('hello'));
23+
echo "# Method default value\n";
24+
var_dump((new C()->f())('hello'));
25+
26+
?>
27+
--EXPECT--
28+
# Class const
29+
int(5)
30+
# Class attr
31+
int(5)
32+
# Method attr
33+
int(5)
34+
# Method default value
35+
int(5)

Zend/zend_ast.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,6 +1054,12 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
10541054
case ZEND_AST_CALL:
10551055
case ZEND_AST_STATIC_CALL:
10561056
{
1057+
// Preloading will attempt to resolve constants but objects can't be stored in shm
1058+
// Aborting here to store the const AST instead
1059+
if (CG(in_compilation)) {
1060+
return FAILURE;
1061+
}
1062+
10571063
zend_function *fptr;
10581064
zend_class_entry *called_scope = NULL;
10591065
switch (ast->kind) {

Zend/zend_compile.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11513,7 +11513,6 @@ static void zend_compile_const_expr_fcc(zend_ast **ast_ptr)
1151311513
if ((*args_ast)->kind != ZEND_AST_CALLABLE_CONVERT) {
1151411514
zend_error_noreturn(E_COMPILE_ERROR, "Constant expression contains invalid operations");
1151511515
}
11516-
ZEND_MAP_PTR_NEW(((zend_ast_fcc *)*args_ast)->fptr);
1151711516

1151811517
switch ((*ast_ptr)->kind) {
1151911518
case ZEND_AST_CALL: {

ext/opcache/zend_file_cache.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1303,7 +1303,9 @@ static void zend_file_cache_unserialize_ast(zend_ast *ast,
13031303
zend_ast_get_op_array(ast)->op_array = Z_PTR(z);
13041304
} else if (ast->kind == ZEND_AST_CALLABLE_CONVERT) {
13051305
zend_ast_fcc *fcc = (zend_ast_fcc*)ast;
1306-
ZEND_MAP_PTR_NEW(fcc->fptr);
1306+
if (!script->corrupted) {
1307+
ZEND_MAP_PTR_NEW(fcc->fptr);
1308+
}
13071309
} else if (zend_ast_is_decl(ast)) {
13081310
/* Not implemented. */
13091311
ZEND_UNREACHABLE();
@@ -2109,7 +2111,7 @@ void zend_file_cache_invalidate(zend_string *full_path)
21092111
if (ZCG(accel_directives).file_cache_read_only) {
21102112
return;
21112113
}
2112-
2114+
21132115
char *filename;
21142116

21152117
filename = zend_file_cache_get_bin_file_path(full_path);

ext/opcache/zend_persist.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,9 @@ static zend_ast *zend_persist_ast(zend_ast *ast)
197197
node = (zend_ast *) copy;
198198
} else if (ast->kind == ZEND_AST_CALLABLE_CONVERT) {
199199
zend_ast_fcc *copy = zend_shared_memdup(ast, sizeof(zend_ast_fcc));
200+
if (!ZCG(current_persistent_script)->corrupted) {
201+
ZEND_MAP_PTR_NEW(copy->fptr);
202+
}
200203
node = (zend_ast *) copy;
201204
} else if (zend_ast_is_decl(ast)) {
202205
/* Not implemented. */

0 commit comments

Comments
 (0)