public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Do not sanitize left shifts for -fwrapv (PR68418)
@ 2015-11-25 14:09 Paolo Bonzini
  2015-12-04 17:51 ` Paolo Bonzini
  0 siblings, 1 reply; 7+ messages in thread
From: Paolo Bonzini @ 2015-11-25 14:09 UTC (permalink / raw)
  To: gcc-patches, joseph, jakub, mpolacek

Left shifts into the sign bit is a kind of overflow, and the
standard chooses to treat left shifts of negative values the
same way.

However, the -fwrapv option modifies the language to one where
integers are defined as two's complement---which also defines
entirely the behavior of shifts.  Disable sanitization of left
shifts when -fwrapv is in effect.  The same change was proposed
for LLVM at https://llvm.org/bugs/show_bug.cgi?id=25552.

Bootstrapped/regtested x86_64-pc-linux-gnu.  Ok for trunk, and for
GCC 5 branch after 5.3 is released?

Thanks,

Paolo

gcc:
	PR sanitizer/68418
	* c-family/c-ubsan.c (ubsan_instrument_shift): Disable
	sanitization of left shifts for wrapping signed types as well.

gcc/testsuite:
	PR sanitizer/68418
	* gcc.dg/ubsan/c99-wrapv-shift-1.c,
	gcc.dg/ubsan/c99-wrapv-shift-2.c: New testcases.

Index: c-family/c-ubsan.c
===================================================================
--- c-family/c-ubsan.c	(revision 230466)
+++ c-family/c-ubsan.c	(working copy)
@@ -128,7 +128,7 @@
      (unsigned) x >> (uprecm1 - y)
      if non-zero, is undefined.  */
   if (code == LSHIFT_EXPR
-      && !TYPE_UNSIGNED (type0)
+      && !TYPE_OVERFLOW_WRAPS (type0)
       && flag_isoc99)
     {
       tree x = fold_build2 (MINUS_EXPR, op1_utype, uprecm1,
@@ -143,7 +143,7 @@
      x < 0 || ((unsigned) x >> (uprecm1 - y))
      if > 1, is undefined.  */
   if (code == LSHIFT_EXPR
-      && !TYPE_UNSIGNED (type0)
+      && !TYPE_OVERFLOW_WRAPS (type0)
       && (cxx_dialect >= cxx11))
     {
       tree x = fold_build2 (MINUS_EXPR, op1_utype, uprecm1,
Index: testsuite/gcc.dg/ubsan/c99-wrapv-shift-1.c
===================================================================
--- testsuite/gcc.dg/ubsan/c99-wrapv-shift-1.c	(revision 0)
+++ testsuite/gcc.dg/ubsan/c99-wrapv-shift-1.c	(working copy)
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=shift -fwrapv -w -std=c99" } */
+
+int
+main (void)
+{
+  int a = -42;
+  a << 1;
+}
Index: testsuite/gcc.dg/ubsan/c99-wrapv-shift-2.c
===================================================================
--- testsuite/gcc.dg/ubsan/c99-wrapv-shift-2.c	(revision 0)
+++ testsuite/gcc.dg/ubsan/c99-wrapv-shift-2.c	(working copy)
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-fsanitize=shift -fwrapv -w -std=c99" } */
+
+int
+main (void)
+{
+  int a = 1;
+  a <<= 31;
+}

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Do not sanitize left shifts for -fwrapv (PR68418)
  2015-11-25 14:09 [PATCH] Do not sanitize left shifts for -fwrapv (PR68418) Paolo Bonzini
@ 2015-12-04 17:51 ` Paolo Bonzini
  2015-12-04 18:57   ` Jeff Law
  0 siblings, 1 reply; 7+ messages in thread
From: Paolo Bonzini @ 2015-12-04 17:51 UTC (permalink / raw)
  To: Paolo Bonzini, gcc-patches, joseph, jakub, mpolacek



On 25/11/2015 14:55, Paolo Bonzini wrote:
> Left shifts into the sign bit is a kind of overflow, and the
> standard chooses to treat left shifts of negative values the
> same way.
> 
> However, the -fwrapv option modifies the language to one where
> integers are defined as two's complement---which also defines
> entirely the behavior of shifts.  Disable sanitization of left
> shifts when -fwrapv is in effect.  The same change was proposed
> for LLVM at https://llvm.org/bugs/show_bug.cgi?id=25552.
> 
> Bootstrapped/regtested x86_64-pc-linux-gnu.  Ok for trunk, and for
> GCC 5 branch after 5.3 is released?
> 
> Thanks,
> 
> Paolo
> 
> gcc:
> 	PR sanitizer/68418
> 	* c-family/c-ubsan.c (ubsan_instrument_shift): Disable
> 	sanitization of left shifts for wrapping signed types as well.
> 
> gcc/testsuite:
> 	PR sanitizer/68418
> 	* gcc.dg/ubsan/c99-wrapv-shift-1.c,
> 	gcc.dg/ubsan/c99-wrapv-shift-2.c: New testcases.
> 
> Index: c-family/c-ubsan.c
> ===================================================================
> --- c-family/c-ubsan.c	(revision 230466)
> +++ c-family/c-ubsan.c	(working copy)
> @@ -128,7 +128,7 @@
>       (unsigned) x >> (uprecm1 - y)
>       if non-zero, is undefined.  */
>    if (code == LSHIFT_EXPR
> -      && !TYPE_UNSIGNED (type0)
> +      && !TYPE_OVERFLOW_WRAPS (type0)
>        && flag_isoc99)
>      {
>        tree x = fold_build2 (MINUS_EXPR, op1_utype, uprecm1,
> @@ -143,7 +143,7 @@
>       x < 0 || ((unsigned) x >> (uprecm1 - y))
>       if > 1, is undefined.  */
>    if (code == LSHIFT_EXPR
> -      && !TYPE_UNSIGNED (type0)
> +      && !TYPE_OVERFLOW_WRAPS (type0)
>        && (cxx_dialect >= cxx11))
>      {
>        tree x = fold_build2 (MINUS_EXPR, op1_utype, uprecm1,
> Index: testsuite/gcc.dg/ubsan/c99-wrapv-shift-1.c
> ===================================================================
> --- testsuite/gcc.dg/ubsan/c99-wrapv-shift-1.c	(revision 0)
> +++ testsuite/gcc.dg/ubsan/c99-wrapv-shift-1.c	(working copy)
> @@ -0,0 +1,9 @@
> +/* { dg-do run } */
> +/* { dg-options "-fsanitize=shift -fwrapv -w -std=c99" } */
> +
> +int
> +main (void)
> +{
> +  int a = -42;
> +  a << 1;
> +}
> Index: testsuite/gcc.dg/ubsan/c99-wrapv-shift-2.c
> ===================================================================
> --- testsuite/gcc.dg/ubsan/c99-wrapv-shift-2.c	(revision 0)
> +++ testsuite/gcc.dg/ubsan/c99-wrapv-shift-2.c	(working copy)
> @@ -0,0 +1,9 @@
> +/* { dg-do run } */
> +/* { dg-options "-fsanitize=shift -fwrapv -w -std=c99" } */
> +
> +int
> +main (void)
> +{
> +  int a = 1;
> +  a <<= 31;
> +}
> 

Ping?

Paolo

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Do not sanitize left shifts for -fwrapv (PR68418)
  2015-12-04 17:51 ` Paolo Bonzini
@ 2015-12-04 18:57   ` Jeff Law
  2015-12-04 20:48     ` Paolo Bonzini
  0 siblings, 1 reply; 7+ messages in thread
From: Jeff Law @ 2015-12-04 18:57 UTC (permalink / raw)
  To: Paolo Bonzini, Paolo Bonzini, gcc-patches, joseph, jakub, mpolacek

On 12/04/2015 10:51 AM, Paolo Bonzini wrote:
>
>
> On 25/11/2015 14:55, Paolo Bonzini wrote:
>> Left shifts into the sign bit is a kind of overflow, and the
>> standard chooses to treat left shifts of negative values the
>> same way.
>>
>> However, the -fwrapv option modifies the language to one where
>> integers are defined as two's complement---which also defines
>> entirely the behavior of shifts.  Disable sanitization of left
>> shifts when -fwrapv is in effect.  The same change was proposed
>> for LLVM at https://llvm.org/bugs/show_bug.cgi?id=25552.
>>
>> Bootstrapped/regtested x86_64-pc-linux-gnu.  Ok for trunk, and for
>> GCC 5 branch after 5.3 is released?
>>
>> Thanks,
>>
>> Paolo
>>
>> gcc:
>> 	PR sanitizer/68418
>> 	* c-family/c-ubsan.c (ubsan_instrument_shift): Disable
>> 	sanitization of left shifts for wrapping signed types as well.
>>
>> gcc/testsuite:
>> 	PR sanitizer/68418
>> 	* gcc.dg/ubsan/c99-wrapv-shift-1.c,
>> 	gcc.dg/ubsan/c99-wrapv-shift-2.c: New testcases.
Doesn't this change how pointer types are handled?

jeff

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Do not sanitize left shifts for -fwrapv (PR68418)
  2015-12-04 18:57   ` Jeff Law
@ 2015-12-04 20:48     ` Paolo Bonzini
  2015-12-04 22:46       ` Jeff Law
  2015-12-04 22:48       ` Jeff Law
  0 siblings, 2 replies; 7+ messages in thread
From: Paolo Bonzini @ 2015-12-04 20:48 UTC (permalink / raw)
  To: Jeff Law; +Cc: Paolo Bonzini, gcc-patches, joseph, jakub, mpolacek


> >> gcc:
> >> 	PR sanitizer/68418
> >> 	* c-family/c-ubsan.c (ubsan_instrument_shift): Disable
> >> 	sanitization of left shifts for wrapping signed types as well.
> >>
> >> gcc/testsuite:
> >> 	PR sanitizer/68418
> >> 	* gcc.dg/ubsan/c99-wrapv-shift-1.c,
> >> 	gcc.dg/ubsan/c99-wrapv-shift-2.c: New testcases.
> Doesn't this change how pointer types are handled?

Why would pointer types be shifted at all (at the ubsan level,
which is basically the AST)?

Paolo

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Do not sanitize left shifts for -fwrapv (PR68418)
  2015-12-04 20:48     ` Paolo Bonzini
@ 2015-12-04 22:46       ` Jeff Law
  2015-12-04 22:48       ` Jeff Law
  1 sibling, 0 replies; 7+ messages in thread
From: Jeff Law @ 2015-12-04 22:46 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Paolo Bonzini, gcc-patches, joseph, jakub, mpolacek

On 12/04/2015 01:48 PM, Paolo Bonzini wrote:
>
>>>> gcc:
>>>> 	PR sanitizer/68418
>>>> 	* c-family/c-ubsan.c (ubsan_instrument_shift): Disable
>>>> 	sanitization of left shifts for wrapping signed types as well.
>>>>
>>>> gcc/testsuite:
>>>> 	PR sanitizer/68418
>>>> 	* gcc.dg/ubsan/c99-wrapv-shift-1.c,
>>>> 	gcc.dg/ubsan/c99-wrapv-shift-2.c: New testcases.
>> Doesn't this change how pointer types are handled?
>
> Why would pointer types be shifted at all (at the ubsan level,
> which is basically the AST)?
It's not really a question of why, it's a change in behaviour. 
Previously this code would emit instrumentation objects of pointer type 
if pointers are signed on the target.  After your change it will not, in 
fact, it may trigger a checking failure.

So you'd have to argue that we don't care about sanitization of these 
operations on pointers and verify that we don't trigger a checking 
failure.  I'm really not the best judge of whether or not we want to 
instrument pointer shifts -- they're not terribly useful in general, but 
I'm always [un]pleasantly surprised at what people actually do.


Jeff

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Do not sanitize left shifts for -fwrapv (PR68418)
  2015-12-04 20:48     ` Paolo Bonzini
  2015-12-04 22:46       ` Jeff Law
@ 2015-12-04 22:48       ` Jeff Law
  2015-12-09 13:31         ` Paolo Bonzini
  1 sibling, 1 reply; 7+ messages in thread
From: Jeff Law @ 2015-12-04 22:48 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Paolo Bonzini, gcc-patches, joseph, jakub, mpolacek

On 12/04/2015 01:48 PM, Paolo Bonzini wrote:
>
>>>> gcc:
>>>> 	PR sanitizer/68418
>>>> 	* c-family/c-ubsan.c (ubsan_instrument_shift): Disable
>>>> 	sanitization of left shifts for wrapping signed types as well.
>>>>
>>>> gcc/testsuite:
>>>> 	PR sanitizer/68418
>>>> 	* gcc.dg/ubsan/c99-wrapv-shift-1.c,
>>>> 	gcc.dg/ubsan/c99-wrapv-shift-2.c: New testcases.
>> Doesn't this change how pointer types are handled?
>
> Why would pointer types be shifted at all (at the ubsan level,
> which is basically the AST)?
BTW, if you argument is that we can never get into this code with a 
shift of a pointer object, I'd like to see some kind of analysis to back 
up that assertion -- which could be as simple as pointing to FE code 
that issues an error if the user tried to do something like shift a 
pointer object.

jeff

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Do not sanitize left shifts for -fwrapv (PR68418)
  2015-12-04 22:48       ` Jeff Law
@ 2015-12-09 13:31         ` Paolo Bonzini
  0 siblings, 0 replies; 7+ messages in thread
From: Paolo Bonzini @ 2015-12-09 13:31 UTC (permalink / raw)
  To: Jeff Law, Paolo Bonzini; +Cc: gcc-patches, joseph, jakub, mpolacek



On 04/12/2015 23:48, Jeff Law wrote:
>>
>> Why would pointer types be shifted at all (at the ubsan level,
>> which is basically the AST)?
> BTW, if you argument is that we can never get into this code with a
> shift of a pointer object, I'd like to see some kind of analysis to back
> up that assertion -- which could be as simple as pointing to FE code
> that issues an error if the user tried to do something like shift a
> pointer object.

You're right, I should have qualified that better.  And actually there
is an issue with this patch, though it is not pointers.

There are only two call sites for ubsan_instrument_shift.
In c/c-typeck.c:

  /* Remember whether we're doing << or >>.  */
  bool doing_shift = false;

  /* The expression codes of the data types of the arguments tell us
     whether the arguments are integers, floating, pointers, etc.  */
  code0 = TREE_CODE (type0);
  code1 = TREE_CODE (type1);

  switch (code)
    {
    ...
    case RSHIFT_EXPR:
      ...
      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
               && code1 == INTEGER_TYPE)
        {
          doing_shift = true;
          ...
        }
      ...
    case LSHIFT_EXPR:
      ...
      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
               && code1 == INTEGER_TYPE)
        {
          doing_shift = true;
          ...
        }
      ...
    }
  ...
  if ((flag_sanitize & (SANITIZE_SHIFT | SANITIZE_DIVIDE
                        | SANITIZE_FLOAT_DIVIDE))
      && do_ubsan_in_current_function ()
      && (doing_div_or_mod || doing_shift)
      && !require_constant_value)
    {
      /* OP0 and/or OP1 might have side-effects.  */
      op0 = c_save_expr (op0);
      op1 = c_save_expr (op1);
      op0 = c_fully_fold (op0, false, NULL);
      op1 = c_fully_fold (op1, false, NULL);
      ...
      else if (doing_shift && (flag_sanitize & SANITIZE_SHIFT))
        instrument_expr = ubsan_instrument_shift (location, code, op0, op1);
    }

cp/typeck.c is the same but it doesn't handle code0 == FIXED_POINT_TYPE.

But FIXED_POINT_TYPE is not an integral type, and thus it would fail the
TYPE_OVERFLOW_WRAPS check with my patch.  I'll post an updated patch that
also removes all instrumentation in the case of fixed point types, similar
to instrument_si_overflow.

Thanks for the careful review!

Paolo

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2015-12-09 13:31 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-25 14:09 [PATCH] Do not sanitize left shifts for -fwrapv (PR68418) Paolo Bonzini
2015-12-04 17:51 ` Paolo Bonzini
2015-12-04 18:57   ` Jeff Law
2015-12-04 20:48     ` Paolo Bonzini
2015-12-04 22:46       ` Jeff Law
2015-12-04 22:48       ` Jeff Law
2015-12-09 13:31         ` Paolo Bonzini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).