Skip to content

Commit 13c9336

Browse files
committed
Introduce zend_lookup_function()
1 parent 6930ef5 commit 13c9336

File tree

6 files changed

+81
-75
lines changed

6 files changed

+81
-75
lines changed

Zend/zend_API.c

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3606,32 +3606,11 @@ static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_
36063606
int call_via_handler = 0;
36073607
zend_class_entry *scope;
36083608
zval *zv;
3609-
ALLOCA_FLAG(use_heap)
36103609

36113610
fcc->calling_scope = NULL;
36123611

36133612
if (!ce_org) {
3614-
zend_function *func;
3615-
zend_string *lmname;
3616-
3617-
/* Check if function with given name exists.
3618-
* This may be a compound name that includes namespace name */
3619-
if (UNEXPECTED(Z_STRVAL_P(callable)[0] == '\\')) {
3620-
/* Skip leading \ */
3621-
ZSTR_ALLOCA_ALLOC(lmname, Z_STRLEN_P(callable) - 1, use_heap);
3622-
zend_str_tolower_copy(ZSTR_VAL(lmname), Z_STRVAL_P(callable) + 1, Z_STRLEN_P(callable) - 1);
3623-
func = zend_fetch_function(lmname);
3624-
ZSTR_ALLOCA_FREE(lmname, use_heap);
3625-
} else {
3626-
lmname = Z_STR_P(callable);
3627-
func = zend_fetch_function(lmname);
3628-
if (!func) {
3629-
ZSTR_ALLOCA_ALLOC(lmname, Z_STRLEN_P(callable), use_heap);
3630-
zend_str_tolower_copy(ZSTR_VAL(lmname), Z_STRVAL_P(callable), Z_STRLEN_P(callable));
3631-
func = zend_fetch_function(lmname);
3632-
ZSTR_ALLOCA_FREE(lmname, use_heap);
3633-
}
3634-
}
3613+
zend_function *func = zend_fetch_function(Z_STR_P(callable));
36353614
if (EXPECTED(func != NULL)) {
36363615
fcc->function_handler = func;
36373616
return 1;

Zend/zend_execute.c

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4044,19 +4044,19 @@ static zend_never_inline void ZEND_FASTCALL init_func_run_time_cache(zend_op_arr
40444044

40454045
ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function(zend_string *name) /* {{{ */
40464046
{
4047-
zval *zv = zend_hash_find(EG(function_table), name);
4047+
zend_function *fbc = zend_lookup_function(name);
40484048

4049-
if (EXPECTED(zv != NULL)) {
4050-
zend_function *fbc = Z_FUNC_P(zv);
4049+
if (UNEXPECTED(fbc == NULL)) {
4050+
return NULL;
4051+
}
40514052

4052-
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
4053-
init_func_run_time_cache_i(&fbc->op_array);
4054-
}
4055-
return fbc;
4053+
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
4054+
init_func_run_time_cache_i(&fbc->op_array);
40564055
}
4057-
return NULL;
4056+
return fbc;
40584057
} /* }}} */
40594058

4059+
// TODO Update or drop as this indicates a zend_call_method() without an object...
40604060
ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function_str(const char *name, size_t len) /* {{{ */
40614061
{
40624062
zval *zv = zend_hash_str_find(EG(function_table), name, len);
@@ -4643,7 +4643,6 @@ static void zend_swap_operands(zend_op *op) /* {{{ */
46434643
static zend_never_inline zend_execute_data *zend_init_dynamic_call_string(zend_string *function, uint32_t num_args) /* {{{ */
46444644
{
46454645
zend_function *fbc;
4646-
zval *func;
46474646
zend_class_entry *called_scope;
46484647
zend_string *lcname;
46494648
const char *colon;
@@ -4695,20 +4694,11 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_string(zend_s
46954694
init_func_run_time_cache(&fbc->op_array);
46964695
}
46974696
} else {
4698-
if (ZSTR_VAL(function)[0] == '\\') {
4699-
lcname = zend_string_alloc(ZSTR_LEN(function) - 1, 0);
4700-
zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(function) + 1, ZSTR_LEN(function) - 1);
4701-
} else {
4702-
lcname = zend_string_tolower(function);
4703-
}
4704-
if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) {
4697+
if (UNEXPECTED((fbc = zend_lookup_function(function)) == NULL)) {
47054698
zend_throw_error(NULL, "Call to undefined function %s()", ZSTR_VAL(function));
4706-
zend_string_release_ex(lcname, 0);
47074699
return NULL;
47084700
}
4709-
zend_string_release_ex(lcname, 0);
47104701

4711-
fbc = Z_FUNC_P(func);
47124702
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
47134703
init_func_run_time_cache(&fbc->op_array);
47144704
}

Zend/zend_execute.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value);
4848
ZEND_API void execute_ex(zend_execute_data *execute_data);
4949
ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_value);
5050
ZEND_API bool zend_is_valid_class_name(zend_string *name);
51+
ZEND_API zend_function *zend_lookup_function(zend_string *name);
52+
ZEND_API zend_function *zend_lookup_function_ex(zend_string *name, zend_string *lcname, bool use_autoload);
5153
ZEND_API zend_class_entry *zend_lookup_class(zend_string *name);
5254
ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string *lcname, uint32_t flags);
5355
ZEND_API zend_class_entry *zend_get_called_scope(zend_execute_data *ex);

Zend/zend_execute_API.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,49 @@ static const uint32_t valid_chars[8] = {
11001100
0xffffffff,
11011101
};
11021102

1103+
ZEND_API zend_function *zend_lookup_function_ex(zend_string *name, zend_string *lc_key, bool use_autoload)
1104+
{
1105+
zend_function *fbc = NULL;
1106+
zval *func;
1107+
zend_string *lc_name;
1108+
zend_string *autoload_name;
1109+
1110+
if (lc_key) {
1111+
lc_name = lc_key;
1112+
} else {
1113+
if (name == NULL || !ZSTR_LEN(name)) {
1114+
return NULL;
1115+
}
1116+
1117+
if (ZSTR_VAL(name)[0] == '\\') {
1118+
lc_name = zend_string_alloc(ZSTR_LEN(name) - 1, 0);
1119+
zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
1120+
} else {
1121+
lc_name = zend_string_tolower(name);
1122+
}
1123+
}
1124+
1125+
func = zend_hash_find(EG(function_table), lc_name);
1126+
1127+
if (EXPECTED(func)) {
1128+
if (!lc_key) {
1129+
zend_string_release_ex(lc_name, 0);
1130+
}
1131+
fbc = Z_FUNC_P(func);
1132+
return fbc;
1133+
}
1134+
1135+
if (!lc_key) {
1136+
zend_string_release_ex(lc_name, 0);
1137+
}
1138+
return NULL;
1139+
}
1140+
1141+
ZEND_API zend_function *zend_lookup_function(zend_string *name) /* {{{ */
1142+
{
1143+
return zend_lookup_function_ex(name, NULL, 0);
1144+
}
1145+
11031146
ZEND_API bool zend_is_valid_class_name(zend_string *name) {
11041147
for (size_t i = 0; i < ZSTR_LEN(name); i++) {
11051148
unsigned char c = ZSTR_VAL(name)[i];

Zend/zend_vm_def.h

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3751,17 +3751,16 @@ ZEND_VM_HOT_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
37513751
{
37523752
USE_OPLINE
37533753
zend_function *fbc;
3754-
zval *function_name, *func;
37553754
zend_execute_data *call;
37563755

37573756
fbc = CACHED_PTR(opline->result.num);
37583757
if (UNEXPECTED(fbc == NULL)) {
3759-
function_name = (zval*)RT_CONSTANT(opline, opline->op2);
3760-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(function_name+1));
3761-
if (UNEXPECTED(func == NULL)) {
3758+
zval *function_name = (zval*)RT_CONSTANT(opline, opline->op2);
3759+
/* Fetch lowercase name stored in the next literal slot */
3760+
fbc = zend_lookup_function_ex(Z_STR_P(function_name), Z_STR_P(function_name+1), /* use_autoload */ true);
3761+
if (UNEXPECTED(fbc == NULL)) {
37623762
ZEND_VM_DISPATCH_TO_HELPER(zend_undefined_function_helper);
37633763
}
3764-
fbc = Z_FUNC_P(func);
37653764
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
37663765
init_func_run_time_cache(&fbc->op_array);
37673766
}
@@ -3893,22 +3892,21 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM)
38933892
ZEND_VM_HOT_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
38943893
{
38953894
USE_OPLINE
3896-
zval *func_name;
3897-
zval *func;
38983895
zend_function *fbc;
38993896
zend_execute_data *call;
39003897

39013898
fbc = CACHED_PTR(opline->result.num);
39023899
if (UNEXPECTED(fbc == NULL)) {
3903-
func_name = (zval *)RT_CONSTANT(opline, opline->op2);
3904-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name + 1));
3905-
if (func == NULL) {
3906-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name + 2));
3907-
if (UNEXPECTED(func == NULL)) {
3900+
zval *function_name = (zval *)RT_CONSTANT(opline, opline->op2);
3901+
/* Fetch lowercase name stored in the next literal slot */
3902+
fbc = zend_lookup_function_ex(Z_STR_P(function_name), Z_STR_P(function_name+1), /* use_autoload */ true);
3903+
if (UNEXPECTED(fbc == NULL)) {
3904+
/* Fallback onto global namespace, by fetching the unqualified lowercase name stored in the second literal slot */
3905+
fbc = zend_lookup_function_ex(Z_STR_P(function_name+2), Z_STR_P(function_name+2), /* use_autoload */ true);
3906+
if (fbc == NULL) {
39083907
ZEND_VM_DISPATCH_TO_HELPER(zend_undefined_function_helper);
39093908
}
39103909
}
3911-
fbc = Z_FUNC_P(func);
39123910
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
39133911
init_func_run_time_cache(&fbc->op_array);
39143912
}
@@ -3926,15 +3924,13 @@ ZEND_VM_HOT_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
39263924
ZEND_VM_HOT_HANDLER(61, ZEND_INIT_FCALL, NUM, CONST, NUM|CACHE_SLOT)
39273925
{
39283926
USE_OPLINE
3929-
zval *fname;
3930-
zval *func;
39313927
zend_function *fbc;
39323928
zend_execute_data *call;
39333929

39343930
fbc = CACHED_PTR(opline->result.num);
39353931
if (UNEXPECTED(fbc == NULL)) {
3936-
fname = (zval*)RT_CONSTANT(opline, opline->op2);
3937-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(fname));
3932+
zval *fname = (zval*)RT_CONSTANT(opline, opline->op2);
3933+
zval *func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(fname));
39383934
ZEND_ASSERT(func != NULL && "Function existence must be checked at compile time");
39393935
fbc = Z_FUNC_P(func);
39403936
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {

Zend/zend_vm_execute.h

Lines changed: 13 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)