From 522427aab08d81d15281c493c1260eaa4d6dc405 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Sun, 27 Aug 2023 23:20:34 +0100 Subject: [PATCH] util: add type checking to CONTAINER_OF Add a SAME_TYPE checking macro and use it to add type validation to CONTAINER_OF. This is inspired by the Linux container_of implementation. The check is inhibited when using C++ as __builtin_types_compatible_p is not available there. Signed-off-by: Fabio Baltieri --- include/zephyr/sys/util.h | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/include/zephyr/sys/util.h b/include/zephyr/sys/util.h index e2c3f9d4fb50665..db5d85eeb41c7c2 100644 --- a/include/zephyr/sys/util.h +++ b/include/zephyr/sys/util.h @@ -15,6 +15,7 @@ #define ZEPHYR_INCLUDE_SYS_UTIL_H_ #include +#include /* needs to be outside _ASMLANGUAGE so 'true' and 'false' can turn * into '1' and '0' for asm or linker scripts @@ -201,6 +202,27 @@ extern "C" { (POINTER_TO_UINT(ptr) - POINTER_TO_UINT(array)) / sizeof((array)[0]); \ }) +/** + * @brief Validate if two entities have a compatible type + * + * @param a the first entity to be compared + * @param a the second entity to be compared + * @return 1 if the two elements are compatible, 0 if they are not + */ +#define SAME_TYPE(a, b) __builtin_types_compatible_p(__typeof__(a), __typeof__(b)) + +/** + * @brief Validate CONTAINER_OF parameters, only applies to C mode. + */ +#ifndef __cplusplus +#define CONTAINER_OF_VALIDATE(ptr, type, field) \ + BUILD_ASSERT(SAME_TYPE(*(ptr), ((type *)0)->field) || \ + SAME_TYPE(*(ptr), void), \ + "pointer type mismatch in CONTAINER_OF"); +#else +#define CONTAINER_OF_VALIDATE(ptr, type, field) +#endif + /** * @brief Get a pointer to a structure containing the element * @@ -222,8 +244,11 @@ extern "C" { * @param field the name of the field within the struct @p ptr points to * @return a pointer to the structure that contains @p ptr */ -#define CONTAINER_OF(ptr, type, field) \ - ((type *)(((char *)(ptr)) - offsetof(type, field))) +#define CONTAINER_OF(ptr, type, field) \ + ({ \ + CONTAINER_OF_VALIDATE(ptr, type, field) \ + ((type *)(((char *)(ptr)) - offsetof(type, field))); \ + }) /** * @brief Value of @p x rounded up to the next multiple of @p align.