From 0607b663d39907093c2fc73779d55f8422e9eef9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Fri, 7 Feb 2025 09:36:33 +0100 Subject: [PATCH] Disallow calls to abstract `__call()` / `__callStatic()` (#17719) Fixes php/php-src#17718 --- NEWS | 2 ++ Zend/tests/gh_17718_001.phpt | 17 +++++++++++++++++ Zend/tests/gh_17718_002.phpt | 17 +++++++++++++++++ Zend/zend_object_handlers.c | 6 +++++- 4 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/gh_17718_001.phpt create mode 100644 Zend/tests/gh_17718_002.phpt diff --git a/NEWS b/NEWS index d2508bf5bde..3fed1c61baf 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,8 @@ PHP NEWS . Fixed bug GH-17618 (UnhandledMatchError does not take zend.exception_ignore_args=1 into account). (timwolla) . Fix fallback paths in fast_long_{add,sub}_function. (nielsdos) + . Fixed bug GH-17718 (Calling static methods on an interface that has + `__callStatic` is allowed). (timwolla) - LDAP: . Fixed bug GH-17704 (ldap_search fails when $attributes contains a diff --git a/Zend/tests/gh_17718_001.phpt b/Zend/tests/gh_17718_001.phpt new file mode 100644 index 00000000000..1f5bee961eb --- /dev/null +++ b/Zend/tests/gh_17718_001.phpt @@ -0,0 +1,17 @@ +--TEST-- +GH-17718: Disallow calling abstract `__callStatic()` trampoline on an interface +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Error: Cannot call abstract method Foo::bar() in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/gh_17718_002.phpt b/Zend/tests/gh_17718_002.phpt new file mode 100644 index 00000000000..f3f75fca40f --- /dev/null +++ b/Zend/tests/gh_17718_002.phpt @@ -0,0 +1,17 @@ +--TEST-- +GH-17718: Disallow calling abstract `__callStatic()` trampoline on an abstract class +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Error: Cannot call abstract method Foo::bar() in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 10664cd1181..2576fda51ec 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -1348,7 +1348,7 @@ ZEND_API zend_function *zend_get_call_trampoline_func(const zend_class_entry *ce func->fn_flags = ZEND_ACC_CALL_VIA_TRAMPOLINE | ZEND_ACC_PUBLIC | ZEND_ACC_VARIADIC - | (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE); + | (fbc->common.fn_flags & (ZEND_ACC_RETURN_REFERENCE|ZEND_ACC_ABSTRACT)); if (is_static) { func->fn_flags |= ZEND_ACC_STATIC; } @@ -1541,6 +1541,10 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st if (EXPECTED(fbc)) { if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_ABSTRACT)) { zend_abstract_method_call(fbc); + if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) { + zend_string_release_ex(fbc->common.function_name, 0); + zend_free_trampoline(fbc); + } fbc = NULL; } else if (UNEXPECTED(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT)) { zend_error(E_DEPRECATED,