build: sanitizers for gcc

GCC also supports sanitizers. GCC doesn't support -fsanitize-blacklist
option though, so replace .asan-blacklist file with no_sanitize_address
function attributes instead.
This commit is contained in:
ii14 2023-03-16 18:13:58 +01:00
parent 995196c614
commit 5bad9afed2
7 changed files with 25 additions and 8 deletions

View File

@ -146,8 +146,10 @@ if((CLANG_ASAN_UBSAN AND CLANG_MSAN)
message(FATAL_ERROR "Sanitizers cannot be enabled simultaneously") message(FATAL_ERROR "Sanitizers cannot be enabled simultaneously")
endif() endif()
if((CLANG_ASAN_UBSAN OR CLANG_MSAN OR CLANG_TSAN) AND NOT CMAKE_C_COMPILER_ID MATCHES "Clang") if(CLANG_ASAN_UBSAN OR CLANG_MSAN OR CLANG_TSAN)
message(FATAL_ERROR "Sanitizers are only supported for Clang") if(NOT CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT CMAKE_C_COMPILER_ID MATCHES "GNU")
message(FATAL_ERROR "Sanitizers are only supported for Clang and GCC")
endif()
endif() endif()
# Place targets in bin/ or lib/ for all build configurations # Place targets in bin/ or lib/ for all build configurations

View File

@ -1,3 +0,0 @@
# multiqueue.h pointer arithmetic is not accepted by asan
fun:multiqueue_node_data
fun:tv_dict_watcher_node_data

View File

@ -803,8 +803,7 @@ if(CLANG_ASAN_UBSAN)
-fno-omit-frame-pointer -fno-omit-frame-pointer
-fno-optimize-sibling-calls -fno-optimize-sibling-calls
-fsanitize=address -fsanitize=address
-fsanitize=undefined -fsanitize=undefined)
-fsanitize-blacklist=${PROJECT_SOURCE_DIR}/src/.asan-blacklist)
target_link_libraries(nvim PRIVATE -fsanitize=address -fsanitize=undefined) target_link_libraries(nvim PRIVATE -fsanitize=address -fsanitize=undefined)
elseif(CLANG_MSAN) elseif(CLANG_MSAN)
message(STATUS "Enabling Clang memory sanitizer for nvim.") message(STATUS "Enabling Clang memory sanitizer for nvim.")

View File

@ -518,13 +518,15 @@ static inline bool tv_get_float_chk(const typval_T *const tv, float_T *const ret
static inline DictWatcher *tv_dict_watcher_node_data(QUEUE *q) static inline DictWatcher *tv_dict_watcher_node_data(QUEUE *q)
REAL_FATTR_NONNULL_ALL REAL_FATTR_NONNULL_RET REAL_FATTR_PURE REAL_FATTR_NONNULL_ALL REAL_FATTR_NONNULL_RET REAL_FATTR_PURE
REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_ALWAYS_INLINE; REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_ALWAYS_INLINE
FUNC_ATTR_NO_SANITIZE_ADDRESS;
/// Compute the `DictWatcher` address from a QUEUE node. /// Compute the `DictWatcher` address from a QUEUE node.
/// ///
/// This only exists for .asan-blacklist (ASAN doesn't handle QUEUE_DATA pointer /// This only exists for .asan-blacklist (ASAN doesn't handle QUEUE_DATA pointer
/// arithmetic). /// arithmetic).
static inline DictWatcher *tv_dict_watcher_node_data(QUEUE *q) static inline DictWatcher *tv_dict_watcher_node_data(QUEUE *q)
FUNC_ATTR_NO_SANITIZE_ADDRESS
{ {
return QUEUE_DATA(q, DictWatcher, node); return QUEUE_DATA(q, DictWatcher, node);
} }

View File

@ -245,6 +245,7 @@ static void multiqueue_push(MultiQueue *this, Event event)
} }
static MultiQueueItem *multiqueue_node_data(QUEUE *q) static MultiQueueItem *multiqueue_node_data(QUEUE *q)
FUNC_ATTR_NO_SANITIZE_ADDRESS
{ {
return QUEUE_DATA(q, MultiQueueItem, node); return QUEUE_DATA(q, MultiQueueItem, node);
} }

View File

@ -99,6 +99,10 @@
# undef FUNC_ATTR_NO_SANITIZE_UNDEFINED # undef FUNC_ATTR_NO_SANITIZE_UNDEFINED
#endif #endif
#ifdef FUNC_ATTR_NO_SANITIZE_ADDRESS
# undef FUNC_ATTR_NO_SANITIZE_ADDRESS
#endif
#ifdef FUNC_ATTR_PRINTF #ifdef FUNC_ATTR_PRINTF
# undef FUNC_ATTR_PRINTF # undef FUNC_ATTR_PRINTF
#endif #endif
@ -139,6 +143,11 @@
# define REAL_FATTR_NO_SANITIZE_UNDEFINED \ # define REAL_FATTR_NO_SANITIZE_UNDEFINED \
__attribute__((no_sanitize("undefined"))) __attribute__((no_sanitize("undefined")))
# endif # endif
# if NVIM_HAS_ATTRIBUTE(no_sanitize_address)
# define REAL_FATTR_NO_SANITIZE_ADDRESS \
__attribute__((no_sanitize_address))
# endif
# endif # endif
// Define attributes that are not defined for this compiler. // Define attributes that are not defined for this compiler.
@ -199,6 +208,10 @@
# define REAL_FATTR_NO_SANITIZE_UNDEFINED # define REAL_FATTR_NO_SANITIZE_UNDEFINED
# endif # endif
# ifndef REAL_FATTR_NO_SANITIZE_ADDRESS
# define REAL_FATTR_NO_SANITIZE_ADDRESS
# endif
# ifndef REAL_FATTR_PRINTF # ifndef REAL_FATTR_PRINTF
# define REAL_FATTR_PRINTF(x, y) # define REAL_FATTR_PRINTF(x, y)
# endif # endif
@ -233,6 +246,7 @@
# define FUNC_ATTR_NONNULL_RET REAL_FATTR_NONNULL_RET # define FUNC_ATTR_NONNULL_RET REAL_FATTR_NONNULL_RET
# define FUNC_ATTR_NORETURN REAL_FATTR_NORETURN # define FUNC_ATTR_NORETURN REAL_FATTR_NORETURN
# define FUNC_ATTR_NO_SANITIZE_UNDEFINED REAL_FATTR_NO_SANITIZE_UNDEFINED # define FUNC_ATTR_NO_SANITIZE_UNDEFINED REAL_FATTR_NO_SANITIZE_UNDEFINED
# define FUNC_ATTR_NO_SANITIZE_ADDRESS REAL_FATTR_NO_SANITIZE_ADDRESS
# define FUNC_ATTR_PRINTF(x, y) REAL_FATTR_PRINTF(x, y) # define FUNC_ATTR_PRINTF(x, y) REAL_FATTR_PRINTF(x, y)
#elif !defined(DO_NOT_DEFINE_EMPTY_ATTRIBUTES) #elif !defined(DO_NOT_DEFINE_EMPTY_ATTRIBUTES)
# define FUNC_ATTR_MALLOC # define FUNC_ATTR_MALLOC
@ -249,5 +263,6 @@
# define FUNC_ATTR_NONNULL_RET # define FUNC_ATTR_NONNULL_RET
# define FUNC_ATTR_NORETURN # define FUNC_ATTR_NORETURN
# define FUNC_ATTR_NO_SANITIZE_UNDEFINED # define FUNC_ATTR_NO_SANITIZE_UNDEFINED
# define FUNC_ATTR_NO_SANITIZE_ADDRESS
# define FUNC_ATTR_PRINTF(x, y) # define FUNC_ATTR_PRINTF(x, y)
#endif #endif

View File

@ -3504,6 +3504,7 @@ set QUESTION FUNC_ATTR_NONNULL_ARG
set QUESTION FUNC_ATTR_NONNULL_RET set QUESTION FUNC_ATTR_NONNULL_RET
set QUESTION FUNC_ATTR_NORETURN set QUESTION FUNC_ATTR_NORETURN
set QUESTION FUNC_ATTR_NO_SANITIZE_UNDEFINED set QUESTION FUNC_ATTR_NO_SANITIZE_UNDEFINED
set QUESTION FUNC_ATTR_NO_SANITIZE_ADDRESS
set QUESTION FUNC_ATTR_PRINTF set QUESTION FUNC_ATTR_PRINTF
set QUESTION FUNC_ATTR_PURE set QUESTION FUNC_ATTR_PURE
set QUESTION FUNC_ATTR_UNUSED set QUESTION FUNC_ATTR_UNUSED