Some safe functions are wrappers around functions with an optional parameter (e.g. open, openat, semctl). To access an element from an empty va_list is undefined behaviour. Introduce the macro SAFE_WRAPPER_COND_HANDLER that handles the variadicness of such wrappers by selecting the right handler for each case.
The intended usage is:
#define SAFE_FN(args, ...) \ SAFE_WRAPPER_COND_HANDLER(, ##__VA_ARGS__, \ SAFE_FN_HANDLER_1, \ SAFE_FN_HANLDER_0) \ ((args), ##__VA_ARGS__)
Subsequent patches would adapt the SAFE_* macros to avoid the undefined behaviour in the safe_* functions.
Signed-off-by: Tudor Cretu tudor.cretu@arm.com --- include/safe_vararg_macros.h | 37 ++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 include/safe_vararg_macros.h
diff --git a/include/safe_vararg_macros.h b/include/safe_vararg_macros.h new file mode 100644 index 000000000..cc95d2dd0 --- /dev/null +++ b/include/safe_vararg_macros.h @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022 Arm Ltd. + * + * Internal helper functions for macros that handle safe wrappers for variadic + * functions. + * Do not use directly in test programs. + */ + +/* + * Some safe functions are wrappers around functions 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 for each case. The intended usage is: + * + * #define SAFE_FN(args, ...) \ + * SAFE_WRAPPER_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 when the optional + * parameter is specified. + * + * The way it works is that SAFE_WRAPPER_COND_HANDLER returns the third + * parameter passed. If SAFE_FN is called with an element in __VA_ARGS__, + * then SAFE_WRAPPER_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 SAFE_FN_HANLDER_0 becomes the third argument. Finally, the chosen + * handler is called with the original arguments. + * + * Note: this macro only handles len(__VA_ARGS__) <= 1. + */ +#define SAFE_WRAPPER_COND_HANDLER(cond_empty_drop, cond_non_empty, SAFE_HELPER, ...) \ + SAFE_HELPER +