Detect Bugs using Google Sanitizers

Tutorials
Detect common bugs using sanitizers
Published

April 3, 2019

Modified

April 3, 2019

Google Sanitizers are a set of dynamic code analysis tools to detect common bugs in your code, including

Preparation

For Windows users, install gcc with MinGW, or install Clang For Mac users, install Clang using `xcode-select –install` For Linux users, make sure you have gcc installed. Open CLion and make sure that the run button is clickable with toolchains configured correctly.

Run Program with Sanitizer

To run a program with sanitizer, we need a special flag -fsanitize to the compiler. Common options include: -fsanitize=address, -fsanitize=thread, -fsanitize=memory, -fsanitize=undefined, -fsanitize=leak. A full list of options can be found here. Note that it is not possible to combine more than one of the -fsanitize=address, -fsanitize=thread, and -fsanitize=memory checkers in the same program, so you may need to toggle the options multiple times for a comprehensive checking. For testing, let’s add the following line to the CMakeLists.txt file:

set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined -g")

When you run the code, you should be able to see a sanitizer tab next to the console.

Thread Sanitizer Example

Here is a poorly-written multithreading program:

int counter = 0;
pthread_mutex_t lock;

void *inc() {
  pthread_mutex_lock(&lock); // lock not initiazlied
  counter++; // thread contention
  pthread_mutex_unlock(&lock);
  return NULL;
}

void thread_bugs() {
  pthread_t tid;
  for (int i = 0; i < 2; ++i)
    pthread_create(&tid, NULL, inc, NULL);
  printf("%d", counter); // print the result before join
  pthread_join(tid, NULL); // the first thread is not joined
}

Add the following line to the CMakeLists.txt to enable the Thread Sanitizer

set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread -g")

When the program is executing, the sanitizer will generate a report for thread-related bugs. Be aware that your program might run significantly slower with sanitizers enabled. The sanitizer noticed that two threads are reading/writing to the same memory location at the line counter++;, since we the locked is used before initialized.

There is also a data race between counter++ and the print statement since the main thread did not wait for one of the child threads.

Finally, there is a thread leak by the same reason above.

Address Sanitizer Example

To enable the Address Sanitizer, you need to add the following line to the CMakeLists.txt

set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -g")

It helps you detect heap overflow, which may happen when you incorrectly calculated the size.

Here is an example of overflowing a stack-allocated array

The Address Sanitizer also checks for using freed pointers. Note that it shows you where is memory is allocated and freed.

Here is a silly example of freeing the same memory twice, but it will be less noticeable when different pointers are pointing to the same heap location.

References

https://clang.llvm.org/docs/UsersManual.html https://www.jetbrains.com/help/clion/google-sanitizers.html