]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
coverity: Add custom assertion macros for Coverity
authorFilipe Brandenburger <filbranden@google.com>
Wed, 18 Jul 2018 02:43:20 +0000 (19:43 -0700)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 19 Jul 2018 07:07:25 +0000 (09:07 +0200)
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

index d1365f705803e94894afec9d993e21b9c8c33370..7e0f6b4ab562745caa10288e55e79de93e68fe63 100644 (file)
@@ -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))                           \