CLion 2020.1 Help

Google Sanitizers

Sanitizers are open source tools for dynamic code analysis designed by Google. CLion integrates the following Sanitizers:

  • AddressSanitizer (ASan)

  • LeakSanitizer (LSan)

  • ThreadSanitizer (TSan)

  • UndefinedBehaviorSanitizer (UBSsan)

  • MemorySanitizer (MSan)

Sanitizers are implemented in Clang starting 3.1 and GCC starting 4.8 and supported on Linux x86_64 machines. AddressSanitizer and UndefinedBehaviorSanitizer are also available on macOS.

Sanitizers are based on compiler instrumentation, therefore a rebuild is required in order to use these tools.

Configuring Sanitizers in CLion

Specify compiler flags in CMakeLists.txt

  • set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=[sanitizer_name] [additional_options] [-g] [-OX]")

    For [sanitizer_name] use one of the following:

    • address for AddressSanitizer

    • leak for LeakSanitizer

    • thread for ThreadSanitizer

    • undefined for UndefinedBehaviorSanitizer (other options are also available, see the UBSan section)

    • memory for MemorySanitizer

    [Additional_flags] are other compilation flags, such as -fno-omit-frame-pointer, fsanitize-recover/fno-sanitize-recover, -fsanitize-blacklist, etc.

    Use [-g] to have file names and line numbers included in warning messages.

    Add optimization level [-OX] to get reasonable performance (see recommendations in the particular Sanitizer documentation).

Configure the Sanitizers settings

  • Navigate to Settings / Preferences | Build, Execution, Deployment | Dynamic Analysis Tools | Sanitizers and set up the following:

    • Run-time flags
      In this section, specify the run-time options for each Sanitizer. You can do that manually or by clicking the Import flags from existing environment variables button (this button becomes available if the variables ASAN/MSAN/LSAN/TSAN_OPTIONS are presented). See Sanitizer Common flags.

    • Use visual representation for Sanitizer's output
      Set this checkbox to have a tree-view output with the Preview Editor and Frame Information:

      CLion Sanitizers visual output
      For the visualized output to be available, switch to Clang at least 3.8.0 or GCC at least 5.0.0 (see this instruction for details on how to change a compiler in CLion).

      When this checkbox is cleared, or the compiler does not fit the requirements, the sanitizers output is presented in a plain text form:

      CLion Sanitizers plain output

Provide the path to llvm-symbolizer

  • To let Sanitizers convert addresses into source code locations and make stack-traces easy to understand, ensure that the PATH or *SAN_SYMBOLIZER_PATH environment variable contains the location of llvm-symbolizer.

    Note that PATH should point to the directory of llvm-symbolizer (for example, /usr/bin/), while *SAN_SYMBOLIZER_PATH should point to the particular binary (like /usr/dir/llvm-symbolizer).

    In case of using Clang compiler, you will get a notification from CLion if none of the PATH or *SAN_SYMBOLIZER_PATH variables points to llvm-symbolizer:

    cl sanitizer symbolizerwarning png

AddressSanitizer

AddressSanitizer (ASan) is a memory corruption detector, capable of finding the following types of bugs:

  • Heap-, stack-, and global buffer overflow

  • Use-after-free (dangling pointer dereference)

  • Use-after-scope -fsanitize-address-use-after-scope

  • Use-after-return (pass detect_stack_use_after_return=1 to ASAN_OPTIONS)

  • Double free, invalid free

  • Initialization order bugs

As an example, consider the following code fragment:

int global_array[100] = {-1}; int main(int argc, char **argv) { return global_array[argc + 100]; // global buffer overflow }

When built with -fsanitize=address -fno-omit-frame-pointer -O1 flags, this program will exit with a non-zero code due to the global buffer overflow detected by AddressSanitizer:

AddressSanitizer

Note that ASan halts on the first detected error. To change this behavior and make ASan continue running after reporting the first error, add -fsanitize-recover=address to compiler flags and halt_on_error=false to ASAN_OPTIONS.

LeakSanitizer

LeakSanitizer (LSan) is a memory leak detector. In a stand-alone mode, this Sanitizer is a run-time tool that does not require compiler instrumentation. However, LSan is also integrated into AddressSanitizer, so you can combine them to get both memory errors and leak detection.

To enable LeakSanitizer as a part of AddressSanitizer, pass detect_leaks=1 to the ASAN_OPTIONS variable. To run ASan-instrumented program without leak detection, set detect_leaks=0.

To run LSan only (and avoid the ASan's slowdown), use -fsanitize=leak instead of -fsanitize=address.

The following code leads to a memory leak due to no-deleting of a heap-allocated object:

int main(){ int *x = new int(10); return 0; }

LSan detects and reports the problem:

LeakSanitizer

ThreadSanitizer

ThreadSanitizer (TSan) is a data race detector. Data races occur when multiple threads access the same memory without synchronization and at least one access is a write.

Take a look at the following code that produces data races:

#include <pthread.h> #include <stdio.h> int Global; void *Thread1(void *x) { Global++; return NULL; } void *Thread2(void *x) { Global--; return NULL; } int main() { pthread_t t[2]; pthread_create(&t[0], NULL, Thread1, NULL); pthread_create(&t[1], NULL, Thread2, NULL); pthread_join(t[0], NULL); pthread_join(t[1], NULL); }

When you run this program compiled with -fsanitize=thread -fPIE -pie -g, TSan prints a report of a data race (refer to ThreadSanitizerReportFormat for details of the output format):

ThreadSanitizer

UndefinedBehaviourSanitizer

UndefinedBehaviorSanitizer (UBSan) is a runtime checker for undefined behavior, which is a result of any operation with unspecified semantics, such as dividing by zero, null pointer dereference, or usage of an uninitialized non-static variable.

UBSan catches various kinds of undefined behavior, see the full list at clang.llvm.org. You can turn the checks on one by one, or use flags for check groups -fsanitize=undefined, -fsanitize=integer, and -fsanitize=nullability.

Code below illustrates the situation of an undefined result of a shift operation:

int main(){ int i = 2048; i <<= 28; return 0; }

If you compile this code with the -fsanitize=undefined flag (alternatively, use -fsanitize=shift) and launch, the program will finish successfully despite of the UBSan warning:

UndefinedBehaviorSanitizer

To make a program exit due to UBSan's diagnostics, use the -fno-sanitize-recover option.

MemorySanitizer

MemorySanitizer (MSan) is a detector of uninitialized memory reads. This Sanitizer finds the cases when stack- or heap-allocated memory is read before it is written. MSan is also capable of tracking uninitialized bits in a bitfield.

MSan can track back the origins of an uninitialized value to where it was created and report this information. Pass the -fsanitize-memory-track-origins flag to enable this functionality.

To efficiently use MSan, compile your program with -fsanitize=memory -fPIE -pie -fno-omit-frame-pointer -g, add -fno-optimize-sibling-calls and -O1 or later.

Find the example of code with an uninitialized read and the corresponding MSan output below:

int main(int argc, char** argv) { int* a = new int[10]; a[5] = 0; if (a[argc]) std::cout << a[3]; return 0; }

MemorySanitizer

Last modified: 08 May 2020