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.
Currently, we distribute IOC in two ways. First, as a tarball of executables for Ubuntu 11.10 on x86-64. If you use this tarball, 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.0-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:
If you require a patch for a more recent version of LLVM/Clang, please let us know.
This should work on Linux and MacOS. Adapt as needed for LLVM 2.9 or pre-3.1.
wget http://llvm.org/releases/3.0/llvm-3.0.tar.gz wget http://llvm.org/releases/3.0/clang-3.0.tar.gz wget http://embed.cs.utah.edu/ioc/files/llvm-3.0.patch tar xvf llvm-3.0.tar.gz cd llvm-3.0.src/tools tar xvf ../../clang-3.0.tar.gz mv clang-3.0.src clang cd clang patch -p1 < ../../../llvm-3.0.patch cd ../.. ./configure --enable-optimized --prefix=SOME_INSTALL_PATH make -j4 make install
Assuming this succeeds, 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
Make sure that libtrapub.so is readable by everyone.
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.