Some of the safe functions providing wrappers for commonly used syscalls allow specifying an optional parameter (e.g. open, openat, semctl). To access an element from an empty va_list is undefined behaviour. Introduce the macro SAFE_COND_HANDLER that takes over handling the variadicness of such wrappers by selecting the right handler for whether the optional argument has been provided or not.
The intended usage is:
#define SAFE_FN(args, ...) \ SAFE_COND_HANDLER(, ##__VA_ARGS__, \ SAFE_FN_HANDLER_1, \ SAFE_FN_HANLDER_0) ( \ (args), ##__VA_ARGS__ )
Subsequent patches would adapt the relevant SAFE_* macros to avoid the undefined behaviour in the corresponding safe_* functions.
Signed-off-by: Tudor Cretu tudor.cretu@arm.com --- include/tst_safe_vararg_macros.h | 38 ++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 include/tst_safe_vararg_macros.h
diff --git a/include/tst_safe_vararg_macros.h b/include/tst_safe_vararg_macros.h new file mode 100644 index 000000000..09f614f70 --- /dev/null +++ b/include/tst_safe_vararg_macros.h @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022 Arm Ltd. + * + * Internal helpers for macros that handle safe variadic wrappers for + * corresponding safe functions. + * Do not use directly in test programs. + */ + +/* + * Some safe functions are wrappers for syscalls with an optional parameter + * (e.g. open, openat, semctl). To access an element from an empty va_list is + * undefined behaviour. This macro enables handling the variadicness of such + * wrappers by selecting the right handler depending on whether the variadic + * argument has been supplied or not. The intended usage is: + * + * #define SAFE_FN(args, ...) \ + * SAFE_COND_HANDLER(, ##__VA_ARGS__, \ + * SAFE_FN_HANDLER_1, \ + * SAFE_FN_HANLDER_0) ( \ + * (args), ##__VA_ARGS__ + * ) + * + * Where SAFE_FN_HANDLER_0 is the handler used when the optional parameter is + * not specified and SAFE_FN_HANDLER_1 is the handler used otherwise. + * + * The way it works is that SAFE_COND_HANDLER returns the third + * parameter passed. If SAFE_FN is called with a variadic element in __VA_ARGS__, + * then SAFE_COND_HANDLER just returns SAFE_FN_HANDLER_1. If SAFE_FN + * is called with an empty __VA_ARGS__, then the comma before the ‘##’ will be + * deleted and, as a consequence, the macro arguments will get shifted, with + * SAFE_FN_HANLDER_0 becoming the actual third argument. + * + * Note: this macro only handles len(__VA_ARGS__) <= 1. + */ +#define SAFE_COND_HANDLER(empty, cond_arg, SAFE_HELPER, ...) \ + SAFE_HELPER +