CMake: finish Clang sanitizer support.

This makes ENABLE_SANITIZERS a proper cached variable, removes some
spurious failures and configures asan/ubsan to die on an error.
This commit is contained in:
whitequark 2016-08-01 05:19:21 +00:00
parent 2fdbabc13c
commit 42d3ec9917
3 changed files with 23 additions and 11 deletions

View File

@ -4,6 +4,8 @@ if echo $TRAVIS_TAG | grep ^v; then BUILD_TYPE=RelWithDebInfo; else BUILD_TYPE=D
mkdir build mkdir build
cd build cd build
cmake -DCMAKE_C_COMPILER=gcc-5 -DCMAKE_CXX_COMPILER=g++-5 \ cmake .. -DCMAKE_C_COMPILER=gcc-5 -DCMAKE_CXX_COMPILER=g++-5 \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE -DENABLE_COVERAGE=ON .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DENABLE_COVERAGE=ON \
-DENABLE_SANITIZERS=ON
make VERBOSE=1 make VERBOSE=1

View File

@ -27,10 +27,12 @@ set(solvespace_VERSION_MAJOR 3)
set(solvespace_VERSION_MINOR 0) set(solvespace_VERSION_MINOR 0)
string(SUBSTRING "${GIT_COMMIT_HASH}" 0 8 solvespace_GIT_HASH) string(SUBSTRING "${GIT_COMMIT_HASH}" 0 8 solvespace_GIT_HASH)
set(ENABLE_TESTS ON CACHE BOOL set(ENABLE_TESTS ON CACHE BOOL
"Whether the test suite will be built and run") "Whether the test suite will be built and run")
set(ENABLE_COVERAGE OFF CACHE BOOL set(ENABLE_COVERAGE OFF CACHE BOOL
"Whether code coverage information will be collected") "Whether code coverage information will be collected")
set(ENABLE_SANITIZERS OFF CACHE BOOL
"Whether to enable Clang's AddressSanitizer and UndefinedBehaviorSanitizer")
if(NOT WIN32 AND NOT APPLE) if(NOT WIN32 AND NOT APPLE)
set(GUI gtk2 CACHE STRING "GUI toolkit to use (one of: gtk2 gtk3)") set(GUI gtk2 CACHE STRING "GUI toolkit to use (one of: gtk2 gtk3)")
@ -58,12 +60,16 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed ${CMAKE_EXE_LINKER_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed ${CMAKE_EXE_LINKER_FLAGS}")
endif() endif()
if(SANITIZE) if(ENABLE_SANITIZE)
if(NOT (CMAKE_C_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")) if(NOT (CMAKE_C_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
message(ERROR "Sanitizers are only available in Clang/Clang++") message(FATAL_ERROR "Sanitizers are only available when using Clang/Clang++")
endif() endif()
set(SANITIZE_FLAGS "-O1 -fno-omit-frame-pointer -fno-optimize-sibling-calls") set(SANITIZE_FLAGS "-O1 -fno-omit-frame-pointer -fno-optimize-sibling-calls")
set(SANITIZE_FLAGS "${SANITIZE_FLAGS} -fsanitize=address,undefined,integer") set(SANITIZE_FLAGS "${SANITIZE_FLAGS} -fsanitize=address,undefined,integer")
set(SANITIZE_FLAGS "${SANITIZE_FLAGS} -fno-sanitize-recover=undefined,integer")
# We assume IEEE floats, which means DIV/0 is defined; but ubsan doesn't do so by default.
set(SANITIZE_FLAGS "${SANITIZE_FLAGS} -fno-sanitize=float-divide-by-zero")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SANITIZE_FLAGS}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SANITIZE_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SANITIZE_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SANITIZE_FLAGS}")
endif() endif()

View File

@ -21,8 +21,8 @@ std::string LoadString(const std::string &name) {
} }
std::string LoadStringFromGzip(const std::string &name) { std::string LoadStringFromGzip(const std::string &name) {
size_t size; size_t deflatedSize;
const void *data = LoadResource(name, &size); const void *data = LoadResource(name, &deflatedSize);
z_stream stream; z_stream stream;
stream.zalloc = Z_NULL; stream.zalloc = Z_NULL;
@ -33,11 +33,15 @@ std::string LoadStringFromGzip(const std::string &name) {
// Extract length mod 2**32 from the gzip trailer. // Extract length mod 2**32 from the gzip trailer.
std::string result; std::string result;
ssassert(size >= 4, "Resource too small to have gzip trailer"); ssassert(deflatedSize >= 4, "Resource too small to have gzip trailer");
result.resize(*(uint32_t *)((uintptr_t)data + size - 4));
// *(uint32_t *) may perform an unaligned access, so do a memcpy.
uint32_t inflatedSize;
memcpy(&inflatedSize, (uint32_t *)((uintptr_t)data + deflatedSize - 4), sizeof(uint32_t));
result.resize(inflatedSize);
stream.next_in = (Bytef *)data; stream.next_in = (Bytef *)data;
stream.avail_in = size; stream.avail_in = deflatedSize;
stream.next_out = (Bytef *)&result[0]; stream.next_out = (Bytef *)&result[0];
stream.avail_out = result.length(); stream.avail_out = result.length();
ssassert(inflate(&stream, Z_NO_FLUSH) == Z_STREAM_END, "Cannot inflate resource"); ssassert(inflate(&stream, Z_NO_FLUSH) == Z_STREAM_END, "Cannot inflate resource");