AddressSanitizer (ASan) for Windows with MSVC
⌚ This post was last updated on January 31st, 2020.
We are pleased to announce AddressSanitizer (ASan) support for the MSVC toolset. ASan is a fast memory error detector that can find runtime memory issues such as use-after-free and perform out of bounds checks. Support for sanitizers has been one of our more popular suggestions on Developer Community, and we can now say that we have an experience for ASan on Windows, in addition to our existing support for Linux projects.
At Microsoft, we believe that developers should be able to use the tools of their choice, and we are glad to collaborate with the LLVM team to introduce more of their tooling into Visual Studio. In the past, we also incorporated tools like clang-format, and most recently, clang-tidy. MSVC support for ASan is available in our second Preview release of Visual Studio 2019 version 16.4.
To bring ASan to Windows and MSVC, we made the following changes:
- The ASan runtime has been updated to better target Windows binaries
- The MSVC compiler can now instrument binaries with ASan
- CMake and MSBuild integrations have been updated to support enabling ASan
- The Visual Studio debugger now can detect ASan errors in Windows binaries
- ASan can be installed from the Visual Studio installer for the C++ Desktop workload
When you’re debugging your ASan-instrumented binary in Visual Studio, the IDE Exception Helper will be displayed when an issue is encountered, and program execution will stop. You can also view detailed ASan logging information in the Output window.
Installing ASan support for Windows
ASan is included with the C++ Desktop workload by default for new installations. However, if you are upgrading from an older version of Visual Studio 2019, you will need to enable ASan support in the Installer after the upgrade:
You can click Modify on your existing Visual Studio installation from the Visual Studio Installer to get to the screen above.
Note: if you run Visual Studio on the new update but have not installed ASan, you will get the following error when you run your code:
LNK 1356 – cannot find library ‘clang_rt.asan_dynamic-i386.lib’
Turning on ASan for Windows MSBuild projects
You can turn on ASan for an MSBuild project by right-clicking on the project in Solution Explorer, choosing Properties, navigating under C/C++ > General, and changing the Enable Address Sanitizer (Experimental) option. The same approach can be used to enable ASan for MSBuild Linux projects.
Note: Right now, this will only work for x86 Release targets, though we will be expanding to more architectures in the future.
Turning on ASan for Windows CMake projects
To enable ASan for CMake projects targeting Windows, do the following:
- Open the Configurations dropdown at the top of the IDE and click on Manage Configurations. This will open the CMake Project Settings UI, which is saved in a CMakeSettings.json file.
- Click the Edit JSON link in the UI. This will switch the view to raw .json.
- Under the x86-Release configuration, add the following property: "addressSanitizerEnabled": true
You may get a green squiggle under the line above with the following warning: Property name is not allowed by the schema. This is a bug that will be fixed shortly – the property will in fact work.
Here is an image of the relevant section of the CMakeSettings.json file after the change:
We will further simplify the process for enabling ASan in CMake projects in a future update.
Contributions to ASan Runtime
To enable a great Windows experience, we decided to contribute to the LLVM compiler-rt project and reuse their runtime in our implementation of ASan. Our contributions to the ASan project include bug fixes and improved interception for HeapAlloc , RtlAllocateHeap , GlobalAlloc , and LocalAlloc , along with their corresponding Free , ReAllocate , and Size functions. Anyone can enable these features by adding the following to the ASAN_OPTIONS environment variable for either Clang or MSVC on Windows:
1 | ASAN_OPTIONS=set windows_hook_rtl_allocators=true |
Additional options can be added with a colon at the end of the line above.
Changes to MSVC to enable ASan
To enable ASan, c1.dll and c2.dll have been modified to add instrumentation to programs at compile time. For a 32-bit address space, about 200 MB of memory is allocated to represent (or ‘shadow’) the entire address space. When an allocation is made, the shadow memory is modified to represent that the allocation is now valid to access. When the allocation is freed or goes out of scope, the shadow memory is modified to show that this allocation is no longer valid. Memory accesses which are potentially dangerous are checked against their entry in the shadow memory to verify that the memory is safe to access at that time. Violations are reported to the user as output from either stderr or an exception window in Visual Studio. The allocation data in the shadow memory is checked before the access happens. The AddressSanitizer algorithm enables error reports to show exactly where the problem occurred and what went wrong.
This means that programs compiled with MSVC + ASan also have the appropriate clang_rt.asan library linked for their target. Each library has a specific use case and linking can be complicated if your program is complex.
Compiling with ASan from the console
For console compilation, you will have to link the ASan libraries manually. Here are the libraries required for an x86 target:
- clang_rt.asan-i386.lib – static runtime compatible with /MT CRT.
- clang_rt.asan_cxx-i386.lib -static runtime component which adds support for new and delete, also compatible with /MT CRT.
- clang_rt.asan_dynamic-i386.lib – dynamic import library, compatible with /MD CRT.
- clang_rt.asan_dynamic-i386.dll – dynamic runtime DLL, compatible with /MD.
- clang_rt.asan_dynamic_runtime_thunk-i386.lib – dynamic library to import and intercept some /MD CRT functions manually.
- clang_rt.asan_dll_thunk-i386.lib – import library which allows an ASAN instrumented DLL to use the static ASan library which is linked into the main executable. Compatible with /MT CRT.
Once you have selected the correct ASan runtime to use, you should add /wholearchive:<library to link> to your link line and add the appropriate library to your executables. The clang_rt.asan_dynamic_i386.dll is not installed into System32, so when running you should make sure it is available in your environment’s search path.
Some additional instructions:
- When compiling a single static EXE: link the static runtime (asan-i386.lib) and the cxx library if it is needed.
- When compiling an EXE with the /MT runtime which will use ASan-instrumented DLLs: the EXE needs to have asan-i386.lib linked and the DLLs need the clang_rt.asan_dll_thunk-i386.lib. This allows the DLLs to use the runtime linked into the main executable and avoid a shadow memory collision problem.
- When compiling with the /MD dynamic runtime: all EXE and DLLs with instrumentation should be linked with copies of asan_dynamic-i386.lib and clang_rt.asan_dynamic_runtime_thunk-i386.lib. At runtime, these libraries will refer to the clang_rt.asan_dynamic-i386.dll shared ASan runtime.
The ASan runtime libraries patch memory management functions at run-time and redirect executions to an ASan wrapper function which manages the shadow memory. This can be unstable if the runtime environment differs from what the libraries have been written to expect. Please submit any compile or run time errors which you encounter while using ASan via the feedback channels below!
Note: Loading ASan-instrumented DLLs with an non-ASan-instrumented EXE without linking the clang_rt.asan_dynamic and clang_rt.asan_dynamic_runtime_thunk library will result in false positive ASan reports. This is due to allocations being created in-between program initialization and whenever the ASan instrumented DLL is loaded. Any allocations which are created during this window will result in an erroneous bug report when they are passed into the newly intercepted CRT functions. These false positive reports are avoidable if you link the dynamic import libraries into the main executable; since linking the dynamic runtime libraries in this manner allows the interceptors to initialize at the proper time. Be sure to use the /wholearchive linker flag to ensure asan’s init routines are not optimized away in the main exe.
Send us feedback!
Your feedback is key for us to deliver the best experience running ASan in Visual Studio. We’d love for you to try out the latest Preview version of Visual Studio 2019 version 16.4 and let us know how it’s working for you, either in the comments below or via email. If you encounter problems with the experience or have suggestions for improvement, please Report A Problem or reach out via Developer Community. You can also find us on Twitter @VisualC.
46 comments
This is very good news, many thanks!
I already know ASan with clang-cl, which currently AFAIK does not support exceptions and only supports release builds. Do these restrictions also apply here?
I think clang-cl does support exceptions, but yes this implementation is also using the compiler-rt from LLVM so all the same restrictions apply here.
A note: The real restriction is that the debug runtime is not supported. This doesn’t mean that you need to build with full optimization or build without debug symbols. Certainly don’t build with ASAN on and then release that binary as a product, this is strictly for debugging or fuzzing. The /MTd and /MDd runtimes are not supported, but setting /MT or /MD along with /Zi for debug info and /Od to disable optimization gives you a ‘release build’ but with full debugging info.
I agree that ASan is very usable also without support for debug runtimes, thanks for clarifying.
Regarding exceptions, clang-cl of course supports exceptions. clang-cl with ASan enabled however does not work with exceptions, because of https://github.com/google/sanitizers/issues/749 . AFAIK this comes from the fact that the companies who developed the Windows port (Google for Chrome, Mozilla for Firefox) ban exceptions in their code bases, so they didn’t have much of an issue with that … Are you planning to fix this specific issue for the MSVC port? I believe this would make ASan usable for many more developers!
How does the MSVC port of ASan currently handle exceptions, what happens if an exception is thrown / catched?
This is fantastic. Now if only you could tell people to use /analyze, we might actually stop some bugs 😏
In the first screenshot, the green squiggle shown is actually a warning reported by /analyze detected by PREFast.
Background code analysis is on by default so everyone using 2019 should be running /analyze by default.
Is x86-64 support being worked on?
Yep
Time frame? It was a interesting read, just to find a really small note that only win32 is supported.
I want UBSan too.
It’s possible! Open issues/suggestions with Visual Studio and ask for it to be added. User feedback counts for a lot when deciding priorities before a sprint starts.
Great news!
Does it somehow affect the Application Verifier?
ApplicationVerifier and ASan shouldn’t be used at the same time. I don’t know if they are strictly incompatible but it wouldn’t get you anything extra to use both and would probably be kind of slow.
Will Microsoft support two tools in parallel?
Not planning to integrate ASan into Application Verifier?
How do you imagine this could work? After all Application Verifier uses facilities provided by the system (and its DLLs) whereas ASan uses instrumentation of the code in question …
Also, due to how ASan works, I imagine it’d be kind of hard to integrate it with certain options of AV by design.
I’ve just seen following critiques in reddit discussion that I tend to agree, so I decided to link them here:
https://www.reddit.com/r/cpp/comments/dfcdnw/code_analysis_with_clangtidy_in_visual_studio/f32xnrm?utm_source=share&utm_medium=web2x
https://www.reddit.com/r/cpp/comments/dm1emb/addresssanitizer_asan_for_windows_with_msvc/f4zrgiy?utm_source=share&utm_medium=web2x
In short, could you explain the rationale on putting those settings in CMakeSettings.json for CMake projects? Is this the final design or to be integrated more smoothly with CMake?
I did not handle the cmake integration so I can’t speak to their rationale. Any usability issues are almost surely bugs which should be filed via the channels at the end of the blog post. We love fixing issues that frustrate people, and occasionally we miss things while alpha/beta testing so please do reach out.
This is awesome! Is support for the debug runtime being worked on?
It’s on the list of things to do but is lower priority than x64 support and a few other items. You can still turn on debug info with cl and link and set optimizations as needed for an excellent debugging experience, just don’t link the MDd or MTd runtimes since they won’t work as expected with the clang runtime libs.
Does this not work on Windows 7, bombs out with “Exception thrown at 0x77BA191E (ntdll.dll) in fm.exe: 0xC0000139: Entry Point Not Found.” straight away
It should work on Win7, can you please provide feedback via the visualcpp@microsoft.com email, visual studio feedback hub, or via the developer community? It helps if you can include a small C file and instructions to reproduce the issue you’re seeing (VS version, windows patch verison, compiler-flags etc).
Will linking from the command-line be more streamlined in the future? For example for clang you just specify -fsanitize=address for the linker as well, instead of this matrix of choices.
Thanks
Probably yes, though I couldn’t put a timeline on it.
Good to hear! Looking forward to it. 🙂
Would I be right read that as “not for 16.4”?
Exciting news. I won’t be able to use it until x64 support arrives.. but when it does, will it work with a mixed-mode application?
ex. Native .exe entry point which loads .NET via C++/CLI? I don’t expect it to flag anything from the managed area, just want to know if it can monitor the native portions of the application.
CMake generation started for configuration: ‘Ninja-MSVC-x64-Debug’.
1> CMakeSettings ‘addressSanitizerEnabled’ value is inconsistent with CMAKE_C_FLAGS or CMAKE_CXX_FLAGS.
1> Environment settings:
1> CXXFLAGS=-fsanitize=address
1> CFLAGS=-fsanitize=address
1> LDFLAGS=/wholearchive:clang_rt.asan_dynamic-i386.lib /wholearchive:clang_rt.asan_dynamic_runtime_thunk-i386.lib /wholearchive:vcasan.lib
[CMake] CMake version: 3.15.19080502-MSVC_2
1> [CMake] — The C compiler identification is MSVC 19.24.28207.0
1> [CMake] — The CXX compiler identification is MSVC 19.24.28207.0
1> [CMake] — Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Preview/VC/Tools/MSVC/14.24.28207/bin/HostX64/x64/cl.exe
1> [CMake] — Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Preview/VC/Tools/MSVC/14.24.28207/bin/HostX64/x64/cl.exe — broken
1> [CMake] CMake Error at C:/Program Files (x86)/Microsoft Visual Studio/2019/Preview/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.15/Modules/CMakeTestCCompiler.cmake:60 (message):
1> [CMake] The C compiler
1> [CMake]
1> [CMake] “C:/Program Files (x86)/Microsoft Visual Studio/2019/Preview/VC/Tools/MSVC/14.24.28207/bin/HostX64/x64/cl.exe”
1> [CMake]
1> [CMake] is not able to compile a simple test program.
1> [CMake]
1> [CMake] It fails with the following output:
1> [CMake]
1> [CMake] Change Dir: X:/GitHub/GunBox/__build-output/Ninja-MSVC-x64-Debug/CMakeFiles/CMakeTmp
1> [CMake]
1> [CMake] Run Build Command(s):C:/Program Files (x86)/Microsoft Visual Studio/2019/Preview/Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja/ninja.exe cmTC_20743 && [1/2] Building C object CMakeFiles\cmTC_20743.dir\testCCompiler.c.obj
1> [CMake] cl : Command line warning D9002 : ignoring unknown option ‘-fsanitize=address’
1> [CMake] [2/2] Linking C executable cmTC_20743.exe
1> [CMake] FAILED: cmTC_20743.exe
1> [CMake] cmd.exe /C “cd . && “C:\Program Files (x86)\Microsoft Visual Studio\2019\Preview\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe” -E vs_link_exe –intdir=CMakeFiles\cmTC_20743.dir –rc=C:\PROGRA~2\WI3CF2~1\10\bin\10.0.18362.0\x64\rc.exe –mt=C:\PROGRA~2\WI3CF2~1\10\bin\10.0.18362.0\x64\mt.exe –manifests — “C:\PROGRA~2\Microsoft Visual Studio\2019\Preview\VC\Tools\MSVC\14.24.28207\bin\Hostx64\x64\link.exe” /nologo CMakeFiles\cmTC_20743.dir\testCCompiler.c.obj /out:cmTC_20743.exe /implib:cmTC_20743.lib /pdb:cmTC_20743.pdb /version:0.0 /machine:x64 /wholearchive:clang_rt.asan_dynamic-i386.lib /wholearchive:clang_rt.asan_dynamic_runtime_thunk-i386.lib /wholearchive:vcasan.lib /debug /INCREMENTAL /subsystem:console kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cmd.exe /C “cd /D X:\GitHub\GunBox\__build-output\Ninja-MSVC-x64-Debug\CMakeFiles\CMakeTmp && powershell -noprofile -executionpolicy Bypass -file C:/SDKs/vcpkg/scripts/buildsystems/msbuild/applocal.ps1 -targetBinary X:/GitHub/GunBox/__build-output/Ninja-MSVC-x64-Debug/CMakeFiles/CMakeTmp/cmTC_20743.exe -installedDir C:/SDKs/vcpkg/installed/x64-windows/debug/bin -OutVariable out””
1> [CMake] LINK Pass 1: command “C:\PROGRA~2\Microsoft Visual Studio\2019\Preview\VC\Tools\MSVC\14.24.28207\bin\Hostx64\x64\link.exe /nologo CMakeFiles\cmTC_20743.dir\testCCompiler.c.obj /out:cmTC_20743.exe /implib:cmTC_20743.lib /pdb:cmTC_20743.pdb /version:0.0 /machine:x64 /wholearchive:clang_rt.asan_dynamic-i386.lib /wholearchive:clang_rt.asan_dynamic_runtime_thunk-i386.lib /wholearchive:vcasan.lib /debug /INCREMENTAL /subsystem:console kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:CMakeFiles\cmTC_20743.dir/intermediate.manifest CMakeFiles\cmTC_20743.dir/manifest.res” failed (exit code 1356) with the following output:
1> [CMake] LINK : fatal error LNK1356: cannot find library `clang_rt.asan_dynamic-i386.lib’ specified to be whole archived
1> [CMake] ninja: build stopped: subcommand failed.
Hello 😀 I have a question. Is there a way to reduce the memory usage of ASAN?
Too much memory used by ASAN to proceed with the test.
Our program is using 2 gigabytes by default, but when used with the ASan , it quickly reaches 4 gigabytes, resulting in out_of_memory.
There are some tuning options for the runtime which you can set via ASAN_OPTIONS. Those runtime options are independent of the compiler-side of the implementation and will be the same for Clang and MSVC.
https://github.com/google/sanitizers/wiki/AddressSanitizerFlags
Is it able to detect all the things that clang/gcc ASAN detects?
I mean all these stack out of bounds, use after scope, global buffer overflow, etc
Yes, this implementation shares a runtime with Clang on windows and it can detect the same categories of bugs.
Slight typo.
Should be
set ASAN_OPTIONS= windows_hook_rtl_allocators=true
not
ASAN_OPTIONS=set windows_hook_rtl_allocators=true
Excellent typo find, this is an important one. I’ll see if I can get this edited.
Great news! Is LeakSanitizer support coming in a future release?
this comment has been deleted.
It’s possible, though it’s lower priority than x64 support (at the moment).
vote for https://developercommunity.visualstudio.com/idea/826620/support-leaksanitizer.html
Windows has an ungodly number of ways that memory can be allocated. Some are even done by kernel drivers calling ZwMapViewOfSection on behalf of a user-mode application. How will such memory accesses be handled?
Similarly, if you use standard free() to free memory, ntdll.dll might do NtFreeVirtualMemory because that whole heap area is no longer needed. Then you get a pointer to new kernel-allocated memory somehow, such as locking a graphics buffer. What happens if the address of this mapping matches the address range that unmapped? Does the ASan runtime monitor the internals of the ntdll.dll heap code to know when address space is allocated and freed?
While I definitely would love ASan for Windows, I just worry that in a lot of use cases, it won’t be reliable.
Does visual c++ support a mechanism similar to __attribute__((no_sanitize(“address”))) in gcc and clang?
It’s nice to see Microsoft adopting useful technologies invented elsewhere, instead of remaining the company of Not Invented Here. Better late than never, I suppose.
For the wider community’s reference, I have found & reported three ASan issues so far:
ASan hooks operator delete with a size_t parameter and does not redirect through to a user-provided replacement operator delete without a size_t paramater, causing allocator mismatch:
https://developercommunity.visualstudio.com/content/problem/844890/asan-replacement-operator-delete-overload-not-call.html
ICE when compiling with ASan, generating an assembler listing containing floating point operations:
https://developercommunity.visualstudio.com/content/problem/845541/asan-ice-when-generating-assembler-listing.html
Code generation bug where ASan call to ___asan_set_shadow_00 clobbers function return value:
https://developercommunity.visualstudio.com/content/problem/845594/asan-address-sanitizer-clobbers-function-return-va.html
Thanks, Andrew R
I’m really excited about this feature! However when trying it out on Windows 7 I get the following error when trying to start the executable:
“The procedure entry point PssQuerySnapshot could not be located in the dynamic link library KERNEL32.dll.”
In what direction should I search to solve this issue?
I added reproduction steps to this Developer Community ticket:
https://developercommunity.visualstudio.com/content/problem/844040/addresssanitizer-the-procedure-entry-point-psscapt.html?childToView=852649#comment-852649
I love the idea of this feature, but sadly cannot get it to work in my test console application:
int* x = new int[100];
x[100] = 1;
I have both compiler and linker flags set, I see the runtime DLL being loaded in the debugger, but no run-time errors are being thrown…
‘apc.exe’ (Win32): Loaded ‘C:\test\build32\bin\RelWithDebInfo\clang_rt.asan_dynamic-i386.dll’.
Visual Studio Version 16.4.1…
Is there a way of testing whether this really is active?
This is a really cool feature, no slow 3rd party tools needed.
Still, in our development practice the hardest to find bugs is UMR (Uninitialized Memory Read). The application may behave normally for years and then you change compiler option or move code around and it starts producing wrong answers. My understanding MSan sanitizer can find such bugs. So, please, don’t stop on Asan only.
I still get the link error:
LNK 1356 – cannot find library ‘clang_rt.asan_dynamic-i386.lib’
For WinRT C++ projects.
I would double check that your path is set correctly, check that you’re using the correct installation of VS (if you have multiple copies of VS installed it can be easy to mix them up; at least in my personal experience), and then finally check that the ASAN package is installed when you selected the c++ tools from the Vs installer.
The @HostListener decorator is used to set up an event binding on the host element and is applied to a method. The example directive relies on the browser’s DOM API to manipulate its host element, both to add and remove class memberships and to receive the click event. Working with the DOM API in an Angular application is a useful technique, but it does mean that your directive can be used only in applications that are run in a web browser. Angular is intended to be run in a range of different execution environments, and not all of them can be assumed to provide the DOM API. Read More!