|The IOC patches on this page are no longer supported because our code has been integrated into the Clang trunk. To get it, please build a recent Clang which will give you almost all of the IOC functionality in a more convenient package using the -fsanitize=integer command line option. Here are some additional details. This functionality is not yet in a released version of LLVM/Clang, but it should appear in the 3.3 release.|
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.
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.
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
CLANG ARITHMETIC UNDEFINED at <add.c, (9:11)> : Op: +, Reason : Signed Addition Overflow, BINARY OPERATION: left (int32): 2147483647 right (int32): 1
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.
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.
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.
The IOC license is identical to the existing LLVM license.
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.