Added option to enable UndefinedBehaviorSanitizer on Clang and GCC.

This commit is contained in:
Lukáš Hejl 2022-01-28 14:51:34 +01:00
parent 46c827c7fc
commit 5f0fea4d58
5 changed files with 70 additions and 0 deletions

View File

@ -33,6 +33,7 @@ option(SLIC3R_MSVC_COMPILE_PARALLEL "Compile on Visual Studio in parallel" 1)
option(SLIC3R_MSVC_PDB "Generate PDB files on MSVC in Release mode" 1)
option(SLIC3R_PERL_XS "Compile XS Perl module and enable Perl unit and integration tests" 0)
option(SLIC3R_ASAN "Enable ASan on Clang and GCC" 0)
option(SLIC3R_UBSAN "Enable UBSan on Clang and GCC" 0)
# If SLIC3R_FHS is 1 -> SLIC3R_DESKTOP_INTEGRATION is always 0, othrewise variable.
CMAKE_DEPENDENT_OPTION(SLIC3R_DESKTOP_INTEGRATION "Allow perfoming desktop integration during runtime" 1 "NOT SLIC3R_FHS" 0)
@ -271,6 +272,32 @@ if (SLIC3R_ASAN)
endif ()
endif ()
if (SLIC3R_UBSAN)
# Stacktrace for every report is enabled by default. It can be disabled by running PrusaSlicer with "UBSAN_OPTIONS=print_stacktrace=0".
# Define macro SLIC3R_UBSAN to allow detection in the source code if this sanitizer is enabled.
add_compile_definitions(SLIC3R_UBSAN)
# Clang supports much more useful checks than GCC, so when Clang is detected, another checks will be enabled.
# List of what GCC is checking: https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html
# List of what Clang is checking: https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(_ubsan_flags "-fsanitize=undefined,integer")
else ()
set(_ubsan_flags "-fsanitize=undefined")
endif ()
add_compile_options(${_ubsan_flags} -fno-omit-frame-pointer)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${_ubsan_flags}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${_ubsan_flags}")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${_ubsan_flags}")
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lubsan")
endif ()
endif ()
if (APPLE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=partial-availability -Werror=unguarded-availability -Werror=unguarded-availability-new")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=partial-availability -Werror=unguarded-availability -Werror=unguarded-availability-new")

View File

@ -120,6 +120,12 @@ set(_build_cmd ${_build_cmd}
set(_install_cmd ${_build_cmd} --prefix=${_prefix} install)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
# When Clang is used with enabled UndefinedBehaviorSanitizer, it produces "undefined reference to '__muloti4'" when __int128 is used.
# Because of that, UndefinedBehaviorSanitizer is disabled for those functions that use __int128.
list(APPEND _patch_command COMMAND ${PATCH_CMD} ${CMAKE_CURRENT_LIST_DIR}/Boost.patch)
endif ()
ExternalProject_Add(
dep_Boost
URL "https://boostorg.jfrog.io/artifactory/main/release/1.75.0/source/boost_1_75_0.tar.gz"

23
deps/Boost/Boost.patch vendored Normal file
View File

@ -0,0 +1,23 @@
diff -u ../boost_1_75_0-orig/boost/rational.hpp ./boost/rational.hpp
--- ../boost_1_75_0-orig/boost/rational.hpp 2020-12-03 06:02:19.000000000 +0100
+++ ./boost/rational.hpp 2022-01-27 16:02:27.993848905 +0100
@@ -302,6 +302,9 @@
return *this;
}
template <class T>
+ #if defined(__clang__)
+ __attribute__((no_sanitize("undefined")))
+ #endif
BOOST_CXX14_CONSTEXPR typename boost::enable_if_c<rational_detail::is_compatible_integer<T, IntType>::value, rational&>::type operator*= (const T& i)
{
// Avoid overflow and preserve normalization
@@ -311,6 +314,9 @@
return *this;
}
template <class T>
+ #if defined(__clang__)
+ __attribute__((no_sanitize("undefined")))
+ #endif
BOOST_CXX14_CONSTEXPR typename boost::enable_if_c<rational_detail::is_compatible_integer<T, IntType>::value, rational&>::type operator/= (const T& i)
{
// Avoid repeated construction

View File

@ -843,6 +843,15 @@ extern "C" {
}
#endif
#if defined(SLIC3R_UBSAN)
extern "C" {
// Enable printing stacktrace by default. It can be disabled by running PrusaSlicer with "UBSAN_OPTIONS=print_stacktrace=0".
const char *__ubsan_default_options() {
return "print_stacktrace=1";
}
}
#endif
#if defined(_MSC_VER) || defined(__MINGW32__)
extern "C" {
__declspec(dllexport) int __stdcall slic3r_main(int argc, wchar_t **argv)

View File

@ -105,6 +105,11 @@ public:
static inline Int128 multiply(int64_t lhs, int64_t rhs) { return Int128(__int128(lhs) * __int128(rhs)); }
#if defined(__clang__)
// When Clang is used with enabled UndefinedBehaviorSanitizer, it produces "undefined reference to '__muloti4'" when __int128 is used.
// Because of that, UndefinedBehaviorSanitizer is disabled for this function.
__attribute__((no_sanitize("undefined")))
#endif
// Evaluate signum of a 2x2 determinant.
static int sign_determinant_2x2(int64_t a11, int64_t a12, int64_t a21, int64_t a22)
{