The IOC patches on this page are no longer supported because our code has been integrated into the Clang trunk. To get it, please download or build Clang 3.3. See the Clang manual for details.




IOC: An Integer Overflow Checker for C/C++

Most large C and C++ programs contain integer overflows, such as evaluating 0U - 1 or INT_MAX + 1. Integer overflows not anticipated by developers can cause programs to behave in unexpected ways. Worse, many integer operations (signed overflow, shift-by-negative, shift-past-bitwidth, divide by zero, and more) are undefined behaviors in the C and C++ standards. When your program executes an operation with undefined behavior, the language implementation is permitted to do literally anything. Undefined behaviors are a pain to debug and cause many security vulnerabilities.

To help developers detect integer overflows, we created IOC (by modifying Clang) to dynamically detect most of C/C++'s integer undefined behaviors. Using it, we have found undefined behaviors in nearly every piece of open source software that we have checked. Relative to other checkers like gcc -ftrapv, IOC provides much more useful error messages and also checks for more kinds of problems.

Just to be clear: IOC is not a static checker. It is a dynamic checker. It adds checks to the application that is being compiled. Then, you run the application and watch the fun. Although it may tell you about problems that you aren't interested in fixing, they are all real problems -- there are no false positives.

Examples of undefined integer overflows we have reported:

We also reported bugs to BIND and OpenSSL. Most of the SPEC CPU 2006 benchmarks contain undefined overflows. Many, many codes remain to be checked!

To learn more about integer overflow in C and C++, please see our ICSE 2012 paper.

Getting IOC

There are several ways to get IOC. First, as a tarball of executables:

If you use one of these, you'll need to include its bin directory in your PATH and you'll also need to install the IOC trap handler where it can be found:

sudo cp YOUR_UNTAR_PATH/llvm-3.1-ioc-install/lib/libtrapub.so /usr/local/lib
chmod a+r /usr/local/lib/libtrapub.so

Second, as a set of patches against LLVM. Three versions of the patch are available:

Finally, if you need a more recent version than those listed here, you can always check our Github project.

How to Build and Install LLVM/Clang 3.1 with IOC

This should work on Linux and MacOS. Adapt as needed for LLVM 2.9 or 3.0.

wget http://llvm.org/releases/3.1/llvm-3.1.src.tar.gz
wget http://llvm.org/releases/3.1/clang-3.1.src.tar.gz
wget http://embed.cs.utah.edu/ioc/files/llvm-3.1.patch
tar xvf llvm-3.1.src.tar.gz 
cd llvm-3.1.src/tools
tar xvf ../../clang-3.1.src.tar.gz 
mv clang-3.1.src clang
cd clang
patch -p1 < ../../../llvm-3.1.patch 
cd ../..
./configure --enable-optimized --prefix=SOME_INSTALL_PATH 
make -j4
make install

Assuming this succeeds, add the installed bin directory into your PATH (so that clang finds the new one) and then compile and install the IOC trap handler:

wget http://embed.cs.utah.edu/ioc/files/traphandler.tar.bz2
tar xvf traphandler.tar.bz2
cd traphandler
clang -O -Wall -fPIC -c -o libtrapub.so trap_handler.c
sudo cp libtrapub.so /usr/local/lib
sudo chmod a+r /usr/local/lib/libtrapub.so

How to Test IOC

How to Use IOC

Without any extra command line options, the new clang and clang++ should emit identical code to an unpatched clang and clang++. To create checked executables, these command line options are available:

Respectively, these deal with C and C++, and with behaviors corresponding to the old and new standards. Basically the only difference is that in the new standards (C99 and C++0x), you are not allowed to shift a 1-bit into or past the sign bit, when shifting a signed integer to the left. Almost all programs do this, and it seems harmless, so we recommend using the options corresponding to the old standards.

The performance of checked code can sometimes be increased by telling the checker to use LLVM's intrinsics to check for overflows (as opposed to using explicit compare instructions). The -fcatch-undefined-use-intrinsic flag turns on this feature.

Undefined behavior checking can be disabled at function granularity using the __attribute__ ((nointegercheck)) attribute.

How to Control the Trap Handler

By default, the checked program will print a message to STDERR before executing any operation that fails an undefined behavior check. The CLANG_UNDEFINED_LOG_METHOD environment variable can be set to any of STDOUT, STDERR, SYSLOG, or NONE.

By default, every failing check causes a message to be printed. In a long checked execution, the output may become large. To suppress excessive messages, set the environment variable CLANG_UNDEFINED_MESSAGE_LIMIT to a positive integer. The number of error messages per program point and kind of error will not exceed this number.

By default, execution continues after an operation with undefined behavior is detected. The result of each such operation is hopefully the same as clang/clang++ would have produced without our patch, but we cannot easily guarantee this. To terminate execution following an operation with undefined behavior, set the CLANG_UNDEFINED_ABORT environment variable to any value.

Overhead

IOC was designed to be used during testing, not for deployed codes. Even so, checked code runs at a reasonable speed, with most codes incurring 0%--50% overhead. Certain math-intensive codes (codecs, crypto) have slowdowns in the 2X to 3X range. It seems likely that by tuning LLVM and our patch a bit, these overheads could be substantially reduced.

License

The IOC license is identical to the existing LLVM license.

Feedback

IOC is joint work between Peng Li and John Regehr at the University of Utah and Will Dietz and Vikram Adve at the University of Illinois. We would be happy to receive feedback about it.

This web page is mostly maintained by John Regehr.