public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c/103292] New: [12 regression] xorg-server-1.20.13 -Werror=array-bounds false positive on unions
@ 2021-11-16 22:47 slyfox at gcc dot gnu.org
  2021-11-17  1:32 ` [Bug c/103292] " msebor at gcc dot gnu.org
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: slyfox at gcc dot gnu.org @ 2021-11-16 22:47 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 103292
           Summary: [12 regression] xorg-server-1.20.13
                    -Werror=array-bounds false positive on unions
           Product: gcc
           Version: 12.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: slyfox at gcc dot gnu.org
  Target Milestone: ---

Created attachment 51818
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=51818&action=edit
a.c.c.orig

Initially observed build failure on xorg-server-1.20.13.

Looks like gcc detects out-of-bounds access on union of structs of different
sizes. Extracted example from unreduced a.c.c.orig (attached):

$ cat a.c.c
    typedef long unsigned int size_t;
    extern void *malloc (size_t __size) __attribute__ ((__nothrow__ ,
__leaf__)) __attribute__ ((__malloc__)) __attribute__ ((__alloc_size__ (1)))
__attribute__ ((__warn_unused_result__));

    struct _PictSolidFill {
        unsigned int type;

        char foo[20];
    };

    struct _PictHuge {
        unsigned int type;

        char foo[200];
    };

    union _SourcePict {
        // each union member has a type
        unsigned int type;

        struct _PictSolidFill maybePSF;

        // presence of this field triggers an error
        struct _PictHuge maybeHuge;
    };

    struct _Picture {
        union _SourcePict* pSourcePict;
    };

    extern
    void CreateSolidPicture(struct _Picture* pPicture);
    void CreateSolidPicture(struct _Picture* pPicture)
    {
        pPicture->pSourcePict = (union _SourcePict*) malloc(sizeof(struct
_PictSolidFill));
        pPicture->pSourcePict->type = 0;
    }

$ gcc-12.0.0 -Werror=array-bounds -c a.c.c -O2
a.c.c: In function 'CreateSolidPicture':
a.c.c:47:30: error: array subscript 'union _SourcePict[0]' is partly outside
array bounds of 'unsigned char[24]' [-Werror=array-bounds]
   47 |         pPicture->pSourcePict->type = 0;
      |                              ^~
a.c.c:46:54: note: object of size 24 allocated by 'malloc'
   46 |         pPicture->pSourcePict = (union _SourcePict*)
malloc(sizeof(struct _PictSolidFill));
      |                                                     
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors

$ gcc-12.0.0 -v
Using built-in specs.
COLLECT_GCC=/nix/store/59jdmdy3ylrpmap1bjxic1fjaq8wf96s-gcc-12.0.0/bin/gcc
COLLECT_LTO_WRAPPER=/nix/store/59jdmdy3ylrpmap1bjxic1fjaq8wf96s-gcc-12.0.0/libexec/gcc/x86_64-unknown-linux-gnu/12.0.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with:
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 12.0.0 20211114 (experimental) (GCC)

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

* [Bug c/103292] [12 regression] xorg-server-1.20.13 -Werror=array-bounds false positive on unions
  2021-11-16 22:47 [Bug c/103292] New: [12 regression] xorg-server-1.20.13 -Werror=array-bounds false positive on unions slyfox at gcc dot gnu.org
@ 2021-11-17  1:32 ` msebor at gcc dot gnu.org
  2021-11-17 21:49 ` slyfox at gcc dot gnu.org
  2021-11-17 22:34 ` [Bug middle-end/103292] " msebor at gcc dot gnu.org
  2 siblings, 0 replies; 4+ messages in thread
From: msebor at gcc dot gnu.org @ 2021-11-17  1:32 UTC (permalink / raw)
  To: gcc-bugs

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

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

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|---                         |INVALID
           Keywords|                            |diagnostic
           See Also|                            |https://gcc.gnu.org/bugzill
                   |                            |a/show_bug.cgi?id=102151
                 CC|                            |msebor at gcc dot gnu.org

--- Comment #1 from Martin Sebor <msebor at gcc dot gnu.org> ---
The warning is intended.  The program allocates an object of a size that's
smaller than the size of the type used to access it:

       pPicture->pSourcePict = (union _SourcePict*) malloc(sizeof(struct
_PictSolidFill));
        pPicture->pSourcePict->type = 0;

It's not valid to access an object of one type using an lvalue of another.  In
simple cases GCC diagnoses violations of this requirement by -Wstrict-aliasing.
 -Warray-bounds doesn't detect aliasing violations but it does detect a subset
of the problem that's apparent when the size of the lvalue's type is greater
than the size of the object.  The object must be big enough for the whole
lvalue, even if the accessed member is within the bounds of the smaller object.

The following is a smaller test case that should make the issue clearer.  See
also pr102151 for a similar report.

$ cat a.c && gcc -O2 -S -Wall a.c
struct A { char a[1]; };
struct B { char a[2]; };
union U { struct A a; struct B b; };

void* f (void)
{
  union U *p = __builtin_malloc (sizeof (struct A));
  p->a.a[0] = 0;
  return p;
}
a.c: In function ‘f’:
a.c:8:4: warning: array subscript ‘union U[0]’ is partly outside array bounds
of ‘unsigned char[1]’ [-Warray-bounds]
    8 |   p->a.a[0] = 0;
      |    ^~
a.c:7:16: note: object of size 1 allocated by ‘__builtin_malloc’
    7 |   union U *p = __builtin_malloc (sizeof (struct A));
      |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

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

* [Bug c/103292] [12 regression] xorg-server-1.20.13 -Werror=array-bounds false positive on unions
  2021-11-16 22:47 [Bug c/103292] New: [12 regression] xorg-server-1.20.13 -Werror=array-bounds false positive on unions slyfox at gcc dot gnu.org
  2021-11-17  1:32 ` [Bug c/103292] " msebor at gcc dot gnu.org
@ 2021-11-17 21:49 ` slyfox at gcc dot gnu.org
  2021-11-17 22:34 ` [Bug middle-end/103292] " msebor at gcc dot gnu.org
  2 siblings, 0 replies; 4+ messages in thread
From: slyfox at gcc dot gnu.org @ 2021-11-17 21:49 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #2 from Sergei Trofimovich <slyfox at gcc dot gnu.org> ---
(In reply to Martin Sebor from comment #1)
> The warning is intended.  The program allocates an object of a size that's
> smaller than the size of the type used to access it:
> 
>        pPicture->pSourcePict = (union _SourcePict*) malloc(sizeof(struct
> _PictSolidFill));
>         pPicture->pSourcePict->type = 0;
> 
> It's not valid to access an object of one type using an lvalue of another. 
> In simple cases GCC diagnoses violations of this requirement by
> -Wstrict-aliasing.  -Warray-bounds doesn't detect aliasing violations but it
> does detect a subset of the problem that's apparent when the size of the
> lvalue's type is greater than the size of the object.  The object must be
> big enough for the whole lvalue, even if the accessed member is within the
> bounds of the smaller object.
> 
> The following is a smaller test case that should make the issue clearer. 
> See also pr102151 for a similar report.
> 
> $ cat a.c && gcc -O2 -S -Wall a.c
> struct A { char a[1]; };
> struct B { char a[2]; };
> union U { struct A a; struct B b; };
> 
> void* f (void)
> {
>   union U *p = __builtin_malloc (sizeof (struct A));
>   p->a.a[0] = 0;
>   return p;
> }
> a.c: In function ‘f’:
> a.c:8:4: warning: array subscript ‘union U[0]’ is partly outside array
> bounds of ‘unsigned char[1]’ [-Warray-bounds]
>     8 |   p->a.a[0] = 0;
>       |    ^~
> a.c:7:16: note: object of size 1 allocated by ‘__builtin_malloc’
>     7 |   union U *p = __builtin_malloc (sizeof (struct A));
>       |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Aha, that makes sense. Filed upstream report as
https://gitlab.freedesktop.org/xorg/xserver/-/issues/1256

Related question:

It sounds like this diagnostic is somewhat related to -fstrict-aliasing. xorg
builds with -fno-strict-aliasing. Would it be fair to say the access in that
case is reasonable and -Warray-bounds is a false positive?

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

* [Bug middle-end/103292] [12 regression] xorg-server-1.20.13 -Werror=array-bounds false positive on unions
  2021-11-16 22:47 [Bug c/103292] New: [12 regression] xorg-server-1.20.13 -Werror=array-bounds false positive on unions slyfox at gcc dot gnu.org
  2021-11-17  1:32 ` [Bug c/103292] " msebor at gcc dot gnu.org
  2021-11-17 21:49 ` slyfox at gcc dot gnu.org
@ 2021-11-17 22:34 ` msebor at gcc dot gnu.org
  2 siblings, 0 replies; 4+ messages in thread
From: msebor at gcc dot gnu.org @ 2021-11-17 22:34 UTC (permalink / raw)
  To: gcc-bugs

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

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

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|INVALID                     |DUPLICATE
          Component|c                           |middle-end
             Blocks|                            |56456
                 CC|                            |jeffreyalaw at gmail dot com

--- Comment #3 from Martin Sebor <msebor at gcc dot gnu.org> ---
The originally intended purpose of this instance of -Warray-bounds was to warn
for accesses to smaller buffers by larger lvalues, like in this function:

struct A { int i; };
struct B { long j; };

struct B* make_B_from_A (const struct A *p)
{
  struct B *q = __builtin_malloc (sizeof *p);   // should be sizeof *q
  q->j = p->i;
  return q;
}

Here a warning should be issued regardless of whether -fstrict-aliasing is in
effect because the access is out of bounds.  That the warning also triggers in
instances when the problem isn't one of an out-of-bounds access but rather an
aliasing violation was incidental (i.e., I didn't set out with that as a goal),
but because -Wstrict-aliasing in GCC is very limited, seemed like a bonus.

So an argument could be (and in pr98503 in fact was) made that the instances of
-Warray-bounds where the ultimate access is strictly in bounds should be
replaced by one of -Wstrict-aliasing, which is enabled only when
-fstrict-aliasing is in effect.  I agreed and submitted a patch to do that:

  https://gcc.gnu.org/pipermail/gcc-patches/2021-January/564483.html

Regrettably, the change was rejected.  I CC the reviewer for his comments.

*** This bug has been marked as a duplicate of bug 98503 ***


Referenced Bugs:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56456
[Bug 56456] [meta-bug] bogus/missing -Warray-bounds

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

end of thread, other threads:[~2021-11-17 22:34 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-16 22:47 [Bug c/103292] New: [12 regression] xorg-server-1.20.13 -Werror=array-bounds false positive on unions slyfox at gcc dot gnu.org
2021-11-17  1:32 ` [Bug c/103292] " msebor at gcc dot gnu.org
2021-11-17 21:49 ` slyfox at gcc dot gnu.org
2021-11-17 22:34 ` [Bug middle-end/103292] " msebor at gcc dot gnu.org

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