diff options
author | Jack Rosenthal <jrosenth@chromium.org> | 2020-01-10 17:25:12 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-01-14 03:29:50 +0000 |
commit | 284344b78731339c3c00eaf71754a071d3ff637c (patch) | |
tree | 251ff96296a7157116404efe17df5b81b7de79f8 | |
parent | fc6070c975516b8cf8f01e00bda6bf32c74e9809 (diff) | |
download | chrome-ec-284344b78731339c3c00eaf71754a071d3ff637c.tar.gz |
common: make ARRAY_SIZE, ARRAY_BEGIN, ARRAY_END type safe
ARRAY_SIZE (and family) used to allow pointers to be passed to the
macro, which would cause a value of one for the array size. This is a
really easy accidental programming error.
This change causes ARRAY_SIZE and ARRAY_END to divide by zero (using
BUILD_CHECK_INLINE) if a pointer is passed. ARRAY_BEGIN will cause a
BUILD_ASSSERT to fail if a pointer is passed.
BUG=none
BRANCH=none
TEST=buildall
Change-Id: Ibdd0efcc9fc46c43d46f2bd06529cc76df910f2e
Signed-off-by: Jack Rosenthal <jrosenth@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1993915
Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
Reviewed-by: Scott Collyer <scollyer@chromium.org>
-rw-r--r-- | include/compile_time_macros.h | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/include/compile_time_macros.h b/include/compile_time_macros.h index e5c1242f4c..ae6ac267eb 100644 --- a/include/compile_time_macros.h +++ b/include/compile_time_macros.h @@ -21,11 +21,26 @@ */ #define BUILD_CHECK_INLINE(value, cond_true) ((value) / (!!(cond_true))) -/* Number of elements in an array */ -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +/* Check that the value is an array (not a pointer) */ +#define _IS_ARRAY(arr) \ + !__builtin_types_compatible_p(typeof(arr), typeof(&(arr)[0])) + +/** + * ARRAY_SIZE - Number of elements in an array. + * + * This version is type-safe and will not allow pointers, causing a + * compile-time divide by zero error if a pointer is passed. + */ +#define ARRAY_SIZE(arr) \ + BUILD_CHECK_INLINE(sizeof(arr) / sizeof((arr)[0]), _IS_ARRAY(arr)) /* Make for loops that iterate over pointers to array entries more readable */ -#define ARRAY_BEGIN(array) (array) +#define ARRAY_BEGIN(array) \ + ({ \ + BUILD_ASSERT(_IS_ARRAY(array), \ + "ARRAY_BEGIN is only compatible with arrays."); \ + (array); \ + }) #define ARRAY_END(array) ((array) + ARRAY_SIZE(array)) /* Just in case - http://gcc.gnu.org/onlinedocs/gcc/Offsetof.html */ |