Commit a66ffb80fd7 for php.net
commit a66ffb80fd7779dea8928ce6eafbad5932c91529
Author: Gina Peter Banyard <girgias@php.net>
Date: Fri Jul 31 12:42:43 2026 +0100
Zend: move '\' and lowercase handling to zend_fetch_function() (#22966)
Rather than having the logic be repeated over and over at the call sites.
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 33128e4a7e3..714fa156522 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -3830,32 +3830,11 @@ static zend_always_inline bool zend_is_callable_check_func(const zval *callable,
int call_via_handler = 0;
zend_class_entry *scope;
zval *zv;
- ALLOCA_FLAG(use_heap)
fcc->calling_scope = NULL;
if (!ce_org) {
- zend_function *func;
- zend_string *lmname;
-
- /* Check if function with given name exists.
- * This may be a compound name that includes namespace name */
- if (UNEXPECTED(Z_STRVAL_P(callable)[0] == '\\')) {
- /* Skip leading \ */
- ZSTR_ALLOCA_ALLOC(lmname, Z_STRLEN_P(callable) - 1, use_heap);
- zend_str_tolower_copy(ZSTR_VAL(lmname), Z_STRVAL_P(callable) + 1, Z_STRLEN_P(callable) - 1);
- func = zend_fetch_function(lmname);
- ZSTR_ALLOCA_FREE(lmname, use_heap);
- } else {
- lmname = Z_STR_P(callable);
- func = zend_fetch_function(lmname);
- if (!func) {
- ZSTR_ALLOCA_ALLOC(lmname, Z_STRLEN_P(callable), use_heap);
- zend_str_tolower_copy(ZSTR_VAL(lmname), Z_STRVAL_P(callable), Z_STRLEN_P(callable));
- func = zend_fetch_function(lmname);
- ZSTR_ALLOCA_FREE(lmname, use_heap);
- }
- }
+ zend_function *func = zend_fetch_function(Z_STR_P(callable));
if (EXPECTED(func != NULL)) {
fcc->function_handler = func;
return 1;
diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c
index a91f0d2c933..4b070d9d5d5 100644
--- a/Zend/zend_ast.c
+++ b/Zend/zend_ast.c
@@ -1241,15 +1241,16 @@ static zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
if (!fptr) {
zend_string *function_name = zend_ast_get_str(ast->child[0]);
- zend_string *function_name_lc = zend_string_tolower(function_name);
- fptr = zend_fetch_function(function_name_lc);
+ fptr = zend_fetch_function(function_name);
+
+ /* Search for global function of the same name */
if (!fptr && ast->child[0]->attr != ZEND_NAME_FQ) {
- const char *backslash = zend_memrchr(ZSTR_VAL(function_name_lc), '\\', ZSTR_LEN(function_name_lc));
+ const char *backslash = zend_memrchr(ZSTR_VAL(function_name), '\\', ZSTR_LEN(function_name));
if (backslash) {
- fptr = zend_fetch_function_str(backslash + 1, ZSTR_LEN(function_name_lc) - (backslash - ZSTR_VAL(function_name_lc) + 1));
+ fptr = zend_fetch_function_str(backslash + 1, ZSTR_LEN(function_name) - (backslash - ZSTR_VAL(function_name) + 1));
}
}
- zend_string_release(function_name_lc);
+
if (!fptr) {
zend_throw_error(NULL, "Call to undefined function %s()", ZSTR_VAL(function_name));
return FAILURE;
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 91cab1b63d2..bc93aa8892a 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -4498,32 +4498,34 @@ static zend_never_inline void ZEND_FASTCALL init_func_run_time_cache(zend_op_arr
ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function(zend_string *name) /* {{{ */
{
- zval *zv = zend_hash_find(EG(function_table), name);
-
- if (EXPECTED(zv != NULL)) {
- zend_function *fbc = Z_FUNC_P(zv);
+ zend_function *fbc;
+ if (UNEXPECTED(ZSTR_VAL(name)[0] == '\\')) {
+ /* Ignore leading "\" */
+ fbc = zend_hash_str_find_ptr_lc(EG(function_table), ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
+ } else {
+ fbc = zend_hash_find_ptr_lc(EG(function_table), name);
+ }
- if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
- init_func_run_time_cache_i(&fbc->op_array);
- }
- return fbc;
+ if (EXPECTED(fbc && fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
+ init_func_run_time_cache_i(&fbc->op_array);
}
- return NULL;
+ return fbc;
} /* }}} */
ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function_str(const char *name, size_t len) /* {{{ */
{
- const zval *zv = zend_hash_str_find(EG(function_table), name, len);
-
- if (EXPECTED(zv != NULL)) {
- zend_function *fbc = Z_FUNC_P(zv);
+ zend_function *fbc;
+ if (UNEXPECTED(name[0] == '\\')) {
+ /* Ignore leading "\" */
+ fbc = zend_hash_str_find_ptr_lc(EG(function_table), name + 1, len - 1);
+ } else {
+ fbc = zend_hash_str_find_ptr_lc(EG(function_table), name, len);
+ }
- if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
- init_func_run_time_cache_i(&fbc->op_array);
- }
- return fbc;
+ if (EXPECTED(fbc && fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
+ init_func_run_time_cache_i(&fbc->op_array);
}
- return NULL;
+ return fbc;
} /* }}} */
ZEND_API void ZEND_FASTCALL zend_init_func_run_time_cache(zend_op_array *op_array) /* {{{ */
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index 7fa76c121ca..6682346a5b0 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -1684,7 +1684,7 @@ ZEND_METHOD(ReflectionFunction, __construct)
{
zend_object *closure_obj = NULL;
zend_function *fptr;
- zend_string *fname, *lcname;
+ zend_string *fname;
zval *object = ZEND_THIS;
reflection_object *intern = Z_REFLECTION_P(object);
@@ -1696,18 +1696,7 @@ ZEND_METHOD(ReflectionFunction, __construct)
if (closure_obj) {
fptr = (zend_function*)zend_get_closure_method_def(closure_obj);
} else {
- if (UNEXPECTED(ZSTR_VAL(fname)[0] == '\\')) {
- /* Ignore leading "\" */
- ALLOCA_FLAG(use_heap)
- ZSTR_ALLOCA_ALLOC(lcname, ZSTR_LEN(fname) - 1, use_heap);
- zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(fname) + 1, ZSTR_LEN(fname) - 1);
- fptr = zend_fetch_function(lcname);
- ZSTR_ALLOCA_FREE(lcname, use_heap);
- } else {
- lcname = zend_string_tolower(fname);
- fptr = zend_fetch_function(lcname);
- zend_string_release(lcname);
- }
+ fptr = zend_fetch_function(fname);
if (fptr == NULL) {
zend_throw_exception_ex(reflection_exception_ptr, 0,
@@ -2429,19 +2418,7 @@ ZEND_METHOD(ReflectionParameter, __construct)
switch (Z_TYPE_P(reference)) {
case IS_STRING: {
zend_string *fname = Z_STR_P(reference);
- zend_string *lcname;
- if (UNEXPECTED(ZSTR_VAL(fname)[0] == '\\')) {
- /* Ignore leading "\" */
- ALLOCA_FLAG(use_heap)
- ZSTR_ALLOCA_ALLOC(lcname, ZSTR_LEN(fname) - 1, use_heap);
- zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(fname) + 1, ZSTR_LEN(fname) - 1);
- fptr = zend_fetch_function(lcname);
- ZSTR_ALLOCA_FREE(lcname, use_heap);
- } else {
- lcname = zend_string_tolower(fname);
- fptr = zend_fetch_function(lcname);
- zend_string_release(lcname);
- }
+ fptr = zend_fetch_function(fname);
if (!fptr) {
zend_throw_exception_ex(reflection_exception_ptr, 0,
"Function %s() does not exist", Z_STRVAL_P(reference));