From d9fb7afb4890a93db478616e7bfc639b2129b466 Mon Sep 17 00:00:00 2001 From: Filipe Brandenburger Date: Tue, 17 Jul 2018 19:43:20 -0700 Subject: [PATCH] coverity: Add custom assertion macros for Coverity These custom macros make the expression go through a function, in order to prevent ASSERT_SIDE_EFFECT false positives on our macros such as assert_se() and assert_return() that cannot be disabled and will always evaluate their expressions. This technique has been described and recommended in: https://community.synopsys.com/s/question/0D534000046Yuzb/suppressing-assertsideeffect-for-functions-that-allow-for-sideeffects Tested by doing a local cov-build and uploading the resulting tarball to scan.coverity.com, confirmed that the ASSERT_SIDE_EFFECT false positives were gone. --- src/basic/macro.h | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/basic/macro.h b/src/basic/macro.h index d1365f70580..7e0f6b4ab56 100644 --- a/src/basic/macro.h +++ b/src/basic/macro.h @@ -247,12 +247,48 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) { (__x / __y + !!(__x % __y)); \ }) +#ifdef __COVERITY__ + +/* Use special definitions of assertion macros in order to prevent + * false positives of ASSERT_SIDE_EFFECT on Coverity static analyzer + * for uses of assert_se() and assert_return(). + * + * These definitions make expression go through a (trivial) function + * call to ensure they are not discarded. Also use ! or !! to ensure + * the boolean expressions are seen as such. + * + * This technique has been described and recommended in: + * https://community.synopsys.com/s/question/0D534000046Yuzb/suppressing-assertsideeffect-for-functions-that-allow-for-sideeffects + */ + +extern void __coverity_panic__(void); + +static inline int __coverity_check__(int condition) { + return condition; +} + +#define assert_message_se(expr, message) \ + do { \ + if (__coverity_check__(!(expr))) \ + __coverity_panic__(); \ + } while (false) + +#define assert_log(expr, message) __coverity_check__(!!(expr)) + +#else /* ! __COVERITY__ */ + #define assert_message_se(expr, message) \ do { \ if (_unlikely_(!(expr))) \ log_assert_failed(message, __FILE__, __LINE__, __PRETTY_FUNCTION__); \ } while (false) +#define assert_log(expr, message) ((_likely_(expr)) \ + ? (true) \ + : (log_assert_failed_return(message, __FILE__, __LINE__, __PRETTY_FUNCTION__), false)) + +#endif /* __COVERITY__ */ + #define assert_se(expr) assert_message_se(expr, #expr) /* We override the glibc assert() here. */ @@ -285,10 +321,6 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) { REENABLE_WARNING #endif -#define assert_log(expr, message) ((_likely_(expr)) \ - ? (true) \ - : (log_assert_failed_return(message, __FILE__, __LINE__, __PRETTY_FUNCTION__), false)) - #define assert_return(expr, r) \ do { \ if (!assert_log(expr, #expr)) \ -- 2.39.2