[RFC] Implement Undefined Behavior Sanitizer

Jakub Jelinek jakub@redhat.com
Thu Jun 6 06:07:00 GMT 2013


On Wed, Jun 05, 2013 at 09:35:08PM +0200, Jakub Jelinek wrote:
> On Wed, Jun 05, 2013 at 09:19:10PM +0200, Jakub Jelinek wrote:
> > On Wed, Jun 05, 2013 at 07:57:28PM +0200, Marek Polacek wrote:
> > > +  tree t, tt;
> > > +  tree orig = build2 (code, TREE_TYPE (op0), op0, op1);
> > > +  tree prec = build_int_cst (TREE_TYPE (op0),
> > > +			     TYPE_PRECISION (TREE_TYPE (op0)));
> 
> BTW, also, to check that the shift count is not < 0 or >= prec, you can
> just test that fold_convert_loc (loc, unsigned_type_for (TREE_TYPE (op1)), op1)
> is LE_EXPR than precm1 (also using the unsigned type).
> While optimizers often fold it to that, you might very well just create
> fewer trees from the start.
> 
> The C99 undefined behavior of left signed shift can be tested by
> testing if ((unsigned type for op0's type) op0) >> (precm1 - y) is
> non-zero.

The C++11/C++14 undefined behavior of left signed shift can be tested
similarly, if ((unsigned type for op0's type) op0) >> (precm1 - y)
is greater than one, then it is undefined behavior.
Jason, does
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3675.html#1457
apply just to C++11/C++14, or to C++03 too?

In C++03 I see in [expr.shift]/2
"The value of E1 << E2 is E1 (interpreted as a bit pattern) left-shifted E2
bit positions; vacated bits are zero-filled. If E1 has an unsigned type,
the value of the result is E1 multiplied by the quantity 2 raised to
the power E2, reduced modulo ULONG_MAX+1 if E1 has type unsigned long,
UINT_MAX+1 otherwise."  Is that the same case as C90 then, the wording seems
to be pretty much the same?

As for controlling the C99 (or even C++11?) warning individually, either it
can be a separate suboption of -fsanitize=, like -fsanitize=shift,lshiftc99
(but then, would lshiftc99 be included in undefined and similar option
groups), or IMHO better we just convince ubsan upstream to have env var for
controlling the lshift diagnostics, gcc emits always checks for precisely
what the current -std= makes as undefined behavior (though, because of DRs
that is somewhat fuzzy, pre-DR1457 C++11 vs. post-DR1457 C++11), and users
would through env var just choose, ok, please ignore left shift warnings
of the 1 << 31 style, or ignore those and also 2 << 31 style.

	Jakub



More information about the Gcc-patches mailing list