Oscar Forner Martinez bio photo

Oscar Forner Martinez

I am software engineer at VCA Technology. Learning Linux Kernel, passionate about GNU/Linux and OSS, enjoying algorithms and data structures and coding in C and C++.

Email Twitter Google+ LinkedIn Github

Clang is a compiler front end for the C, C++, Objective-C and Objective-C++ programming languages. It uses LLVM as its back end. In this post I talk about some of the sanitizers available in Clang (some are avilable in GCC as well). They help you detect problems at run time (dynamic analysis).

As usual, I am working from an Arch Linux computer. Therefore, I can install Clang and the tools from the repository (clang). For other distributions you can find the information in the documentation.

As always, all the code used in this post is available in this repo.

The videos are made with asciinema, that means you can copy from the video.

Clang sanitizers

The Clang sanitizers available are:

In this post I show AddressSanitizer, ThreadSanitizer, MemorySanitizer and UndefinedBehaviorSanitizer. I do not talk about DataFlowSanitizer because it is a work in progress and it is really specific of the application where you need it. Moreover, I do not talk about LeakSanitizzer because it is a subset of checks from AddressSanitizer that can be run independently from it.

AddressSanitizer

Usage of freed memory

The code below is trying to use a region of memory that has been freed already. We can compile it with: When you run the previously generated executable you will get something similar to the following:

Buffer overflow

The code below is trying to access a memory region that is not part of the allocated one. We can compile it with: When you run the previously generated executable you will get something similar to the following:

Memory leak

The code below is allocating memory twice but it only frees the memory once. We can compile it with: When you run the previously generated executable you will get something similar to the following:

Double free

The code below is allocating memory once but it is freeing it twice. We can compile it with: When you run the previously generated executable you will get something similar to the following:

ThreadSanitizer

Data race

The code below has a data race due to having two threads modifying the same global variable. We can compile it with: When you run the previously generated executable you will get something similar to the following:

MemorySanitizer

Uninitialized values

The code below is reading the value stored in an array that has not been initialized. We can compile it with: When you run the previously generated executable you will get something similar to the following:

UndefinedBehaviorSanitizer

Function not returning a value

The code below contains a function that must return an integer, but it does not. We can compile it with: When you run the previously generated executable you will get something similar to the following:

Conclusion

Using these tools to compile your code to run your tests (integration test, smoke test, system test, etc) helps you catch plenty of problems. The downside is that you cannot use two sanitizers at the same time (except AddressSanitizer and LeakSanitizer). Therefore, you need multiple binaries to test your code with all these sanitizers, but the payoff is worth it.