[cfe-dev] request for comments on patch: detecting integer undefined behaviors

John Regehr regehr at cs.utah.edu
Sun Aug 29 12:37:58 PDT 2010


Thanks again for the feedback Eli.  Attached is an improved patch that 
addresses those comments, though see below.

Any chance we can sneak this in before the 2.8 branch?

> 2. The driver changes for adding -ltrapub to the link line look
> strange, but I don't know the code well enough to properly review
> them.

Peng doesn't know of a better way to accomplish the desired result.  Can 
anyone close to this part of the code comment?

> 6. Please get rid of UndefinedBehaviorAddCheck,
> UndefinedBehaviorSubCheck, and UndefinedBehaviorMulCheck; if there are
> issues, we'd prefer to fix them in the LLVM backend (I'll try to fix
> PR7838 sometime in the near future).

This is done.  Our patched clang now crashes when compiling signed 64-bit 
multiplies on a 32-bit architecture, until that PR is fixed.

Also you asked for a single flag that requests undefined behavior 
checking, and then it keys off of the language that was chosen.  This 
turns out to be a bad idea because Clang defaults to c99 mode, causing the 
aggressive shift checks to be added.  Please just trust us that very few 
people want to see reports that for example 1<<31 is undefined!  All real 
C codes contain lots of these "problems".  In the attached patch, these 
checks are turned off by default for all languages, but can be enabled 
with -fshl-checks-extension for people who do want to try to be clean with 
respect to the c99/c++0x standards.

John
-------------- next part --------------
A non-text attachment was scrubbed...
Name: trap_handler_onefile.c
Type: text/x-csrc
Size: 24862 bytes
Desc: 
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20100829/b6a71366/attachment.c>
-------------- next part --------------
========================================================================t
Building and Installing a Checking Clang

1. Get the appropriate LLVM/Clang revision from SVN

2. Go to "llvm/tools/clang" 

3. Patch the code:

  patch -p0 < clang-<version>.patch

4. Build LLVM and Clang:
   1). cd ../.. (back to llvm)
   2). ./configure --enable-optimized
   3). make
   4). make install

Probably you'll want to make sure the new clang and clang++ are in
your path

5. Build the trap handler:

  clang -O2 -Wall -fPIC -c -o libtrapub.so trap_handler.c

6. Install the trap handler

Copy libtrapub.so to a directory in LD_LIBRARY_PATH, such as
/usr/local/lib

=========================================================================
Using the Checking Clang

Simply add this flag to clang / clang++ invocations:

    -fcatch-undefined-behavior
or  -fcatch-undefined-ansic-behavior
or  -fcatch-undefined-c99-behavior
or  -fcatch-undefined-cxx0x-behavior
or  -fcatch-undefined-cxx98-behavior 

The flags above only target integer arithmetic operations. Besides, our undefined
behavior checker still supports some other checks. To activate them, please add
"-fcatch-undefined-nonarith-behavior" option in addition to the flags above.

If users wish to invoke the GCC's intrinsic checks to examine the potential
overflows for addition, subtraction and multiplication operations, they
could add "-fuse-intrinsic" flag during compilation; otherwise, the ub checker
will only apply our own checks for basic arithmetic operations instead.

By default, the checked program will print a message to STDERR before
executing any operation that fails an undefined behavior check.  To
direct the output elsewhere, define the CLANG_UNDEFINED_LOG_METHOD
environment variable to one of STDOUT, STDERR, SYSLOG, or NONE.

By default, every instance of undefined behavior results in a message
being 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 operating with undefined
behavior is performed.  The result of this operation is undefined,
clang or clang++ does whatever it wants (probably it acts the same as
it did without the -fcatch-undefined-behavior flag, but we cannot
guarantee this).  To terminate execution following an operation with
undefined behavior, set the CLANG_UNDEFINED_ABORT environment variable
to any value.

=========================================================================
An Example

Copy this code into a file undef.c:

#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>

static int big_r (void)
{
  int a = rand();
  if ((rand()%2)==0)
    return a;
  else 
    return -a;
}

static int small_r (void)
{
  int a = rand();
  a &= 0xff;
  if ((rand()%2)==0)
    return a;
  else 
    return -a;  
}

int main (void)
{
  srand (time(NULL)+getpid());
  int i;
  int c = big_r();
  for (i=0; i<10000; i++) {
    c += big_r();
    c -= big_r();
    c *= big_r();
    c /= small_r();
    c %= small_r();
    c >>= small_r();
    c <<= small_r();
  }
  return c;
}

=========================================================================
-------------- next part --------------
A non-text attachment was scrubbed...
Name: clang-standalone-112452.patch
Type: text/x-diff
Size: 38922 bytes
Desc: 
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20100829/b6a71366/attachment.patch>


More information about the cfe-dev mailing list