Skip to content

Commit bd411a9

Browse files
committed
Introduce zend_lookup_function()
1 parent 6e8f2ba commit bd411a9

File tree

6 files changed

+92
-75
lines changed

6 files changed

+92
-75
lines changed

Zend/zend_API.c

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3545,32 +3545,11 @@ static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_
35453545
int call_via_handler = 0;
35463546
zend_class_entry *scope;
35473547
zval *zv;
3548-
ALLOCA_FLAG(use_heap)
35493548

35503549
fcc->calling_scope = NULL;
35513550

35523551
if (!ce_org) {
3553-
zend_function *func;
3554-
zend_string *lmname;
3555-
3556-
/* Check if function with given name exists.
3557-
* This may be a compound name that includes namespace name */
3558-
if (UNEXPECTED(Z_STRVAL_P(callable)[0] == '\\')) {
3559-
/* Skip leading \ */
3560-
ZSTR_ALLOCA_ALLOC(lmname, Z_STRLEN_P(callable) - 1, use_heap);
3561-
zend_str_tolower_copy(ZSTR_VAL(lmname), Z_STRVAL_P(callable) + 1, Z_STRLEN_P(callable) - 1);
3562-
func = zend_fetch_function(lmname);
3563-
ZSTR_ALLOCA_FREE(lmname, use_heap);
3564-
} else {
3565-
lmname = Z_STR_P(callable);
3566-
func = zend_fetch_function(lmname);
3567-
if (!func) {
3568-
ZSTR_ALLOCA_ALLOC(lmname, Z_STRLEN_P(callable), use_heap);
3569-
zend_str_tolower_copy(ZSTR_VAL(lmname), Z_STRVAL_P(callable), Z_STRLEN_P(callable));
3570-
func = zend_fetch_function(lmname);
3571-
ZSTR_ALLOCA_FREE(lmname, use_heap);
3572-
}
3573-
}
3552+
zend_function *func = zend_fetch_function(Z_STR_P(callable));
35743553
if (EXPECTED(func != NULL)) {
35753554
fcc->function_handler = func;
35763555
return 1;

Zend/zend_execute.c

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

39513951
ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function(zend_string *name) /* {{{ */
39523952
{
3953-
zval *zv = zend_hash_find(EG(function_table), name);
3953+
zend_function *fbc = zend_lookup_function(name);
39543954

3955-
if (EXPECTED(zv != NULL)) {
3956-
zend_function *fbc = Z_FUNC_P(zv);
3955+
if (UNEXPECTED(fbc == NULL)) {
3956+
return NULL;
3957+
}
39573958

3958-
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
3959-
init_func_run_time_cache_i(&fbc->op_array);
3960-
}
3961-
return fbc;
3959+
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
3960+
init_func_run_time_cache_i(&fbc->op_array);
39623961
}
3963-
return NULL;
3962+
return fbc;
39643963
} /* }}} */
39653964

3965+
// TODO Update or drop as this indicates a zend_call_method() without an object...
39663966
ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function_str(const char *name, size_t len) /* {{{ */
39673967
{
39683968
zval *zv = zend_hash_str_find(EG(function_table), name, len);
@@ -4330,7 +4330,6 @@ static void zend_swap_operands(zend_op *op) /* {{{ */
43304330
static zend_never_inline zend_execute_data *zend_init_dynamic_call_string(zend_string *function, uint32_t num_args) /* {{{ */
43314331
{
43324332
zend_function *fbc;
4333-
zval *func;
43344333
zend_class_entry *called_scope;
43354334
zend_string *lcname;
43364335
const char *colon;
@@ -4382,20 +4381,11 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_string(zend_s
43824381
init_func_run_time_cache(&fbc->op_array);
43834382
}
43844383
} else {
4385-
if (ZSTR_VAL(function)[0] == '\\') {
4386-
lcname = zend_string_alloc(ZSTR_LEN(function) - 1, 0);
4387-
zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(function) + 1, ZSTR_LEN(function) - 1);
4388-
} else {
4389-
lcname = zend_string_tolower(function);
4390-
}
4391-
if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) {
4384+
if (UNEXPECTED((fbc = zend_lookup_function(function)) == NULL)) {
43924385
zend_throw_error(NULL, "Call to undefined function %s()", ZSTR_VAL(function));
4393-
zend_string_release_ex(lcname, 0);
43944386
return NULL;
43954387
}
4396-
zend_string_release_ex(lcname, 0);
43974388

4398-
fbc = Z_FUNC_P(func);
43994389
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
44004390
init_func_run_time_cache(&fbc->op_array);
44014391
}

Zend/zend_execute.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value);
4646
ZEND_API void execute_ex(zend_execute_data *execute_data);
4747
ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_value);
4848
ZEND_API bool zend_is_valid_class_name(zend_string *name);
49+
ZEND_API zend_function *zend_lookup_function(zend_string *name);
50+
ZEND_API zend_function *zend_lookup_function_ex(zend_string *name, zend_string *lcname, bool use_autoload);
4951
ZEND_API zend_class_entry *zend_lookup_class(zend_string *name);
5052
ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string *lcname, uint32_t flags);
5153
ZEND_API zend_class_entry *zend_get_called_scope(zend_execute_data *ex);

Zend/zend_execute_API.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,64 @@ static const uint32_t valid_chars[8] = {
10721072
0xffffffff,
10731073
};
10741074

1075+
ZEND_API zend_function *zend_lookup_function_ex(zend_string *name, zend_string *lc_key, bool use_autoload)
1076+
{
1077+
zend_function *fbc = NULL;
1078+
zval *func;
1079+
zend_string *lc_name;
1080+
zend_string *autoload_name;
1081+
1082+
if (lc_key) {
1083+
lc_name = lc_key;
1084+
} else {
1085+
if (name == NULL || !ZSTR_LEN(name)) {
1086+
return NULL;
1087+
}
1088+
1089+
if (ZSTR_VAL(name)[0] == '\\') {
1090+
lc_name = zend_string_alloc(ZSTR_LEN(name) - 1, 0);
1091+
zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
1092+
} else {
1093+
lc_name = zend_string_tolower(name);
1094+
}
1095+
}
1096+
1097+
func = zend_hash_find(EG(function_table), lc_name);
1098+
1099+
if (EXPECTED(func)) {
1100+
if (!lc_key) {
1101+
zend_string_release_ex(lc_name, 0);
1102+
}
1103+
fbc = Z_FUNC_P(func);
1104+
return fbc;
1105+
}
1106+
1107+
/* The compiler is not-reentrant. Make sure we autoload only during run-time. */
1108+
if (!use_autoload || zend_is_compiling()) {
1109+
if (!lc_key) {
1110+
zend_string_release_ex(lc_name, 0);
1111+
}
1112+
return NULL;
1113+
}
1114+
1115+
if (!zend_autoload) {
1116+
if (!lc_key) {
1117+
zend_string_release_ex(lc_name, 0);
1118+
}
1119+
return NULL;
1120+
}
1121+
1122+
if (!lc_key) {
1123+
zend_string_release_ex(lc_name, 0);
1124+
}
1125+
return NULL;
1126+
}
1127+
1128+
ZEND_API zend_function *zend_lookup_function(zend_string *name) /* {{{ */
1129+
{
1130+
return zend_lookup_function_ex(name, NULL, 0);
1131+
}
1132+
10751133
ZEND_API bool zend_is_valid_class_name(zend_string *name) {
10761134
for (size_t i = 0; i < ZSTR_LEN(name); i++) {
10771135
unsigned char c = ZSTR_VAL(name)[i];

Zend/zend_vm_def.h

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3706,17 +3706,16 @@ ZEND_VM_HOT_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
37063706
{
37073707
USE_OPLINE
37083708
zend_function *fbc;
3709-
zval *function_name, *func;
37103709
zend_execute_data *call;
37113710

37123711
fbc = CACHED_PTR(opline->result.num);
37133712
if (UNEXPECTED(fbc == NULL)) {
3714-
function_name = (zval*)RT_CONSTANT(opline, opline->op2);
3715-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(function_name+1));
3716-
if (UNEXPECTED(func == NULL)) {
3713+
zval *function_name = (zval*)RT_CONSTANT(opline, opline->op2);
3714+
fbc = zend_lookup_function(Z_STR_P(function_name+1));
3715+
//fbc = zend_lookup_function(Z_STR_P(function_name));
3716+
if (UNEXPECTED(fbc == NULL)) {
37173717
ZEND_VM_DISPATCH_TO_HELPER(zend_undefined_function_helper);
37183718
}
3719-
fbc = Z_FUNC_P(func);
37203719
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
37213720
init_func_run_time_cache(&fbc->op_array);
37223721
}
@@ -3848,22 +3847,19 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM)
38483847
ZEND_VM_HOT_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
38493848
{
38503849
USE_OPLINE
3851-
zval *func_name;
3852-
zval *func;
38533850
zend_function *fbc;
38543851
zend_execute_data *call;
38553852

38563853
fbc = CACHED_PTR(opline->result.num);
38573854
if (UNEXPECTED(fbc == NULL)) {
3858-
func_name = (zval *)RT_CONSTANT(opline, opline->op2);
3859-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name + 1));
3860-
if (func == NULL) {
3861-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name + 2));
3862-
if (UNEXPECTED(func == NULL)) {
3855+
zval *function_name = (zval *)RT_CONSTANT(opline, opline->op2);
3856+
fbc = zend_lookup_function(Z_STR_P(function_name+1));
3857+
if (fbc == NULL) {
3858+
fbc = zend_lookup_function(Z_STR_P(function_name+2));
3859+
if (fbc == NULL) {
38633860
ZEND_VM_DISPATCH_TO_HELPER(zend_undefined_function_helper);
38643861
}
38653862
}
3866-
fbc = Z_FUNC_P(func);
38673863
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
38683864
init_func_run_time_cache(&fbc->op_array);
38693865
}
@@ -3881,15 +3877,13 @@ ZEND_VM_HOT_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
38813877
ZEND_VM_HOT_HANDLER(61, ZEND_INIT_FCALL, NUM, CONST, NUM|CACHE_SLOT)
38823878
{
38833879
USE_OPLINE
3884-
zval *fname;
3885-
zval *func;
38863880
zend_function *fbc;
38873881
zend_execute_data *call;
38883882

38893883
fbc = CACHED_PTR(opline->result.num);
38903884
if (UNEXPECTED(fbc == NULL)) {
3891-
fname = (zval*)RT_CONSTANT(opline, opline->op2);
3892-
func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(fname));
3885+
zval *fname = (zval*)RT_CONSTANT(opline, opline->op2);
3886+
zval *func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(fname));
38933887
ZEND_ASSERT(func != NULL && "Function existence must be checked at compile time");
38943888
fbc = Z_FUNC_P(func);
38953889
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {

Zend/zend_vm_execute.h

Lines changed: 11 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)