From d25c238f97529942b71680c67b759b32005a3951 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Sun, 20 Apr 2025 21:20:42 +0200 Subject: [PATCH] basic: Move various macros from assert-util.h to assert-fundamental.h ASSERT_PTR() and friends in assert-fundamental.h make use of assert() and assert_se() which when not building for sd-boot are defined in assert-util.h. Because assert() from glibc is only overridden in assert-util.h, the macros in assert-fundamental.h still end up using the glibc assert. Let's fix this by moving the required macros and related logic to assert-fundamental.h. --- src/basic/assert-util.h | 54 -------------------------- src/basic/macro.h | 3 -- src/boot/meson.build | 1 + src/fundamental/assert-fundamental.h | 57 ++++++++++++++++++++++++++++ src/fundamental/macro-fundamental.h | 3 ++ 5 files changed, 61 insertions(+), 57 deletions(-) diff --git a/src/basic/assert-util.h b/src/basic/assert-util.h index 9383a6bb604..7462e1b2225 100644 --- a/src/basic/assert-util.h +++ b/src/basic/assert-util.h @@ -9,66 +9,12 @@ void log_set_assert_return_is_critical(bool b); bool log_get_assert_return_is_critical(void) _pure_; -_noreturn_ void log_assert_failed(const char *text, const char *file, int line, const char *func); -_noreturn_ void log_assert_failed_unreachable(const char *file, int line, const char *func); void log_assert_failed_return(const char *text, const char *file, int line, const char *func); -#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 void __coverity_check__(int condition) { - if (!condition) - __coverity_panic__(); -} - -static inline int __coverity_check_and_return__(int condition) { - return condition; -} - -#define assert_message_se(expr, message) __coverity_check__(!!(expr)) - -#define assert_log(expr, message) __coverity_check_and_return__(!!(expr)) - -#else /* ! __COVERITY__ */ - -#define assert_message_se(expr, message) \ - do { \ - if (_unlikely_(!(expr))) \ - log_assert_failed(message, PROJECT_FILE, __LINE__, __func__); \ - } while (false) - #define assert_log(expr, message) ((_likely_(expr)) \ ? (true) \ : (log_assert_failed_return(message, PROJECT_FILE, __LINE__, __func__), false)) -#endif /* __COVERITY__ */ - -#define assert_se(expr) assert_message_se(expr, #expr) - -/* We override the glibc assert() here. */ -#undef assert -#ifdef NDEBUG -#define assert(expr) ({ if (!(expr)) __builtin_unreachable(); }) -#else -#define assert(expr) assert_message_se(expr, #expr) -#endif - -#define assert_not_reached() \ - log_assert_failed_unreachable(PROJECT_FILE, __LINE__, __func__) - #define assert_return(expr, r) \ do { \ if (!assert_log(expr, #expr)) \ diff --git a/src/basic/macro.h b/src/basic/macro.h index a022e60e170..4ee1ad4d578 100644 --- a/src/basic/macro.h +++ b/src/basic/macro.h @@ -42,9 +42,6 @@ #error "neither int nor long are four bytes long?!?" #endif -assert_cc(STRLEN(__FILE__) > STRLEN(RELATIVE_SOURCE_PATH) + 1); -#define PROJECT_FILE (&__FILE__[STRLEN(RELATIVE_SOURCE_PATH) + 1]) - static inline uint64_t u64_multiply_safe(uint64_t a, uint64_t b) { if (_unlikely_(a != 0 && b > (UINT64_MAX / a))) return 0; /* overflow */ diff --git a/src/boot/meson.build b/src/boot/meson.build index 52f6350620c..e393ed9d744 100644 --- a/src/boot/meson.build +++ b/src/boot/meson.build @@ -92,6 +92,7 @@ endforeach efi_conf.set_quoted('PROJECT_VERSION', project_major_version) efi_conf.set_quoted('VERSION_TAG', version_tag) efi_conf.set('PROJECT_URL', conf.get('PROJECT_URL')) +efi_conf.set_quoted('RELATIVE_SOURCE_PATH', relative_source_path) if meson.is_cross_build() and get_option('sbat-distro') == 'auto' warning('Auto detection of SBAT information not supported when cross-building, disabling SBAT.') diff --git a/src/fundamental/assert-fundamental.h b/src/fundamental/assert-fundamental.h index 292656aa6b1..0b5c7f21de9 100644 --- a/src/fundamental/assert-fundamental.h +++ b/src/fundamental/assert-fundamental.h @@ -18,6 +18,63 @@ #define assert_not_reached() efi_assert("Code should not be reached", __FILE__, __LINE__, __func__) #endif #define assert_se(expr) ({ _likely_(expr) ? VOID_0 : efi_assert(#expr, __FILE__, __LINE__, __func__); }) +#else + +_noreturn_ void log_assert_failed(const char *text, const char *file, int line, const char *func); +_noreturn_ void log_assert_failed_unreachable(const char *file, int line, const char *func); + +#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 void __coverity_check__(int condition) { + if (!condition) + __coverity_panic__(); +} + +static inline int __coverity_check_and_return__(int condition) { + return condition; +} + +#define assert_message_se(expr, message) __coverity_check__(!!(expr)) + +#define assert_log(expr, message) __coverity_check_and_return__(!!(expr)) + +#else /* ! __COVERITY__ */ + +#define assert_message_se(expr, message) \ + do { \ + if (_unlikely_(!(expr))) \ + log_assert_failed(message, PROJECT_FILE, __LINE__, __func__); \ + } while (false) + +#endif /* __COVERITY__ */ + +#define assert_se(expr) assert_message_se(expr, #expr) + +/* We override the glibc assert() here. */ +#undef assert +#ifdef NDEBUG +#define assert(expr) ({ if (!(expr)) __builtin_unreachable(); }) +#else +#define assert(expr) assert_message_se(expr, #expr) +#endif + +#define assert_not_reached() \ + log_assert_failed_unreachable(PROJECT_FILE, __LINE__, __func__) + #endif /* This passes the argument through after (if asserts are enabled) checking that it is not null. */ diff --git a/src/fundamental/macro-fundamental.h b/src/fundamental/macro-fundamental.h index cab8368c871..dbf0a7d8466 100644 --- a/src/fundamental/macro-fundamental.h +++ b/src/fundamental/macro-fundamental.h @@ -463,3 +463,6 @@ assert_cc(sizeof(dummy_t) == 0); #define PTR_TO_SIZE(p) ((size_t) ((uintptr_t) (p))) #define SIZE_TO_PTR(u) ((void *) ((uintptr_t) (u))) + +assert_cc(STRLEN(__FILE__) > STRLEN(RELATIVE_SOURCE_PATH) + 1); +#define PROJECT_FILE (&__FILE__[STRLEN(RELATIVE_SOURCE_PATH) + 1]) -- 2.47.3