]> git.ipfire.org Git - thirdparty/zlib-ng.git/commitdiff
Separate sanitizers so they can be run independently.
authorNathan Moinvaziri <nathan@nathanm.com>
Sun, 22 Nov 2020 22:28:12 +0000 (14:28 -0800)
committerHans Kristian Rosbach <hk-github@circlestorm.org>
Sat, 12 Dec 2020 09:17:44 +0000 (10:17 +0100)
.github/workflows/cmake.yml
CMakeLists.txt
README.md
cmake/detect-sanitizer.cmake
configure

index 66aee306f7aa599e1903704642a1e2f42ce106c9..48d1e6c29b0c9166874e74145e90dd7856743997 100644 (file)
@@ -11,13 +11,13 @@ jobs:
           - name: Ubuntu GCC
             os: ubuntu-latest
             compiler: gcc
-            cmake-args: -DWITH_SANITIZERS=ON
+            cmake-args: -DWITH_SANITIZER=Address
             codecov: ubuntu_gcc
 
           - name: Ubuntu GCC OSB -O1 No Unaligned64
             os: ubuntu-latest
             compiler: gcc
-            cmake-args: -DWITH_SANITIZERS=ON -DWITH_UNALIGNED=ON -DUNALIGNED64_OK=OFF
+            cmake-args: -DWITH_UNALIGNED=ON -DUNALIGNED64_OK=OFF -DWITH_SANITIZER=Undefined
             build-dir: ../build
             build-src-dir: ../zlib-ng
             codecov: ubuntu_gcc_osb
@@ -26,7 +26,7 @@ jobs:
           - name: Ubuntu GCC -O3 No Unaligned
             os: ubuntu-latest
             compiler: gcc
-            cmake-args: -DWITH_SANITIZERS=ON -DWITH_UNALIGNED=OFF
+            cmake-args: -DWITH_UNALIGNED=OFF
             codecov: ubuntu_gcc_o3
             cflags: -O3
 
@@ -38,80 +38,80 @@ jobs:
           - name: Ubuntu GCC No AVX2
             os: ubuntu-latest
             compiler: gcc
-            cmake-args: -DWITH_SANITIZERS=ON -DWITH_AVX2=OFF
+            cmake-args: -DWITH_AVX2=OFF -DWITH_SANITIZER=Undefined
             codecov: ubuntu_gcc_no_avx2
 
           - name: Ubuntu GCC No SSE2
             os: ubuntu-latest
             compiler: gcc
-            cmake-args: -DWITH_SANITIZERS=ON -DWITH_SSE2=OFF
+            cmake-args: -DWITH_SSE2=OFF -DWITH_SANITIZER=Undefined
             codecov: ubuntu_gcc_no_sse2
 
           - name: Ubuntu GCC No SSE4
             os: ubuntu-latest
             compiler: gcc
-            cmake-args: -DWITH_SANITIZERS=ON -DWITH_SSE4=OFF
+            cmake-args: -DWITH_SSE4=OFF -DWITH_SANITIZER=Undefined
             codecov: ubuntu_gcc_no_sse4
 
           - name: Ubuntu GCC No PCLMULQDQ
             os: ubuntu-latest
             compiler: gcc
-            cmake-args: -DWITH_SANITIZERS=ON -DWITH_PCLMULQDQ=OFF
+            cmake-args: -DWITH_PCLMULQDQ=OFF -DWITH_SANITIZER=Undefined
             codecov: ubuntu_gcc_no_pclmulqdq
 
           - name: Ubuntu GCC Compat No Opt
             os: ubuntu-latest
             compiler: gcc
-            cmake-args: -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZERS=ON
+            cmake-args: -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Address
             codecov: ubuntu_gcc_compat_no_opt
             cflags: -DNOT_TWEAK_COMPILER
 
           - name: Ubuntu GCC ARM SF
             os: ubuntu-latest
             compiler: arm-linux-gnueabi-gcc
-            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabi -DWITH_SANITIZERS=ON
+            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabi -DWITH_SANITIZER=Address
             packages: qemu gcc-arm-linux-gnueabi libc-dev-armel-cross
             codecov: ubuntu_gcc_armsf
 
           - name: Ubuntu GCC ARM SF Compat No Opt
             os: ubuntu-latest
             compiler: arm-linux-gnueabi-gcc
-            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabi -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZERS=ON
+            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabi -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Undefined
             packages: qemu gcc-arm-linux-gnueabi libc-dev-armel-cross
             codecov: ubuntu_gcc_armsf_compat_no_opt
 
           - name: Ubuntu GCC ARM HF
             os: ubuntu-latest
             compiler: arm-linux-gnueabihf-gcc
-            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf -DWITH_SANITIZERS=ON
+            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf -DWITH_SANITIZER=Address
             packages: qemu gcc-arm-linux-gnueabihf libc-dev-armel-cross
             codecov: ubuntu_gcc_armhf
 
           - name: Ubuntu GCC ARM HF No ACLE
             os: ubuntu-latest
             compiler: arm-linux-gnueabihf-gcc
-            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf -DWITH_SANITIZERS=ON -DWITH_ACLE=OFF
+            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf -DWITH_ACLE=OFF -DWITH_SANITIZER=Address
             packages: qemu gcc-arm-linux-gnueabihf libc-dev-armel-cross
             codecov: ubuntu_gcc_armhf_no_acle
 
           - name: Ubuntu GCC ARM HF No NEON
             os: ubuntu-latest
             compiler: arm-linux-gnueabihf-gcc
-            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf -DWITH_SANITIZERS=ON -DWITH_NEON=OFF
+            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf -DWITH_NEON=OFF -DWITH_SANITIZER=Address
             packages: qemu gcc-arm-linux-gnueabihf libc-dev-armel-cross
             codecov: ubuntu_gcc_armhf_no_neon
 
           - name: Ubuntu GCC ARM HF Compat No Opt
             os: ubuntu-latest
             compiler: arm-linux-gnueabihf-gcc
-            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZERS=ON
+            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Undefined
             packages: qemu gcc-arm-linux-gnueabihf libc-dev-armel-cross
             codecov: ubuntu_gcc_armhf_compat_no_opt
 
           - name: Ubuntu GCC AARCH64
             os: ubuntu-latest
             compiler: aarch64-linux-gnu-gcc
-            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DWITH_SANITIZERS=ON
+            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DWITH_SANITIZER=Address
             asan-options: detect_leaks=0
             packages: qemu gcc-aarch64-linux-gnu libc-dev-arm64-cross
             codecov: ubuntu_gcc_aarch64
@@ -119,7 +119,7 @@ jobs:
           - name: Ubuntu GCC AARCH64 No ACLE
             os: ubuntu-latest
             compiler: aarch64-linux-gnu-gcc
-            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DWITH_SANITIZERS=ON -DWITH_ACLE=OFF
+            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DWITH_ACLE=OFF -DWITH_SANITIZER=Undefined
             asan-options: detect_leaks=0
             packages: qemu gcc-aarch64-linux-gnu libc-dev-arm64-cross
             codecov: ubuntu_gcc_aarch64_no_acle
@@ -127,7 +127,7 @@ jobs:
           - name: Ubuntu GCC AARCH64 No NEON
             os: ubuntu-latest
             compiler: aarch64-linux-gnu-gcc
-            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DWITH_SANITIZERS=ON -DWITH_NEON=OFF
+            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DWITH_NEON=OFF -DWITH_SANITIZER=Undefined
             asan-options: detect_leaks=0
             packages: qemu gcc-aarch64-linux-gnu libc-dev-arm64-cross
             codecov: ubuntu_gcc_aarch64_no_neon
@@ -135,7 +135,7 @@ jobs:
           - name: Ubuntu GCC AARCH64 Compat No Opt
             os: ubuntu-latest
             compiler: aarch64-linux-gnu-gcc
-            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZERS=ON
+            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Undefined
             asan-options: detect_leaks=0
             packages: qemu gcc-aarch64-linux-gnu libc-dev-arm64-cross
             codecov: ubuntu_gcc_aarch64_compat_no_opt
@@ -174,7 +174,7 @@ jobs:
           - name: Ubuntu GCC S390X
             os: ubuntu-latest
             compiler: s390x-linux-gnu-gcc
-            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-s390x.cmake -DWITH_SANITIZERS=ON
+            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-s390x.cmake -DWITH_SANITIZER=Address
             packages: qemu gcc-s390x-linux-gnu libc-dev-s390x-cross
             ldflags: -static
             codecov: ubuntu_gcc_s390x
@@ -182,7 +182,7 @@ jobs:
           - name: Ubuntu GCC S390X DFLTCC
             os: ubuntu-latest
             compiler: s390x-linux-gnu-gcc
-            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-s390x.cmake -DWITH_DFLTCC_DEFLATE=ON -DWITH_DFLTCC_INFLATE=ON -DWITH_SANITIZERS=ON
+            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-s390x.cmake -DWITH_DFLTCC_DEFLATE=ON -DWITH_DFLTCC_INFLATE=ON -DWITH_SANITIZER=Address
             packages: qemu gcc-s390x-linux-gnu libc-dev-s390x-cross
             ldflags: -static
             codecov: ubuntu_gcc_s390x
@@ -190,7 +190,7 @@ jobs:
           - name: Ubuntu GCC S390X DFLTCC Compat
             os: ubuntu-latest
             compiler: s390x-linux-gnu-gcc
-            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-s390x.cmake -DZLIB_COMPAT=ON -DWITH_DFLTCC_DEFLATE=ON -DWITH_DFLTCC_INFLATE=ON -DWITH_SANITIZERS=ON
+            cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-s390x.cmake -DZLIB_COMPAT=ON -DWITH_DFLTCC_DEFLATE=ON -DWITH_DFLTCC_INFLATE=ON -DWITH_SANITIZER=Undefined
             packages: qemu gcc-s390x-linux-gnu libc-dev-s390x-cross
             ldflags: -static
             codecov: ubuntu_gcc_s390x
@@ -251,7 +251,7 @@ jobs:
           - name: Ubuntu Clang MSAN
             os: ubuntu-latest
             compiler: clang
-            cmake-args: -GNinja -DWITH_MSAN=ON
+            cmake-args: -GNinja -DWITH_SANITIZER=Memory
             packages:  ninja-build llvm-6.0
             gcov-exec: llvm-cov-6.0 gcov
             cflags: -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize-memory-track-origins
@@ -290,15 +290,15 @@ jobs:
             codecov: win64_gcc_compat_no_opt
 
           - name: macOS Clang
-            os: macOS-latest
+            os: macos-latest
             compiler: clang
-            cmake-args: -DWITH_SANITIZERS=ON
+            cmake-args: -DWITH_SANITIZER=Address
             codecov: macos_clang
 
           - name: macOS GCC
-            os: macOS-latest
+            os: macos-latest
             compiler: gcc
-            cmake-args: -DWITH_SANITIZERS=ON
+            cmake-args: -DWITH_SANITIZER=Undefined
             codecov: macos_gcc
 
     steps:
index 9ddd575ac8d7f3c771b64f4127e268181a6b4077..9ee040487124d5b91e21e1e22048395714f2b691 100644 (file)
@@ -81,8 +81,7 @@ add_option(WITH_GZFILEOP "Compile with support for gzFile related functions" ON)
 add_option(ZLIB_COMPAT "Compile with zlib compatible API" OFF)
 add_option(ZLIB_ENABLE_TESTS "Build test binaries" ON)
 add_option(ZLIB_DUAL_LINK "Dual link tests against system zlib" OFF)
-add_option(WITH_SANITIZERS "Build with address sanitizer and all supported sanitizers other than memory sanitizer" OFF)
-add_option(WITH_MSAN "Build with memory sanitizer" OFF)
+add_option(WITH_SANITIZER "Build with sanitizer (Memory, Address, Undefined)" OFF)
 add_option(WITH_FUZZERS "Build test/fuzz" OFF)
 add_option(WITH_OPTIM "Build with optimisation" ON)
 add_option(WITH_NEW_STRATEGIES "Use new strategies" ON)
@@ -358,12 +357,12 @@ if(NOT HAVE_STRERROR)
     add_definitions(-DNO_STRERROR)
 endif()
 
-if(WITH_MSAN AND WITH_SANITIZERS)
-    message(FATAL_ERROR "Memory sanitizer is incompatible with address sanitizer")
-elseif(WITH_MSAN)
-    add_memory_sanitizer_check()
-elseif(WITH_SANITIZERS)
-    add_sanitizer_checks()
+if(WITH_SANITIZER STREQUAL "Address")
+    add_address_sanitizer()
+elseif(WITH_SANITIZER STREQUAL "Memory")
+    add_memory_sanitizer()
+elseif(WITH_SANITIZER STREQUAL "Undefined")
+    add_undefined_sanitizer()
 endif()
 #
 # Check if we can hide zlib internal symbols that are linked between separate source files using hidden
index 901af0781581a598cfa4b6bac58824730e94f264..ad14c3ff428a4d48c8ac8f771319fad75c89dbfe 100644 (file)
--- a/README.md
+++ b/README.md
@@ -111,12 +111,11 @@ Build Options
 |:-------------------------|:-------------------------|:--------------------------------------------------------------------------------------|---------|
 | ZLIB_COMPAT              | --zlib-compat            | Compile with zlib compatible API                                                      | OFF     |
 | ZLIB_ENABLE_TESTS        |                          | Build test binaries                                                                   | ON      |
-| WITH_GZFILEOP            | --without-gzfileops      | Compile with support for gzFile related functions                                     | ON     |
-| WITH_MSAN                | --with-msan              | Build with memory sanitizer                                                           | OFF     |
+| WITH_GZFILEOP            | --without-gzfileops      | Compile with support for gzFile related functions                                     | ON      |
 | WITH_OPTIM               | --without-optimizations  | Build with optimisations                                                              | ON      |
 | WITH_NEW_STRATEGIES      | --without-new-strategies | Use new strategies                                                                    | ON      |
 | WITH_NATIVE_INSTRUCTIONS | --native                 | Compiles with full instruction set supported on this host (gcc/clang -march=native)   | OFF     |
-| WITH_SANITIZERS          | --with-sanitizers        | Build with address sanitizer and all supported sanitizers other than memory sanitizer | OFF     |
+| WITH_SANITIZER           | --with-sanitizer         | Build with sanitizer (memory, address, undefined)                                     | OFF     |
 | WITH_FUZZERS             | --with-fuzzers           | Build test/fuzz                                                                       | OFF     |
 | WITH_MAINTAINER_WARNINGS |                          | Build with project maintainer warnings                                                | OFF     |
 | WITH_CODE_COVERAGE       |                          | Enable code coverage reporting                                                        | OFF     |
index 82ad0fd3694e4f193fa5ef406aca9e61dfce053a..172a8d558390768ab6a002a2be5f93f26ad5a2fa 100644 (file)
@@ -29,33 +29,61 @@ macro(check_sanitizer_support known_checks supported_checks)
     set(${supported_checks} ${available_checks})
 endmacro()
 
-macro(add_memory_sanitizer_check)
+macro(add_address_sanitizer)
+    set(known_checks
+        address
+        pointer-compare
+        pointer-subtract
+        )
+
+    check_sanitizer_support("${known_checks}" supported_checks)
+    if(NOT ${supported_checks} STREQUAL "")
+        message(STATUS "Address sanitizer is enabled: ${supported_checks}")
+        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}")
+    else()
+        message(STATUS "Address sanitizer is not supported")
+    endif()
+
+    if(CMAKE_CROSSCOMPILING_EMULATOR)
+        # Only check for leak sanitizer if not cross-compiling due to qemu crash
+        message(WARNING "Leak sanitizer is not supported when cross compiling")
+    else()
+        # Leak sanitizer requires address sanitizer
+        check_sanitizer_support("leak" supported_checks)
+        if(NOT ${supported_checks} STREQUAL "")
+            message(STATUS "Leak sanitizer is enabled: ${supported_checks}")
+            set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}")
+        else()
+            message(STATUS "Leak sanitizer is not supported")
+        endif()
+    endif()
+endmacro()
+
+macro(add_memory_sanitizer)
     check_sanitizer_support("memory" supported_checks)
     if(NOT ${supported_checks} STREQUAL "")
-        message(STATUS "Memory sanitizer is enabled")
+        message(STATUS "Memory sanitizer is enabled: ${supported_checks}")
         set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}")
     else()
         message(STATUS "Memory sanitizer is not supported")
     endif()
 endmacro()
 
-macro(add_sanitizer_checks)
+macro(add_undefined_sanitizer)
     set(known_checks
-        address
         array-bounds
         bool
         bounds
         builtin
         enum
+        float-cast-overflow
         float-divide-by-zero
         function
         integer-divide-by-zero
+        local-bounds
         null
         nonnull-attribute
-        object-size
-        pointer-compare             # Depends on 'address'
         pointer-overflow
-        pointer-subtract            # Depends on 'address'
         return
         returns-nonnull-attribute
         shift
@@ -64,23 +92,24 @@ macro(add_sanitizer_checks)
         signed-integer-overflow
         undefined
         unsigned-integer-overflow
+        unsigned-shift-base
         vla-bound
         vptr
         )
 
-    # Only check for leak sanitizer if not cross-compiling due to qemu crash
-    if(NOT CMAKE_CROSSCOMPILING_EMULATOR)
-        list(APPEND known_checks leak)
-    endif()
     # Only check for alignment sanitizer flag if unaligned access is not supported
     if(NOT UNALIGNED_OK)
         list(APPEND known_checks alignment)
     endif()
+    # Object size sanitizer has no effect at -O0 and produces compiler warning if enabled
+    if(NOT CMAKE_C_FLAGS MATCHES "-O0")
+        list(APPEND known_checks object-size)
+    endif()
 
     check_sanitizer_support("${known_checks}" supported_checks)
 
     if(NOT ${supported_checks} STREQUAL "")
-        message(STATUS "Supported sanitizers checks are enabled: ${supported_checks}")
+        message(STATUS "Undefined behavior sanitizer is enabled: ${supported_checks}")
         set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}")
 
         # Group sanitizer flag -fsanitize=undefined will automatically add alignment, even if
@@ -89,6 +118,6 @@ macro(add_sanitizer_checks)
             set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-sanitize=alignment")
         endif()
     else()
-        message(STATUS "Sanitizer checks are not supported")
+        message(STATUS "UNdefined behavior sanitizer is not supported")
     endif()
 endmacro()
\ No newline at end of file
index 5e3d5bb1c2a5bcaee5a1c347b1e35468b840cfc6..b5a446287a8fa5eb1e2adbe69ce6f6cc2069f8e0 100755 (executable)
--- a/configure
+++ b/configure
@@ -96,8 +96,7 @@ buildacle=1
 buildneon=1
 builddfltccdeflate=0
 builddfltccinflate=0
-with_sanitizers=0
-with_msan=0
+with_sanitizer=""
 with_fuzzers=0
 floatabi=
 native=0
@@ -157,8 +156,7 @@ case "$1" in
       echo '    [--with-dfltcc-deflate]     Use DEFLATE CONVERSION CALL instruction for compression on IBM Z' | tee -a configure.log
       echo '    [--with-dfltcc-inflate]     Use DEFLATE CONVERSION CALL instruction for decompression on IBM Z' | tee -a configure.log
       echo '    [--force-sse2]              Assume SSE2 instructions are always available (disabled by default on x86, enabled on x86_64)' | tee -a configure.log
-      echo '    [--with-sanitizers]         Build with address sanitizer and all supported sanitizers other than memory sanitizer (disabled by default)' | tee -a configure.log
-      echo '    [--with-msan]               Build with memory sanitizer (disabled by default)' | tee -a configure.log
+      echo '    [--with-sanitizer]          Build with sanitizer (memory, address, undefined)' | tee -a configure.log
       echo '    [--with-fuzzers]            Build test/fuzz (disabled by default)' | tee -a configure.log
       echo '    [--native]                  Compiles with full instruction set supported on this host' | tee -a configure.log
         exit 0 ;;
@@ -192,8 +190,7 @@ case "$1" in
     -oldstrat | --without-new-strategies) without_new_strategies=1; shift;;
     -w* | --warn) warn=1; shift ;;
     -d* | --debug) debug=1; shift ;;
-    --with-sanitizers) with_sanitizers=1; shift ;;
-    --with-msan) with_msan=1; shift ;;
+    --with-sanitizer=*) with_sanitizer=`echo $1 | sed 's/.*=//'`; shift ;;
     --with-fuzzers) with_fuzzers=1; shift ;;
 
     *)
@@ -574,14 +571,10 @@ fi
 
 echo >> configure.log
 
-if test $with_sanitizers -eq 1; then
-    if test $with_msan -eq 1; then
-        echo "Error: --with-sanitizers and --with-msan cannot be used together"
-        exit 1
-    fi
-    echo -n "Checking for sanitizers ASan/UBSan... " | tee -a configure.log
+if test "$with_sanitizer" = "address"; then
+    echo -n "Checking for address sanitizer... " | tee -a configure.log
     sanitizers=""
-    for san in bool address array-bounds float-divide-by-zero function integer-divide-by-zero return shift signed-integer-overflow undefined unsigned-integer-overflow vla-bound vptr; do
+    for san in address pointer-compare pointer-subtract; do
         if try $CC -c $CFLAGS $test.c -fsanitize=$san ; then
             if test -n "$sanitizers"; then
                 sanitizers="$sanitizers,$san"
@@ -600,11 +593,21 @@ if test $with_sanitizers -eq 1; then
         echo No | tee -a configure.log
     fi
 
+    echo -n "Checking for leak sanitizer... " | tee -a configure.log
+    if try $CC -c $CFLAGS $test.c -fsanitize=leak; then
+        echo "-fsanitize=leak" | tee -a configure.log
+        CFLAGS="$CFLAGS -fsanitize=leak"
+        SFLAGS="$SFLAGS -fsanitize=leak"
+        LDFLAGS="$LDFLAGS -fsanitize=leak"
+    else
+        echo No | tee -a configure.log
+    fi
+
     echo >> configure.log
 fi
 
-if test $with_msan -eq 1; then
-    echo -n "Checking for MSan... " | tee -a configure.log
+if test "$with_sanitizer" = "memory"; then
+    echo -n "Checking for memory sanitizer... " | tee -a configure.log
     if try $CC -c $CFLAGS $test.c -fsanitize=memory ; then
         echo "-fsanitize=memory" | tee -a configure.log
         CFLAGS="$CFLAGS -fsanitize=memory"
@@ -617,6 +620,31 @@ if test $with_msan -eq 1; then
     echo >> configure.log
 fi
 
+if test "$with_sanitizer" = "undefined"; then
+    echo -n "Checking for undefined behavior sanitizer... " | tee -a configure.log
+    sanitizers=""
+    for san in array-bounds bool bounds builtin enum float-cast-overflow float-divide-by-zero function integer-divide-by-zero local-bounds null nonnull-attribute object-size pointer-overflow return returns-nonnull-attribute shift shift-base shift-exponent signed-integer-overflow undefined unsigned-integer-overflow unsigned-shift-base vla-bound vptr; do
+        if try $CC -c $CFLAGS $test.c -fsanitize=$san; then
+            if test -n "$sanitizers"; then
+                sanitizers="$sanitizers,$san"
+            else
+                sanitizers="$san"
+            fi
+        fi
+    done
+
+    if test -n "$sanitizers"; then
+        echo "-fsanitize=$sanitizers" | tee -a configure.log
+        CFLAGS="$CFLAGS -fsanitize=$sanitizers"
+        SFLAGS="$SFLAGS -fsanitize=$sanitizers"
+        LDFLAGS="$LDFLAGS -fsanitize=$sanitizers"
+    else
+        echo No | tee -a configure.log
+    fi
+
+    echo >> configure.log
+fi
+
 # see if shared library build supported
 cat > $test.c <<EOF
 extern int getchar();