mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Zend: Add ZPP F type check for callables that do not free trampolines
As refetching it with the new FCC API does get tedious
This commit is contained in:
parent
d24f07cbfe
commit
d86314939c
4 changed files with 39 additions and 17 deletions
|
@ -19,6 +19,11 @@ PHP 8.4 INTERNALS UPGRADE NOTES
|
|||
to do this at the call site anymore. Writing the handle should happen after
|
||||
successful registration.
|
||||
|
||||
* ZPP now accepts a F or Z_PARAM_FUNC_NO_TRAMPOLINE_FREE type check.
|
||||
This is identical to the 'f' or Z_PARAM_FUNC type check, except the FCC is
|
||||
always initialized because it doesn't free trampolines.
|
||||
Trampolines MUST be freed using zend_release_fcall_info_cache() or consumed.
|
||||
|
||||
========================
|
||||
2. Build system changes
|
||||
========================
|
||||
|
|
|
@ -981,6 +981,7 @@ static const char *zend_parse_arg_impl(zval *arg, va_list *va, const char **spec
|
|||
}
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
case 'f':
|
||||
{
|
||||
zend_fcall_info *fci = va_arg(*va, zend_fcall_info *);
|
||||
|
@ -995,10 +996,12 @@ 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);
|
||||
if (c == 'f') {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
@ -1109,7 +1112,7 @@ static zend_result zend_parse_va_args(uint32_t num_args, const char *type_spec,
|
|||
case 'o': case 'O':
|
||||
case 'z': case 'Z':
|
||||
case 'C': case 'h':
|
||||
case 'f': case 'A':
|
||||
case 'f': case 'F': case 'A':
|
||||
case 'H': case 'p':
|
||||
case 'S': case 'P':
|
||||
case 'L': case 'n':
|
||||
|
|
|
@ -1794,9 +1794,9 @@ ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *
|
|||
Z_PARAM_DOUBLE_EX(dest, is_null, 1, 0)
|
||||
|
||||
/* old "f" */
|
||||
#define Z_PARAM_FUNC_EX(dest_fci, dest_fcc, check_null, deref) \
|
||||
#define Z_PARAM_FUNC_EX(dest_fci, dest_fcc, check_null, deref, free_trampoline) \
|
||||
Z_PARAM_PROLOGUE(deref, 0); \
|
||||
if (UNEXPECTED(!zend_parse_arg_func(_arg, &dest_fci, &dest_fcc, check_null, &_error))) { \
|
||||
if (UNEXPECTED(!zend_parse_arg_func(_arg, &dest_fci, &dest_fcc, check_null, &_error, free_trampoline))) { \
|
||||
if (!_error) { \
|
||||
_expected_type = check_null ? Z_EXPECTED_FUNC_OR_NULL : Z_EXPECTED_FUNC; \
|
||||
_error_code = ZPP_ERROR_WRONG_ARG; \
|
||||
|
@ -1807,13 +1807,19 @@ ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *
|
|||
} \
|
||||
|
||||
#define Z_PARAM_FUNC(dest_fci, dest_fcc) \
|
||||
Z_PARAM_FUNC_EX(dest_fci, dest_fcc, 0, 0)
|
||||
Z_PARAM_FUNC_EX(dest_fci, dest_fcc, 0, 0, true)
|
||||
|
||||
#define Z_PARAM_FUNC_NO_TRAMPOLINE_FREE(dest_fci, dest_fcc) \
|
||||
Z_PARAM_FUNC_EX(dest_fci, dest_fcc, 0, 0, false)
|
||||
|
||||
#define Z_PARAM_FUNC_OR_NULL(dest_fci, dest_fcc) \
|
||||
Z_PARAM_FUNC_EX(dest_fci, dest_fcc, 1, 0)
|
||||
Z_PARAM_FUNC_EX(dest_fci, dest_fcc, 1, 0, true)
|
||||
|
||||
#define Z_PARAM_FUNC_NO_TRAMPOLINE_FREE_OR_NULL(dest_fci, dest_fcc) \
|
||||
Z_PARAM_FUNC_EX(dest_fci, dest_fcc, 1, 0, false)
|
||||
|
||||
#define Z_PARAM_FUNC_OR_NULL_WITH_ZVAL(dest_fci, dest_fcc, dest_zp) \
|
||||
Z_PARAM_FUNC_EX(dest_fci, dest_fcc, 1, 0) \
|
||||
Z_PARAM_FUNC_EX(dest_fci, dest_fcc, 1, 0, true) \
|
||||
Z_PARAM_GET_PREV_ZVAL(dest_zp)
|
||||
|
||||
/* old "h" */
|
||||
|
@ -2428,7 +2434,7 @@ static zend_always_inline bool zend_parse_arg_resource(zval *arg, zval **dest, b
|
|||
return 1;
|
||||
}
|
||||
|
||||
static zend_always_inline bool zend_parse_arg_func(zval *arg, zend_fcall_info *dest_fci, zend_fcall_info_cache *dest_fcc, bool check_null, char **error)
|
||||
static zend_always_inline bool zend_parse_arg_func(zval *arg, zend_fcall_info *dest_fci, zend_fcall_info_cache *dest_fcc, bool check_null, char **error, bool free_trampoline)
|
||||
{
|
||||
if (check_null && UNEXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
|
||||
dest_fci->size = 0;
|
||||
|
@ -2437,10 +2443,12 @@ static zend_always_inline bool zend_parse_arg_func(zval *arg, zend_fcall_info *d
|
|||
} else if (UNEXPECTED(zend_fcall_info_init(arg, 0, dest_fci, dest_fcc, NULL, error) != SUCCESS)) {
|
||||
return 0;
|
||||
}
|
||||
if (free_trampoline) {
|
||||
/* 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(dest_fcc);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -70,8 +70,14 @@ A - array or object (zval*)
|
|||
b - boolean (bool)
|
||||
C - class (zend_class_entry*)
|
||||
d - double (double)
|
||||
f - function or array containing php method call info (returned as
|
||||
zend_fcall_info and zend_fcall_info_cache)
|
||||
f - PHP callable containing php function/method call info (returned as
|
||||
zend_fcall_info and zend_fcall_info_cache).
|
||||
The FCC may be uninitialized if the callable is a trampoline.
|
||||
F - PHP callable containing php function/method call info (returned as
|
||||
zend_fcall_info and zend_fcall_info_cache).
|
||||
The FCC will *always* be initialized, even if the callable is a trampoline.
|
||||
A trampoline *must* be consumed or released with
|
||||
zend_release_fcall_info_cache().
|
||||
h - array (returned as HashTable*)
|
||||
H - array or HASH_OF(object) (returned as HashTable*)
|
||||
l - long (zend_long)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue