public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Bernd Schmidt <bschmidt@redhat.com>
To: Joseph Myers <joseph@codesourcery.com>, Martin Sebor <msebor@gmail.com>
Cc: Gcc Patch List <gcc-patches@gcc.gnu.org>
Subject: Re: [PATCH] c/67882 - improve -Warray-bounds for invalid offsetof
Date: Tue, 20 Oct 2015 20:36:00 -0000	[thread overview]
Message-ID: <5626A5A0.7040003@redhat.com> (raw)
In-Reply-To: <alpine.DEB.2.10.1510201650350.7944@digraph.polyomino.org.uk>

On 10/20/2015 06:53 PM, Joseph Myers wrote:
> On Tue, 20 Oct 2015, Martin Sebor wrote:
>
>> I think -Warray-bounds should emit consistent diagnostics for invalid
>> array references regardless of the contexts. I.e., given
>>
>>      struct S {
>>          int A [5][7];
>>          int x;
>>      } s;
>>
>> these should both be diagnosed:
>>
>>      int i = offsetof (struct S, A [0][7]);
>>
>>      int *p = &s.A [0][7];
>>
>> because they are both undefined and both can lead to surprising
>> results when used.
>
> But both are valid.  &s.A [0][7] means s.A[0] + 7 (as explicitly specified
> in C11, neither the & nor the [] is evaluated in this case, but the []
> turns into a +), and s.A[0] is an object of type int[7], which decays to a
> pointer to the first element of that array, so adding 7 produces a
> just-past-end pointer.  It's not valid to dereference that pointer, but
> the pointer itself is valid (and subtracting 1 from it produces a pointer
> you can dereference).

Thanks, Joseph, this is helpful. There are a few other cases that I'm 
uncertain about and which might require additional changes to the patch; 
the one I sent was an experiment more than a finished product.

Consider

struct t { int a; int b; };
struct A { struct t v[2]; } a;

So I think we've established that
   &a.v[2]
is valid, giving a pointer just past the end of the structure. How about
   &a.v[2].a
and
   &a.v[2].b
The first of these gives the same pointer just past the end of the 
array, while the second one gives a higher address. I would expect that 
the second one is invalid, but I'm not so sure about the first one. 
Syntactically we have an access to an out-of-bounds field, but the whole 
expression just computes the valid one-past-the-end address.

I think this has an impact on the tests I quoted in my last mail:

typedef struct FA5_7 {
   int i;
   char a5_7 [5][7];
} FA5_7;

     __builtin_offsetof (FA5_7, a5_7 [0][7]),         // { dg-warning 
"index" }
     __builtin_offsetof (FA5_7, a5_7 [1][7]),         // { dg-warning 
"index" }
     __builtin_offsetof (FA5_7, a5_7 [5][0]),         // { dg-warning 
"index" }
     __builtin_offsetof (FA5_7, a5_7 [5][7]),         // { dg-warning 
"index" }

Here I think the last one of these is most likely invalid (being 8 bytes 
past the end of the object, rather than just one) and the others valid. 
Can you confirm this? (If the &a.v[2].a example is considered invalid, 
then I think the a5_7[5][0] test would be the equivalent and ought to 
also be considered invalid).

It might turn out that we have to do something like pass a pointer to an 
"at_end" boolean to recursive invocations, which would set it to true if 
the expression dealt with by the caller should not increase the address 
any further. Then, when folding the addition we check that the offset we 
have is either zero or we don't have at_end, and warn otherwise.


Bernd

  reply	other threads:[~2015-10-20 20:35 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-10-09  2:55 Martin Sebor
2015-10-15 21:59 ` [PING] " Martin Sebor
2015-10-16 12:28 ` Bernd Schmidt
2015-10-16 17:27   ` Joseph Myers
2015-10-16 19:34   ` Martin Sebor
2015-10-20 13:21     ` Bernd Schmidt
2015-10-20 15:33       ` Martin Sebor
2015-10-20 15:52         ` Bernd Schmidt
2015-10-20 16:57           ` Martin Sebor
2015-10-20 17:11             ` Joseph Myers
2015-10-20 19:10               ` Martin Sebor
2015-10-20 16:54         ` Joseph Myers
2015-10-20 20:36           ` Bernd Schmidt [this message]
2015-10-20 22:19             ` Joseph Myers
2015-10-23 11:17               ` Bernd Schmidt
2015-10-23 15:15                 ` Martin Sebor
2015-10-23 16:53                   ` Joseph Myers
2015-10-23 17:45                     ` Bernd Schmidt
2015-10-23 20:54                       ` Martin Sebor
2015-10-26 11:44                         ` Bernd Schmidt
2015-10-26 11:51                           ` Jakub Jelinek
2015-10-26 12:01                             ` Bernd Schmidt
2015-10-26 12:04                               ` Jakub Jelinek
2015-10-26 12:32                                 ` Richard Biener
2015-10-27 11:18                                   ` Bernd Schmidt
2015-11-03 19:15                         ` Martin Sebor
2015-11-07 23:38               ` Segher Boessenkool
2015-11-09 22:46                 ` Martin Sebor
2015-11-10  0:02                 ` Joseph Myers
  -- strict thread matches above, loose matches on Subject: below --
2015-10-09  2:49 Martin Sebor

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5626A5A0.7040003@redhat.com \
    --to=bschmidt@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=joseph@codesourcery.com \
    --cc=msebor@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).