Skip to content

Commit

Permalink
util: add type checking to CONTAINER_OF
Browse files Browse the repository at this point in the history
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 <fabiobaltieri@google.com>
  • Loading branch information
fabiobaltieri committed Aug 29, 2023
1 parent a257e53 commit 1bcd92d
Showing 1 changed file with 27 additions and 2 deletions.
29 changes: 27 additions & 2 deletions include/zephyr/sys/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#define ZEPHYR_INCLUDE_SYS_UTIL_H_

#include <zephyr/sys/util_macro.h>
#include <zephyr/toolchain/common.h>

/* needs to be outside _ASMLANGUAGE so 'true' and 'false' can turn
* into '1' and '0' for asm or linker scripts
Expand Down Expand Up @@ -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
*
Expand All @@ -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.
Expand Down

0 comments on commit 1bcd92d

Please sign in to comment.