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
|
to do this at the call site anymore. Writing the handle should happen after
|
||||||
successful registration.
|
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
|
2. Build system changes
|
||||||
========================
|
========================
|
||||||
|
|
|
@ -981,6 +981,7 @@ static const char *zend_parse_arg_impl(zval *arg, va_list *va, const char **spec
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'F':
|
||||||
case 'f':
|
case 'f':
|
||||||
{
|
{
|
||||||
zend_fcall_info *fci = va_arg(*va, zend_fcall_info *);
|
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) {
|
if (zend_fcall_info_init(arg, 0, fci, fcc, NULL, &is_callable_error) == SUCCESS) {
|
||||||
ZEND_ASSERT(!is_callable_error);
|
ZEND_ASSERT(!is_callable_error);
|
||||||
/* Release call trampolines: The function may not get called, in which case
|
if (c == 'f') {
|
||||||
* the trampoline will leak. Force it to be refetched during
|
/* Release call trampolines: The function may not get called, in which case
|
||||||
* zend_call_function instead. */
|
* the trampoline will leak. Force it to be refetched during
|
||||||
zend_release_fcall_info_cache(fcc);
|
* zend_call_function instead. */
|
||||||
|
zend_release_fcall_info_cache(fcc);
|
||||||
|
}
|
||||||
break;
|
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 'o': case 'O':
|
||||||
case 'z': case 'Z':
|
case 'z': case 'Z':
|
||||||
case 'C': case 'h':
|
case 'C': case 'h':
|
||||||
case 'f': case 'A':
|
case 'f': case 'F': case 'A':
|
||||||
case 'H': case 'p':
|
case 'H': case 'p':
|
||||||
case 'S': case 'P':
|
case 'S': case 'P':
|
||||||
case 'L': case 'n':
|
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)
|
Z_PARAM_DOUBLE_EX(dest, is_null, 1, 0)
|
||||||
|
|
||||||
/* old "f" */
|
/* 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); \
|
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) { \
|
if (!_error) { \
|
||||||
_expected_type = check_null ? Z_EXPECTED_FUNC_OR_NULL : Z_EXPECTED_FUNC; \
|
_expected_type = check_null ? Z_EXPECTED_FUNC_OR_NULL : Z_EXPECTED_FUNC; \
|
||||||
_error_code = ZPP_ERROR_WRONG_ARG; \
|
_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) \
|
#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) \
|
#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) \
|
#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)
|
Z_PARAM_GET_PREV_ZVAL(dest_zp)
|
||||||
|
|
||||||
/* old "h" */
|
/* old "h" */
|
||||||
|
@ -2428,7 +2434,7 @@ static zend_always_inline bool zend_parse_arg_resource(zval *arg, zval **dest, b
|
||||||
return 1;
|
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)) {
|
if (check_null && UNEXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
|
||||||
dest_fci->size = 0;
|
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)) {
|
} else if (UNEXPECTED(zend_fcall_info_init(arg, 0, dest_fci, dest_fcc, NULL, error) != SUCCESS)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* Release call trampolines: The function may not get called, in which case
|
if (free_trampoline) {
|
||||||
* the trampoline will leak. Force it to be refetched during
|
/* Release call trampolines: The function may not get called, in which case
|
||||||
* zend_call_function instead. */
|
* the trampoline will leak. Force it to be refetched during
|
||||||
zend_release_fcall_info_cache(dest_fcc);
|
* zend_call_function instead. */
|
||||||
|
zend_release_fcall_info_cache(dest_fcc);
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,8 +70,14 @@ A - array or object (zval*)
|
||||||
b - boolean (bool)
|
b - boolean (bool)
|
||||||
C - class (zend_class_entry*)
|
C - class (zend_class_entry*)
|
||||||
d - double (double)
|
d - double (double)
|
||||||
f - function or array containing php method call info (returned as
|
f - PHP callable containing php function/method call info (returned as
|
||||||
zend_fcall_info and zend_fcall_info_cache)
|
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 (returned as HashTable*)
|
||||||
H - array or HASH_OF(object) (returned as HashTable*)
|
H - array or HASH_OF(object) (returned as HashTable*)
|
||||||
l - long (zend_long)
|
l - long (zend_long)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue