14

Clang 8 release notes have this promising line:

  • Allow using Address Sanitizer and Undefined Behaviour Sanitizer on MinGW.

However, I unable to figure out how to use those properly.

I'm using Clang 8.0.0 with MSYS2 MinGW GCC. Exact details are at the bottom of the question.

I'm trying to compile following minimal piece of code:

1.cpp

#include <iostream>

int main()
{
    // Testing ubsan
    int x = 0x7fffffff;
    x++;
    std::cout << x << std::endl;

    // Testing asan
    int *y = new int;
    delete y;
    std::cout << *y << std::endl;
}

Here are results for -fsanitize=address:

# /z/Lander/LLVM/bin/clang++ -target x86_64-w64-windows-gnu -fsanitize=address 1.cpp
Z:\Lander\msys2\mingw64\bin\ld.exe: cannot find Z:\Lander\LLVM\lib\clang\8.0.0\lib\windows\libclang_rt.asan_dynamic-x86_64.dll.a: No such file or directory
Z:\Lander\msys2\mingw64\bin\ld.exe: cannot find Z:\Lander\LLVM\lib\clang\8.0.0\lib\windows\libclang_rt.asan_dynamic_runtime_thunk-x86_64.a: No such file or directory
Z:\Lander\msys2\mingw64\bin\ld.exe: cannot find Z:\Lander\LLVM\lib\clang\8.0.0\lib\windows\libclang_rt.asan_dynamic_runtime_thunk-x86_64.a: No such file or directory
clang++: error: linker command failed with exit code 1 (use -v to see invocation)

And here is -fsanitize=undefined:

# /z/Lander/LLVM/bin/clang++ -target x86_64-w64-windows-gnu -fsanitize=undefined 1.cpp
Warning: corrupt .drectve at end of def file
Z:\Lander\msys2\tmp\1-13f09e.o:1.cpp:(.text+0x9f): undefined reference to `__ubsan_handle_add_overflow'
Z:\Lander\msys2\tmp\1-13f09e.o:1.cpp:(.text+0xef): undefined reference to `__ubsan_handle_type_mismatch_v1'
Z:\Lander\msys2\tmp\1-13f09e.o:1.cpp:(.text+0x148): undefined reference to `__ubsan_handle_type_mismatch_v1'
Z:\Lander\msys2\tmp\1-13f09e.o:1.cpp:(.text+0x196): undefined reference to `__ubsan_handle_type_mismatch_v1'
Z:\Lander\msys2\tmp\1-13f09e.o:1.cpp:(.text+0x1df): undefined reference to `__ubsan_handle_type_mismatch_v1'
Z:\Lander\msys2\tmp\1-13f09e.o:1.cpp:(.text+0x22c): undefined reference to `__ubsan_handle_type_mismatch_v1'
clang++: error: linker command failed with exit code 1 (use -v to see invocation)

Here are the contents of Z:\Lander\LLVM\lib\clang\8.0.0\lib\windows\ where it looks for libraries:

clang_rt.asan-preinit-x86_64.lib
clang_rt.asan-x86_64.lib
clang_rt.asan_cxx-x86_64.lib
clang_rt.asan_dll_thunk-x86_64.lib
clang_rt.asan_dynamic-x86_64.dll
clang_rt.asan_dynamic-x86_64.lib
clang_rt.asan_dynamic_runtime_thunk-x86_64.lib
clang_rt.builtins-x86_64.lib
clang_rt.fuzzer-x86_64.lib
clang_rt.fuzzer_no_main-x86_64.lib
clang_rt.profile-x86_64.lib
clang_rt.stats-x86_64.lib
clang_rt.stats_client-x86_64.lib
clang_rt.ubsan_standalone-x86_64.lib
clang_rt.ubsan_standalone_cxx-x86_64.lib

This doesn't look right, since the MinGW GCC normally works with .a libraries, not .lib.

I tried to manually link various libraries from that directory.

For asan, I managed to get rid of compiler errors, but the asan itself doesn't seem to emit any diagnostics:

# /z/Lander/LLVM/bin/clang++ -target x86_64-w64-windows-gnu -fsanitize=address 1.cpp -c
# /z/Lander/LLVM/bin/clang++ -target x86_64-w64-windows-gnu 1.o /z/Lander/LLVM/lib/clang/8.0.0/lib/windows/clang_rt.asan_dynamic-x86_64.lib
# ./a.exe
-2147483648
5089296         <- expected a diagnostic here

For ubsan, I tried to link against clang_rt.ubsan_standalone-x86_64.lib, but got more undefined references and several Warning: corrupt .drectve at end of def file.

I did some research on Warning: corrupt .drectve at end of def file, and this question suggests that it means I'm linking incompatible MSVC libraries.

What's going on here? How am I supposed to use asan & ubsan?


All commands above were run from MSYS2 terminal, running on Windows 7 x64.

I'm targeting x86_64 and using latest GCC available in MSYS2:

# g++ --version
g++.exe (Rev2, Built by MSYS2 project) 8.3.0

Clang from MSYS2 doesn't seem to have asan & ubsan libraries bundled, so I'm using the official build from llvm.org:

# /z/Lander/LLVM/bin/clang++ --version
clang version 8.0.0 (tags/RELEASE_800/final)
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: Z:\Lander\LLVM\bin

I'm using -target x86_64-w64-windows-gnu because otherwise Clang tries to use a MSVC installation, which I don't have. This specific triplet is what MSYS2 clang reports in reponse to --version.

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207

3 Answers3

6

I've found a way to make UBsan work, but not Asan.

Turns out, UBsan can function even without libubsan. You need to use following flags:

-fsanitize=undefined -fsanitize-undefined-trap-on-error

This way, errors are reported via crashing with 'Illegal instruction' rather by emitting pretty diagnostics, but it's better than nothing.

This flag is supported by both GCC and Clang.

GCC manual:

-fsanitize-undefined-trap-on-error

The -fsanitize-undefined-trap-on-error option instructs the compiler to report undefined behavior using __builtin_trap rather than a libubsan library routine. The advantage of this is that the libubsan library is not needed and is not linked in, so this is usable even in freestanding environments.

Community
  • 1
  • 1
HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
3

Compilers that support sanitizers (address, UB etc.) on Windows

To be able to use sanitizers on Windows as of now (3/2023) you need either:

  • MSVC with Visual Studio 2019 or later (with AddressSanitizer installed)
    • Only supports AddressSanitizer
    • A good StackOverflow answer with instructions here
  • Any Clang on Visual Studio
    • Can be installed via the installer on Visual Studio 2019 or later.
    • Microsoft C++ library requires Clang compiler version 8.0.0 or newer, so any VS-compliant compiler should come with address and UB sanitizers.
  • Any gcc or clang compiler in WSL (Windows Subsystem for Linux)
    • Should support all sanitizers (address, thread, memory, and UB)
    • Requires you to be able to compile and run your code in a Linux environment.
  • MSYS2 with clang and libc++ as of 4/2021 on MSYS2 CLANG64 environment
    • Supports UB and address sanitizers (thread and memory sanitizers are unsupported).
    • Other clang variants do not support sanitizers, namely the libstdc++ versions eg. UCRT64. You will get linker errors trying to use sanitizers with these clang packages.
    • MSYS2 gcc does not support AddressSanitizer.

Visual Studio AddressSanitizer or Clang installation should be easy following the guide(s) above. WSL also has plenty of guides from Microsoft and other third-party sites. Thus, I will only go through the installation on MSYS2, as it has a few stumbling blocks. MSYS2 includes many different environments and each environment has its own clang package and only one of these clang variants (libc++) supports sanitizers.

How to install MSYS2 clang with address and UB sanitizers

  1. Install MSYS2 with the installer following the MSYS2 Getting started guide. Note that by default the installer starts a sanitizer incompatible environment UCRT64 if you tick the box Run MSYS2 now.
  2. Start MSYS2 CLANG64 terminal environment from Start Menu. The correct terminal has the prefix <username>@<computer_name> CLANG64.
  3. Update MSYS2 using the package manager pacman -Syu (MSYS2 Update guide here)
  4. In certain cases, and especially with first-time installations, the update process needs to close the terminal to update some core packages. If this happens, start the CLANG64 terminal again and run pacman -Syu again to update non-core packages.
  5. Next, we need to install the correct clang variation. This done with the package manager command pacman -S mingw-w64-clang-x86_64-clang.
  6. After the installation, check that you have installed the correct variation by running clang --version.
  7. If you get an error -bash: clang: command not found or something similar you are most likely in the wrong environment. Switch to CLANG64 environment as the mingw-w64-clang-x86_64-clang package installs clang there.

Now within the CLANG64 MSYS2 environment you can compile code with address and UB sanitizers using -fsanitize=address and -fsanitize=undefined options with clang or clang++ compilers. For example, we can test AddressSanitizer with the following program:

int main()
{
    int* const heapOverflow = new int[5]{};
    heapOverflow[5] = 0;
}

Compile with clang++ and run, and you should get an AddressSanitizer error:

$ clang++ -fsanitize=address heapoverflow.cpp -o heapoverflow`
$./heapoverflow

=================================================================
==17384==ERROR: AddressSanitizer: heap-buffer-overflow on address
...
Rane
  • 321
  • 2
  • 6
1

ASAN indeed works on Windows.

To avoid errors such as:

C:/msys64/mingw64/bin/ld: cannot find C:/msys64/mingw64/lib/clang/13.0.0/lib/windows/libclang_rt.asan_dynamic-x86_64.dll.a: No such file or directory
C:/msys64/mingw64/bin/ld: cannot find C:/msys64/mingw64/lib/clang/13.0.0/lib/windows/libclang_rt.asan_dynamic_runtime_thunk-x86_64.a: No such file or directory

use /clang64/bin/clang instead of /mingw64/bin/clang. Install it with:

pacman -S mingw-w64-clang-x86_64-clang

See https://www.msys2.org/docs/environments/

0xF
  • 3,214
  • 1
  • 25
  • 29