Skip to content

Commit 57626b7

Browse files
committed
Fix double autoloading issue in debug builds
1 parent b01e120 commit 57626b7

File tree

4 files changed

+18
-16
lines changed

4 files changed

+18
-16
lines changed

Zend/zend_API.c

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3451,38 +3451,35 @@ ZEND_API void zend_release_fcall_info_cache(zend_fcall_info_cache *fcc) {
34513451
}
34523452
}
34533453

3454-
static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_execute_data *frame, zend_fcall_info_cache *fcc, bool strict_class, char **error) /* {{{ */
3454+
static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_execute_data *frame,
3455+
zend_fcall_info_cache *fcc, bool strict_class, char **error, bool use_autoloader) /* {{{ */
34553456
{
34563457
zend_class_entry *ce_org = fcc->calling_scope;
34573458
bool retval = 0;
34583459
zend_string *mname, *cname;
34593460
zend_string *lmname;
3460-
const char *colon;
3461-
size_t clen;
3461+
const char *colon = zend_memrchr(Z_STRVAL_P(callable), ':', Z_STRLEN_P(callable));
34623462
HashTable *ftable;
3463-
int call_via_handler = 0;
3463+
bool call_via_handler = 0;
34643464
zend_class_entry *scope;
34653465
zval *zv;
34663466

34673467
fcc->calling_scope = NULL;
34683468

3469-
if (!ce_org) {
3470-
zend_function *func = zend_fetch_function(Z_STR_P(callable));
3469+
if (!ce_org && !colon) {
3470+
zend_function *func = zend_fetch_function_ex(Z_STR_P(callable), use_autoloader);
34713471
if (EXPECTED(func != NULL)) {
34723472
fcc->function_handler = func;
34733473
return 1;
34743474
}
34753475
}
34763476

34773477
/* Split name into class/namespace and method/function names */
3478-
if ((colon = zend_memrchr(Z_STRVAL_P(callable), ':', Z_STRLEN_P(callable))) != NULL &&
3479-
colon > Z_STRVAL_P(callable) &&
3480-
*(colon-1) == ':'
3481-
) {
3478+
if (colon && colon > Z_STRVAL_P(callable) && *(colon-1) == ':') {
34823479
size_t mlen;
34833480

34843481
colon--;
3485-
clen = colon - Z_STRVAL_P(callable);
3482+
size_t clen = colon - Z_STRVAL_P(callable);
34863483
mlen = Z_STRLEN_P(callable) - clen - 2;
34873484

34883485
if (colon == Z_STRVAL_P(callable)) {
@@ -3768,7 +3765,7 @@ ZEND_API bool zend_is_callable_at_frame(
37683765
}
37693766

37703767
check_func:
3771-
ret = zend_is_callable_check_func(callable, frame, fcc, strict_class, error);
3768+
ret = zend_is_callable_check_func(callable, frame, fcc, strict_class, error, (check_flags & IS_CALLABLE_CHECK_NO_AUTOLOAD));
37723769
if (fcc == &fcc_local) {
37733770
zend_release_fcall_info_cache(fcc);
37743771
}

Zend/zend_API.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,8 @@ ZEND_API zend_result zend_disable_class(const char *class_name, size_t class_nam
379379
ZEND_API ZEND_COLD void zend_wrong_param_count(void);
380380

381381
#define IS_CALLABLE_CHECK_SYNTAX_ONLY (1<<0)
382+
/* Only used for DEBUG builds where the VM will check if a call should throw, causing double autoloading */
383+
#define IS_CALLABLE_CHECK_NO_AUTOLOAD (2<<0)
382384

383385
ZEND_API void zend_release_fcall_info_cache(zend_fcall_info_cache *fcc);
384386
ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, zend_object *object);

Zend/zend_execute.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,7 +1045,7 @@ static zend_always_inline bool zend_check_type_slow(
10451045
}
10461046

10471047
type_mask = ZEND_TYPE_FULL_MASK(*type);
1048-
if ((type_mask & MAY_BE_CALLABLE) && zend_is_callable(arg, 0, NULL)) {
1048+
if ((type_mask & MAY_BE_CALLABLE) && zend_is_callable(arg, IS_CALLABLE_CHECK_NO_AUTOLOAD, NULL)) {
10491049
return 1;
10501050
}
10511051
if ((type_mask & MAY_BE_ITERABLE) && zend_is_iterable(arg)) {
@@ -3783,9 +3783,9 @@ static zend_never_inline void ZEND_FASTCALL init_func_run_time_cache(zend_op_arr
37833783
}
37843784
/* }}} */
37853785

3786-
ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function(zend_string *name) /* {{{ */
3786+
ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function_ex(zend_string *name, bool use_autoloader) /* {{{ */
37873787
{
3788-
zend_function *fbc = zend_lookup_function(name);
3788+
zend_function *fbc = zend_lookup_function_ex(name, NULL, use_autoloader);
37893789

37903790
if (UNEXPECTED(fbc == NULL)) {
37913791
return NULL;

Zend/zend_execute.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,10 @@ ZEND_API zend_class_entry *zend_fetch_class(zend_string *class_name, int fetch_t
355355
ZEND_API zend_class_entry *zend_fetch_class_with_scope(zend_string *class_name, int fetch_type, zend_class_entry *scope);
356356
ZEND_API zend_class_entry *zend_fetch_class_by_name(zend_string *class_name, zend_string *lcname, int fetch_type);
357357

358-
ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function(zend_string *name);
358+
ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function_ex(zend_string *name, bool use_autoload);
359+
static inline zend_function * zend_fetch_function(zend_string *name) {
360+
return zend_fetch_function_ex(name, true);
361+
}
359362
ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function_str(const char *name, size_t len);
360363
ZEND_API void ZEND_FASTCALL zend_init_func_run_time_cache(zend_op_array *op_array);
361364

0 commit comments

Comments
 (0)