diff --git a/NEWS b/NEWS index 2248d6a292e4..7a1edbfb4645 100644 --- a/NEWS +++ b/NEWS @@ -37,6 +37,9 @@ PHP NEWS (Jorg Sowa) . Fixed bug GH-25061 ($x = $x - 1 on null is optimized to PRE_DEC). (Lazizbek Ergashev) + . Fixed first-class callables to static methods in trait constant + expressions resolving to the method of the first using class and + bypassing visibility checks. (Jorg Sowa) - CLI: . Fixed bug GH-24697 (PHP_HTTP_PARSER_STRICT build option doesn't work). diff --git a/Zend/tests/first_class_callable/constexpr/trait_scope_001.phpt b/Zend/tests/first_class_callable/constexpr/trait_scope_001.phpt new file mode 100644 index 000000000000..8199b47afa97 --- /dev/null +++ b/Zend/tests/first_class_callable/constexpr/trait_scope_001.phpt @@ -0,0 +1,18 @@ +--TEST-- +FCC for self:: static method in trait default argument is resolved per using class +--FILE-- + +--EXPECT-- +A +B diff --git a/Zend/tests/first_class_callable/constexpr/trait_scope_002.phpt b/Zend/tests/first_class_callable/constexpr/trait_scope_002.phpt new file mode 100644 index 000000000000..5390f6337a52 --- /dev/null +++ b/Zend/tests/first_class_callable/constexpr/trait_scope_002.phpt @@ -0,0 +1,20 @@ +--TEST-- +FCC for parent:: static method in trait default argument is resolved per using class +--FILE-- + +--EXPECT-- +P1 +P2 diff --git a/Zend/tests/first_class_callable/constexpr/trait_scope_003.phpt b/Zend/tests/first_class_callable/constexpr/trait_scope_003.phpt new file mode 100644 index 000000000000..ae63777392ba --- /dev/null +++ b/Zend/tests/first_class_callable/constexpr/trait_scope_003.phpt @@ -0,0 +1,23 @@ +--TEST-- +FCC for self:: static method in trait constant and property default is resolved per using class +--FILE-- +p)(), PHP_EOL; +echo ((new B)->p)(), PHP_EOL; + +?> +--EXPECT-- +A +B +A +B diff --git a/Zend/tests/first_class_callable/constexpr/trait_scope_004.phpt b/Zend/tests/first_class_callable/constexpr/trait_scope_004.phpt new file mode 100644 index 000000000000..da1608e2d918 --- /dev/null +++ b/Zend/tests/first_class_callable/constexpr/trait_scope_004.phpt @@ -0,0 +1,22 @@ +--TEST-- +FCC for self:: private static method in trait default argument does not leak to other using classes +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +A +Error: Call to undefined method B::who() diff --git a/Zend/tests/first_class_callable/constexpr/trait_scope_005.phpt b/Zend/tests/first_class_callable/constexpr/trait_scope_005.phpt new file mode 100644 index 000000000000..50382a449939 --- /dev/null +++ b/Zend/tests/first_class_callable/constexpr/trait_scope_005.phpt @@ -0,0 +1,22 @@ +--TEST-- +FCC for named class private static method in trait default argument checks visibility per using class +--FILE-- +getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +A +Error: Call to private method A::who() from scope B diff --git a/Zend/tests/first_class_callable/constexpr/trait_scope_006.phpt b/Zend/tests/first_class_callable/constexpr/trait_scope_006.phpt new file mode 100644 index 000000000000..4ffb56841caa --- /dev/null +++ b/Zend/tests/first_class_callable/constexpr/trait_scope_006.phpt @@ -0,0 +1,20 @@ +--TEST-- +FCC for named class public static method in trait default argument is shared across using classes +--FILE-- + +--EXPECT-- +A +A +A diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 791bc8c1f233..f7eb7ee05e6e 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -1148,7 +1148,11 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner( } } - ZEND_MAP_PTR_SET(fcc_ast->fptr, fptr); + /* The AST may be shared between scopes (e.g. via traits), so only cache scope-independent results. */ + if ((ast->child[0]->attr >> ZEND_CONST_EXPR_NEW_FETCH_TYPE_SHIFT) == ZEND_FETCH_CLASS_DEFAULT + && (fptr->common.fn_flags & ZEND_ACC_PUBLIC)) { + ZEND_MAP_PTR_SET(fcc_ast->fptr, fptr); + } } break;