Bug 44786 - -fsanitize=undefined: Turn on runtime code generation to check for undefined behavior
Summary: -fsanitize=undefined: Turn on runtime code generation to check for undefined ...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: unknown
: P3 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-07-02 16:47 UTC by Manuel López-Ibáñez
Modified: 2014-08-21 06:55 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Manuel López-Ibáñez 2010-07-02 16:47:15 UTC
Clang provides a number of ways to control code generation. The options are listed below.
-fcatch-undefined-behavior: Turn on runtime code generation to check for undefined behavior.
    This option, which defaults to off, controls whether or not Clang adds runtime checks for undefined runtime behavior. If the check fails, __builtin_trap() is used to indicate failure. The checks are:

  # Subscripting where the static type of one operand is variable which is decayed from an array type and the other operand is greater than the size of the array or less than zero.
  # Shift operators where the amount shifted is greater or equal to the promoted bit-width of the left-hand-side or less than zero.
  # If control flow reaches __builtin_unreachable.
Comment 1 Andrew Pinski 2010-07-05 01:21:58 UTC
-ftrapv checks for one undefined behavior which is not mentioned in that list.  Why isn't that listed?

>  # Shift operators where the amount shifted is greater or equal to the
promoted bit-width of the left-hand-side or less than zero.

I think C90 and C99 say slightly different things here.

Really I think this is a not good option.  It adds a huge overhead in some cases and does not fix a security issue.  In fact it allows the developer to feel more safe when in reality they are not.
Comment 2 joseph@codesourcery.com 2010-07-23 20:41:23 UTC
Subject: Re:  -fcatch-undefined-behavior: Turn on runtime code
 generation to check for undefined behavior

On Mon, 5 Jul 2010, pinskia at gcc dot gnu dot org wrote:

> -ftrapv checks for one undefined behavior which is not mentioned in that list. 
> Why isn't that listed?
> 
> >  # Shift operators where the amount shifted is greater or equal to the
> promoted bit-width of the left-hand-side or less than zero.
> 
> I think C90 and C99 say slightly different things here.

You may be thinking of the cases of signed left shift that are undefined 
only in C99 (and implementation-defined in C90).

I think having options to trap on various detectable cases of undefined 
behavior *is* a good idea, but there should be separate options for the 
separate cases.  Thus we already have -ftrapv (which, if made to work 
properly, might have different variants for strict detection of overflow 
and for allowing overflows to be folded away) and could add -ftrapv-shift 
to detect cases of shift counts out of range (similarly, -fwrapv-shift to 
give defined results for such shifts).  You might then consider a 
catch-all option to enable the various separate options.

The C1x drafts have a woefully underdefined Analyzability annex describing 
an option that bounds most kinds of undefined behavior.  If this ever gets 
better specified than it is at present, there would be various 
possibilities for an option to implement that annex, either trapping on 
particular undefined behavior or bounding what effects it has.

Comment 3 Ivan Sorokin 2012-04-08 12:11:02 UTC
> Really I think this is a not good option.  It adds a huge overhead in some
> cases and does not fix a security issue.  In fact it allows the developer to
> feel more safe when in reality they are not.

I think the rationale for this checking is not a security issue, but the ease of debugging. When a program is shipped to end user these checks could be omitted.
Comment 4 Jonathan Wakely 2012-04-08 14:06:31 UTC
Indeed.  I think it's meant to be useful for catching some of the problems that valgrind identifies, and valgrind has even more performance overhead.

That said, although I haven't used it heavily clang's -fcatch-undefined-behavior has never caught any problems for me. YMMV.
Comment 5 Andrew Pinski 2012-04-08 18:57:51 UTC
>  # Subscripting where the static type of one operand is variable which is
decayed from an array type and the other operand is greater than the size of
the array or less than zero.


That sounds like -fbounds-check.
Comment 6 Markus Trippelsdorf 2012-11-08 12:53:17 UTC
Just for fun, today I've build gcc trunk with:
CC="clang -fsanitize=undefined -w" CXX="clang++ -fsanitize=undefined -w" ~/gcc/configure --disable-bootstrap --disable-werror --disable-multilib --enable-languages=c,c++


It didn't get very far (haven't looked deeper yet):

gcc/libiberty/regex.c:6968:11: fatal error: left shift of negative value -1

gcc/gcc/genattrtab.c:625:27: fatal error: signed integer overflow: 4568797 * 613 cannot be represented in type 'int'

gcc/gcc/genautomata.c:3510:23: fatal error: shift exponent 64 is too large for 64-bit type 'set_el_t' (aka 'unsigned long')
Comment 7 Manuel López-Ibáñez 2012-11-08 13:21:54 UTC
> It didn't get very far (haven't looked deeper yet):

This PR is for implementing those checks in GCC. For things broken in GCC, you should open new PRs.

BTW, Clang now supports all these checks:

    -fsanitize=alignment: Use of a misaligned pointer or creation of a misaligned reference.
    -fsanitize=divide-by-zero: Division by zero.
    -fsanitize=float-cast-overflow: Conversion to, from, or between floating-point types which would overflow the destination.
    -fsanitize=null: Use of a null pointer or creation of a null reference.
    -fsanitize=object-size: An attempt to use bytes which the optimizer can determine are not part of the object being accessed. The sizes of objects are determined using __builtin_object_size, and consequently may be able to detect more problems at higher optimization levels.
    -fsanitize=return: In C++, reaching the end of a value-returning function without returning a value.
    -fsanitize=shift: Shift operators where the amount shifted is greater or equal to the promoted bit-width of the left hand side or less than zero, or where the left hand side is negative. For a signed left shift, also checks for signed overflow in C, and for unsigned overflow in C++.
    -fsanitize=signed-integer-overflow: Signed integer overflow, including all the checks added by -ftrapv, and checking for overflow in signed division (INT_MIN / -1).
    -fsanitize=unreachable: If control flow reaches __builtin_unreachable.
    -fsanitize=vla-bound: A variable-length array whose bound does not evaluate to a positive value.
    -fsanitize=vptr: Use of an object whose vptr indicates that it is of the wrong dynamic type, or that its lifetime has not begun or has ended. Incompatible with -fno-rtti.
Comment 8 Vincent Lefèvre 2014-04-25 08:20:36 UTC
GCC 4.9, which has just been released, has -fsanitize=undefined (and some other -fsanitize checks):

http://gcc.gnu.org/onlinedocs/gcc-4.9.0/gcc/Debugging-Options.html#Debugging-Options

However it only gives a runtime diagnostic message. It basically lacks clang's -fno-sanitize-recover option to make the program abort (useful for test suites). After that, I suppose that this enhancement would be complete (it doesn't check all kinds of undefined behavior, such as the use of uninitialized variables, but clang doesn't do this either).
Comment 9 Marek Polacek 2014-04-25 08:28:07 UTC
(In reply to Vincent Lefèvre from comment #8)
> However it only gives a runtime diagnostic message. It basically lacks
> clang's -fno-sanitize-recover option to make the program abort (useful for
> test suites). After that, I suppose that this enhancement would be complete
> (it doesn't check all kinds of undefined behavior, such as the use of
> uninitialized variables, but clang doesn't do this either).

-fno-sanitize-recover is now implemented in the mainline, see PR60275.
Comment 10 Manuel López-Ibáñez 2014-08-20 23:51:32 UTC
So what is missing here? Can we close this or not yet?
Comment 11 Vincent Lefèvre 2014-08-21 01:58:48 UTC
(In reply to Manuel López-Ibáñez from comment #10)
> So what is missing here? Can we close this or not yet?

I've tested that -fno-sanitize-recover works correctly with gcc-snapshot under Debian. So, I suppose that this can be closed.
Comment 12 Marek Polacek 2014-08-21 06:55:37 UTC
Okay, closing.