Bug 90525 - Wrong offsets in warning text for -Warray-bounds (with subobject)
Summary: Wrong offsets in warning text for -Warray-bounds (with subobject)
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 9.1.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks: Warray-bounds
  Show dependency treegraph
 
Reported: 2019-05-17 19:57 UTC by Miguel Ojeda
Modified: 2019-05-21 02:19 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2019-05-20 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Miguel Ojeda 2019-05-17 19:57:30 UTC
When fixing an -Warray-bounds warning for the kernel I noticed that the offsets were off-by-1 in at least one of the warning texts. For instance:

    struct T { char a, b, c; } t;
    void f(void) { __builtin_memset(&t.a, 0, 3); }

gives:

    x.c: In function 'f':
    x.c:2:16: warning: '__builtin_memset' offset [2, 3] from the object at 't' is out of the bounds of referenced subobject 'a' with type 'char' at offset 0 [-Warray-bounds]
        2 | void f(void) { __builtin_memset(&t.a, 0, 3); }
          |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~

Instead of [2, 3], it should be [1, 2].
Comment 1 Martin Sebor 2019-05-20 15:47:22 UTC
The warning means to say that the pointers formed by adding the offsets to the starting address are out-of-bounds.  Offset 1 from &t.a isn't out-of-bounds -- it points just past the end of t.a (it just isn't dereferenceable).  But offsets 2 and 3 definitely are out of the bounds of t.a.
Comment 2 Miguel Ojeda 2019-05-20 19:54:04 UTC
I see. About offset 1: even if it is not (formally) out of bounds, memset will end up dereferencing it. In the end, what users care about is that b and c are being overwritten (even users that know about the one-past-the-last rules may be surprised).

About offset 3, even if a particular memset function is implemented in C and ends up with a pointer to offset 3 (internally), it will never be written to, so why would it be mentioned?

Note: this is, again, just from the users' perspective :)
Comment 3 Martin Sebor 2019-05-21 02:19:42 UTC
The part of -Warray-bounds that checks offsets in calls to built-ins (as opposed to the subscript operator) is a part of the -Wrestrict implementation.  It exists mainly to avoid some pathological instances of the latter warning in corner cases.  Its goal isn't so much to detect writing past the end but to catch invalid pointers formed by calls to the built-ins.  The warning also detects past-the-end reads, including reads of padding bytes (this also isn't necessarily by design, it just falls out of the invalid pointer checking).

  struct A { char a[2]; int c; } t;

  void f (void *p)
  {
    __builtin_strcpy (t.a, "abc");   // no warning here :(
    __builtin_strcpy (p, t.a);       // but -Warray-bounds here
  }

With that said, I agree the warning could be improved/made clearer.  The above is just to explain why it works the way it does.