Skip to content

Commit be82abb

Browse files
committed
Merge branch 'PHP-8.5'
* PHP-8.5: Fix const expr support in preloading (#22783)
2 parents 417e3d7 + 740d1f5 commit be82abb

6 files changed

Lines changed: 65 additions & 3 deletions

File tree

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
@@ -1139,6 +1139,12 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
11391139
case ZEND_AST_CALL:
11401140
case ZEND_AST_STATIC_CALL:
11411141
{
1142+
// Preloading will attempt to resolve constants but objects can't be stored in shm
1143+
// Aborting here to store the const AST instead
1144+
if (CG(in_compilation)) {
1145+
return FAILURE;
1146+
}
1147+
11421148
zend_function *fptr;
11431149
zend_class_entry *called_scope = NULL;
11441150

Zend/zend_compile.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12037,8 +12037,6 @@ static void zend_compile_const_expr_fcc(zend_ast **ast_ptr)
1203712037
zend_error_noreturn(E_COMPILE_ERROR, "Constant expression contains invalid operations");
1203812038
}
1203912039

12040-
ZEND_MAP_PTR_NEW(((zend_ast_fcc *)*args_ast)->fptr);
12041-
1204212040
switch ((*ast_ptr)->kind) {
1204312041
case ZEND_AST_CALL: {
1204412042
zend_ast *name_ast = (*ast_ptr)->child[0];

ext/opcache/zend_file_cache.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1308,7 +1308,9 @@ static void zend_file_cache_unserialize_ast(zend_ast *ast,
13081308
zend_ast_get_op_array(ast)->op_array = Z_PTR(z);
13091309
} else if (ast->kind == ZEND_AST_CALLABLE_CONVERT) {
13101310
zend_ast_fcc *fcc = (zend_ast_fcc*)ast;
1311-
ZEND_MAP_PTR_NEW(fcc->fptr);
1311+
if (!script->corrupted) {
1312+
ZEND_MAP_PTR_NEW(fcc->fptr);
1313+
}
13121314
if (!IS_UNSERIALIZED(fcc->args)) {
13131315
UNSERIALIZE_PTR(fcc->args);
13141316
zend_file_cache_unserialize_ast(fcc->args, script, buf);

ext/opcache/zend_persist.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,9 @@ static zend_ast *zend_persist_ast(zend_ast *ast)
195195
node = (zend_ast *) copy;
196196
} else if (ast->kind == ZEND_AST_CALLABLE_CONVERT) {
197197
zend_ast_fcc *copy = zend_shared_memdup(ast, sizeof(zend_ast_fcc));
198+
if (!ZCG(current_persistent_script)->corrupted) {
199+
ZEND_MAP_PTR_NEW(copy->fptr);
200+
}
198201
copy->args = zend_persist_ast(copy->args);
199202
node = (zend_ast *) copy;
200203
} else if (zend_ast_is_decl(ast)) {

0 commit comments

Comments
 (0)