public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/94985] New: False-positive -Warray-bounds for char[1] on a non-zero offset in a referenced buffer
@ 2020-05-07 13:33 joeyjyliu at gmail dot com
  2020-05-07 19:26 ` [Bug middle-end/94985] " msebor at gcc dot gnu.org
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: joeyjyliu at gmail dot com @ 2020-05-07 13:33 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94985

            Bug ID: 94985
           Summary: False-positive -Warray-bounds for char[1] on a
                    non-zero offset in a referenced buffer
           Product: gcc
           Version: 11.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: joeyjyliu at gmail dot com
  Target Milestone: ---

Created attachment 48474
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=48474&action=edit
patch for -Warray-bounds with test case

I think the assumption in builtin_memref::set_base_and_offset
(gimple-ssa-warn-restrict.c) is not necessarily correct. It is only applicable
for flexible arrays. Actually even for flexible arrays this check is
controversial as it assumes the pointer to the struct is always a pointer to
the array of structs.  

In the attachment, there is a test file. The incorrect warning is like below.

error: ‘char* strncpy(char*, const char*, size_t)’ offset 1 from the object at
‘<unknown>’ is out of the bounds of referenced subobject ‘cstr<1>::m_data’ with
type ‘char [1]’ at offset 1 [-Werror=array-bounds]
    8 |         ::strncpy( data(), src, n );
      |         ~~~~~~~~~^~~~~~~~~~~~~~~~~~

Also in the attachment there is a suggested change. With that, the warning goes
away and the regression tests still pass. 

The original patch was sent to gcc-patches but I was advised to open a Bugzilla
ticket first. So here it is and the patch is modified to accommodate the
existing regression tests. 

$ g++ -v
Using built-in specs.
COLLECT_GCC=/local/usr/bin/g++
COLLECT_LTO_WRAPPER=/local/usr/libexec/gcc/x86_64-pc-linux-gnu/11.0.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../configure --prefix=/local/usr --disable-multilib
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 11.0.0 20200505 (experimental) (GCC)

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

* [Bug middle-end/94985] False-positive -Warray-bounds for char[1] on a non-zero offset in a referenced buffer
  2020-05-07 13:33 [Bug c++/94985] New: False-positive -Warray-bounds for char[1] on a non-zero offset in a referenced buffer joeyjyliu at gmail dot com
@ 2020-05-07 19:26 ` msebor at gcc dot gnu.org
  2020-05-07 19:26 ` msebor at gcc dot gnu.org
  2020-05-07 20:23 ` joeyjyliu at gmail dot com
  2 siblings, 0 replies; 4+ messages in thread
From: msebor at gcc dot gnu.org @ 2020-05-07 19:26 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94985

Martin Sebor <msebor at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2020-05-07
     Ever confirmed|0                           |1
           Keywords|                            |diagnostic
                 CC|                            |msebor at gcc dot gnu.org
          Component|c++                         |middle-end

--- Comment #1 from Martin Sebor <msebor at gcc dot gnu.org> ---
Thanks for opening the bug.  For reference, the gcc-patches thread is here:
https://gcc.gnu.org/pipermail/gcc-patches/2020-May/545280.html

As I said in response, I agree the warning in this instance (writing a single
byte into a one-element array) is a false positive, so confirmed.  But the fix
in the submitted patch is not correct because it both introduces testsuite
regressions and other false negatives, and doesn't prevent other similar false
positives.  A more comprehensive test with the expected diagnostics is below.

The root cause of the problem is that the builtin_memref::set_base_and_offset
(tree) function doesn't handle the sorts of cases where the access is to a
member of an object pointed to indirectly by some pointer.  The IL for the
simple test case below is:

  _1 = &q0_7(D)->a;
  q0_7(D)->p = _1;
  _2 = &MEM[(struct A1 *)q0_7(D) + 8B].a;

and set_base_and_offset() only considers A1::a when (for flexible array members
and arrays of size 0; I'm not sure we should cater to other array sizes) it
should look through the pointer and consider what it points to (i.e., look
through q0_7(D) and consider it points to &q0_7(D)->a).

The code in set_base_and_offset() is quite convoluted and should probably be
rewritten more cleanly.

That being said, the original test case, although valid, suggests it may be
derived from code that uses one-element trailing arrays as a substitute for
flexible array members (or zero-length arrays).  If that's so, GCC has been
increasingly diagnosing such misuses and so while I will work on fixing this
bug it could well be that other similar uses of the class will continue to be
diagnosed.

typedef struct A1
{
  char c;
  char a[1];
} A1;

typedef struct BA1
{
  struct A1 *p;
  char a[4];
} BA1;

void test_a1 (BA1 *q0, BA1 *q1, BA1 *q2, char *s)
{
  q0->p = (A1*)q0->a;
  __builtin_strncpy (q0->p->a, s, 1);   // { dg-bogus
"\\\[-Warray-bounds|-Wstringop-overflow" }

  q0->p = (A1*)q0->a;
  __builtin_strncpy (q0->p->a, s, 2);   // { dg-bogus
"\\\[-Warray-bounds|-Wstringop-overflow" }

  q0->p = (A1*)q0->a;
  __builtin_strncpy (q0->p->a, s, 3);   // { dg-bogus
"\\\[-Warray-bounds|-Wstringop-overflow" }

  q1->p = (A1*)q1->a;
  __builtin_strncpy (q1->p->a, s, 4);   // { dg-bogus
"\\\[-Warray-bounds|-Wstringop-overflow" }

  q2->p = (A1*)q2->a;
  __builtin_strncpy (q2->p->a, s, 5);   // { dg-warning
"\\\[-Warray-bounds|-Wstringop-overflow" }
}

struct A2
{
  char c;
  char a[2];
};

struct BA2
{
  struct A2 *p;
  char a[4];
};

void test_a2 (BA2 *q0, BA2 *q1, BA2 *q2, char *s)
{
  q0->p = (A2*)q0->a;
  __builtin_strncpy (q0->p->a, s, 1);   // { dg-bogus
"\\\[-Warray-bounds|-Wstringop-overflow" }

  q0->p = (A2*)q0->a;
  __builtin_strncpy (q0->p->a, s, 2);   // { dg-bogus
"\\\[-Warray-bounds|-Wstringop-overflow" }

  q0->p = (A2*)q0->a;
  __builtin_strncpy (q0->p->a, s, 3);   // { dg-warning
"\\\[-Warray-bounds|-Wstringop-overflow" }
}

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

* [Bug middle-end/94985] False-positive -Warray-bounds for char[1] on a non-zero offset in a referenced buffer
  2020-05-07 13:33 [Bug c++/94985] New: False-positive -Warray-bounds for char[1] on a non-zero offset in a referenced buffer joeyjyliu at gmail dot com
  2020-05-07 19:26 ` [Bug middle-end/94985] " msebor at gcc dot gnu.org
@ 2020-05-07 19:26 ` msebor at gcc dot gnu.org
  2020-05-07 20:23 ` joeyjyliu at gmail dot com
  2 siblings, 0 replies; 4+ messages in thread
From: msebor at gcc dot gnu.org @ 2020-05-07 19:26 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94985

Martin Sebor <msebor at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Assignee|unassigned at gcc dot gnu.org      |msebor at gcc dot gnu.org
             Status|NEW                         |ASSIGNED

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

* [Bug middle-end/94985] False-positive -Warray-bounds for char[1] on a non-zero offset in a referenced buffer
  2020-05-07 13:33 [Bug c++/94985] New: False-positive -Warray-bounds for char[1] on a non-zero offset in a referenced buffer joeyjyliu at gmail dot com
  2020-05-07 19:26 ` [Bug middle-end/94985] " msebor at gcc dot gnu.org
  2020-05-07 19:26 ` msebor at gcc dot gnu.org
@ 2020-05-07 20:23 ` joeyjyliu at gmail dot com
  2 siblings, 0 replies; 4+ messages in thread
From: joeyjyliu at gmail dot com @ 2020-05-07 20:23 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94985

--- Comment #2 from Joey Liu <joeyjyliu at gmail dot com> ---
Just fyi, the patch attached in this ticket is slightly different than the
patch in the mailing list (I limit it to flexible array only). It can handle
the existing test cases (no regressions). However I do think we can do better
than that since it still can't deduce the correct refsize for my test case. For
now tree::component_ref_size just returns NULL_TREE as it can't really
distinguish the regular a[1] and the flexible array a[1].

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

end of thread, other threads:[~2020-05-07 20:23 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-07 13:33 [Bug c++/94985] New: False-positive -Warray-bounds for char[1] on a non-zero offset in a referenced buffer joeyjyliu at gmail dot com
2020-05-07 19:26 ` [Bug middle-end/94985] " msebor at gcc dot gnu.org
2020-05-07 19:26 ` msebor at gcc dot gnu.org
2020-05-07 20:23 ` joeyjyliu at gmail dot com

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).