Release call trampolines in zpp fcc

When using zpp 'f' or Z_PARAM_FUNC, if the fcc points to a call
trampoline release it immediately and force zend_call_function
to refetch it. This may require additional callability checks
if __call is used, but avoids the need to carefully free fcc
values in all internal functions -- in some cases this is not
simple, as a type error might be triggered by a later argument
in the same zpp call.

This fixes oss-fuzz #25390.

Closes GH-6073.
This commit is contained in:
Nikita Popov 2020-09-04 09:41:27 +02:00
parent c0d6b05b68
commit 2e218180ef
6 changed files with 30 additions and 18 deletions

View file

@ -825,6 +825,10 @@ static const char *zend_parse_arg_impl(zval *arg, va_list *va, const char **spec
if (zend_fcall_info_init(arg, 0, fci, fcc, NULL, &is_callable_error) == SUCCESS) {
ZEND_ASSERT(!is_callable_error);
/* Release call trampolines: The function may not get called, in which case
* the trampoline will leak. Force it to be refetched during
* zend_call_function instead. */
zend_release_fcall_info_cache(fcc);
break;
}
@ -2979,8 +2983,8 @@ ZEND_API void zend_release_fcall_info_cache(zend_fcall_info_cache *fcc) {
zend_string_release_ex(fcc->function_handler->common.function_name, 0);
}
zend_free_trampoline(fcc->function_handler);
fcc->function_handler = NULL;
}
fcc->function_handler = NULL;
}
static zend_always_inline bool zend_is_callable_check_func(int check_flags, zval *callable, zend_execute_data *frame, zend_fcall_info_cache *fcc, bool strict_class, char **error) /* {{{ */