public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* Gcc 8.1, -O2 optimisation build failure
@ 2018-07-30 11:26 Wei Liu
  2018-07-30 13:36 ` U.Mutlu
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Wei Liu @ 2018-07-30 11:26 UTC (permalink / raw)
  To: gcc-help; +Cc: Wei Liu

Hello,

We have a program which fails to build with gcc 8.1 -m32 -O2 (version
Debian 8.1.0-12). We couldn't figure out how the optimiser came up with
the idea that array bounds could become negative. Any help would be
appreciated. The attached code has been simplified from the original to
reproduce the issue.

The same code snippet builds find with 8.1 debug build and older
versions of gcc.

$ gcc  -m32 -march=i686 -std=gnu99 -Wall -O2   -Werror   -c -o t.o t.c
t.c: In function 'func':
t.c:41:9: error: 'memcpy' offset [-204, -717] is out of the bounds [0, 216] of object 'ctrl' with type 'struct kdd_ctrl' [-Werror=array-bounds]
         memcpy(buf, ((uint8_t *)&ctrl.c32) + offset, len);
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
t.c:27:21: note: 'ctrl' declared here
     struct kdd_ctrl ctrl;

<code>
#include <stdint.h>
#include <string.h>

struct kdd_ctrl_32 {
    uint8_t _[84];
};

struct kdd_ctrl_64 {
    uint8_t _[216];
};

struct kdd_ctrl {
    union {
        struct kdd_ctrl_32 c32;
        struct kdd_ctrl_64 c64;
    };
};

typedef struct {
    uint8_t buf[17 + 65536];
    uint32_t length_req;
    uint64_t addr;
} kdd_state;

void func(kdd_state *s)
{
    struct kdd_ctrl ctrl;
    uint8_t *buf = s->buf + 17 + 57;
    uint32_t len = s->length_req;
    uint64_t addr = s->addr;

    uint32_t offset = addr;

    /* 32-bit control-register space starts at 0x[2]cc, for 84 bytes */
    if (offset > 0x200)
        offset -= 0x200;
    offset -= 0xcc;
    if (offset > sizeof ctrl.c32 || offset + len > sizeof ctrl.c32) {
        len = 0;
    } else {
        memcpy(buf, ((uint8_t *)&ctrl.c32) + offset, len);
    }
}
</code>

Regards,
Wei.

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

* Re: Gcc 8.1, -O2 optimisation build failure
  2018-07-30 11:26 Gcc 8.1, -O2 optimisation build failure Wei Liu
@ 2018-07-30 13:36 ` U.Mutlu
  2018-07-30 13:47   ` Wei Liu
  2018-07-30 14:14   ` U.Mutlu
  2018-07-30 14:38 ` Wei Liu
  2018-08-01 21:07 ` Martin Sebor
  2 siblings, 2 replies; 10+ messages in thread
From: U.Mutlu @ 2018-07-30 13:36 UTC (permalink / raw)
  To: Wei Liu, gcc-help

I think there's a mismatch with decimal and hexadecimal values.

Write/simulate testcases for some border cases of offset, for example 0, 128, 
256, 512, 768.


Wei Liu wrote on 07/30/2018 10:08 AM:
> Hello,
>
> We have a program which fails to build with gcc 8.1 -m32 -O2 (version
> Debian 8.1.0-12). We couldn't figure out how the optimiser came up with
> the idea that array bounds could become negative. Any help would be
> appreciated. The attached code has been simplified from the original to
> reproduce the issue.
>
> The same code snippet builds find with 8.1 debug build and older
> versions of gcc.
>
> $ gcc  -m32 -march=i686 -std=gnu99 -Wall -O2   -Werror   -c -o t.o t.c
> t.c: In function 'func':
> t.c:41:9: error: 'memcpy' offset [-204, -717] is out of the bounds [0, 216] of object 'ctrl' with type 'struct kdd_ctrl' [-Werror=array-bounds]
>           memcpy(buf, ((uint8_t *)&ctrl.c32) + offset, len);
>           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> t.c:27:21: note: 'ctrl' declared here
>       struct kdd_ctrl ctrl;
>
> <code>
> #include <stdint.h>
> #include <string.h>
>
> struct kdd_ctrl_32 {
>      uint8_t _[84];
> };
>
> struct kdd_ctrl_64 {
>      uint8_t _[216];
> };
>
> struct kdd_ctrl {
>      union {
>          struct kdd_ctrl_32 c32;
>          struct kdd_ctrl_64 c64;
>      };
> };
>
> typedef struct {
>      uint8_t buf[17 + 65536];
>      uint32_t length_req;
>      uint64_t addr;
> } kdd_state;
>
> void func(kdd_state *s)
> {
>      struct kdd_ctrl ctrl;
>      uint8_t *buf = s->buf + 17 + 57;
>      uint32_t len = s->length_req;
>      uint64_t addr = s->addr;
>
>      uint32_t offset = addr;
>
>      /* 32-bit control-register space starts at 0x[2]cc, for 84 bytes */
>      if (offset > 0x200)
>          offset -= 0x200;
>      offset -= 0xcc;
>      if (offset > sizeof ctrl.c32 || offset + len > sizeof ctrl.c32) {
>          len = 0;
>      } else {
>          memcpy(buf, ((uint8_t *)&ctrl.c32) + offset, len);
>      }
> }
> </code>
>
> Regards,
> Wei.
>

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

* Re: Gcc 8.1, -O2 optimisation build failure
  2018-07-30 13:36 ` U.Mutlu
@ 2018-07-30 13:47   ` Wei Liu
  2018-07-30 14:14   ` U.Mutlu
  1 sibling, 0 replies; 10+ messages in thread
From: Wei Liu @ 2018-07-30 13:47 UTC (permalink / raw)
  To: U.Mutlu; +Cc: Wei Liu, gcc-help

On Mon, Jul 30, 2018 at 02:59:39PM +0200, U.Mutlu wrote:
> I think there's a mismatch with decimal and hexadecimal values.
> 

You suggested that -204 is actually 0xffffff34, right? We considered
that, too.

> Write/simulate testcases for some border cases of offset, for example 0,
> 128, 256, 512, 768.

It seems that the line offset -= 0xcc is triggering this behaviour.
Changing 0xcc to other values causes the bounds to change.

Suppose offset underflows, the if statement becomes true, memcpy won't
be invoked at all. In that case, why would gcc complain the indices are
out of bounds?

Further pointers are appreciated.

Wei.

> 
> 
> Wei Liu wrote on 07/30/2018 10:08 AM:
> > Hello,
> > 
> > We have a program which fails to build with gcc 8.1 -m32 -O2 (version
> > Debian 8.1.0-12). We couldn't figure out how the optimiser came up with
> > the idea that array bounds could become negative. Any help would be
> > appreciated. The attached code has been simplified from the original to
> > reproduce the issue.
> > 
> > The same code snippet builds find with 8.1 debug build and older
> > versions of gcc.
> > 
> > $ gcc  -m32 -march=i686 -std=gnu99 -Wall -O2   -Werror   -c -o t.o t.c
> > t.c: In function 'func':
> > t.c:41:9: error: 'memcpy' offset [-204, -717] is out of the bounds [0, 216] of object 'ctrl' with type 'struct kdd_ctrl' [-Werror=array-bounds]
> >           memcpy(buf, ((uint8_t *)&ctrl.c32) + offset, len);
> >           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > t.c:27:21: note: 'ctrl' declared here
> >       struct kdd_ctrl ctrl;
> > 
> > <code>
> > #include <stdint.h>
> > #include <string.h>
> > 
> > struct kdd_ctrl_32 {
> >      uint8_t _[84];
> > };
> > 
> > struct kdd_ctrl_64 {
> >      uint8_t _[216];
> > };
> > 
> > struct kdd_ctrl {
> >      union {
> >          struct kdd_ctrl_32 c32;
> >          struct kdd_ctrl_64 c64;
> >      };
> > };
> > 
> > typedef struct {
> >      uint8_t buf[17 + 65536];
> >      uint32_t length_req;
> >      uint64_t addr;
> > } kdd_state;
> > 
> > void func(kdd_state *s)
> > {
> >      struct kdd_ctrl ctrl;
> >      uint8_t *buf = s->buf + 17 + 57;
> >      uint32_t len = s->length_req;
> >      uint64_t addr = s->addr;
> > 
> >      uint32_t offset = addr;
> > 
> >      /* 32-bit control-register space starts at 0x[2]cc, for 84 bytes */
> >      if (offset > 0x200)
> >          offset -= 0x200;
> >      offset -= 0xcc;
> >      if (offset > sizeof ctrl.c32 || offset + len > sizeof ctrl.c32) {
> >          len = 0;
> >      } else {
> >          memcpy(buf, ((uint8_t *)&ctrl.c32) + offset, len);
> >      }
> > }
> > </code>
> > 
> > Regards,
> > Wei.
> > 
> 

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

* Re: Gcc 8.1, -O2 optimisation build failure
  2018-07-30 13:36 ` U.Mutlu
  2018-07-30 13:47   ` Wei Liu
@ 2018-07-30 14:14   ` U.Mutlu
  2018-07-30 14:23     ` Wei Liu
  1 sibling, 1 reply; 10+ messages in thread
From: U.Mutlu @ 2018-07-30 14:14 UTC (permalink / raw)
  To: Wei Liu, gcc-help

...
     if (/* offset > sizeof ctrl.c32 || */ offset + len > sizeof ctrl.c32)
     {
         len = 0;
         printf("A: s->addr=%zu off=%zu len=0\n", s->addr, (size_t) offset);
     }
     else
     {
         const uint8_t* p = ((uint8_t *)&ctrl.c32) + offset;
         printf("B: s->addr=%zu off=%zu poff=%ld\n", s->addr, (size_t) offset, 
p - ((uint8_t *)&ctrl.c32));
         memcpy(buf, p, len);
     }
}

int main()
{
   kdd_state s;
   s.buf[0]     = 0;
   s.length_req = 84;
   for (int i = 0; i <= 1000; i += 10)
     {
       s.addr = i;
       func(&s);
     }

   return 0;
}

Just compiling and executing normal 64bit:

$ gcc -Wall -Wextra -std=gnu99 -O2 t.c
$ ./a.out
A: s->addr=0 off=4294967092 len=0
A: s->addr=10 off=4294967102 len=0
A: s->addr=20 off=4294967112 len=0
A: s->addr=30 off=4294967122 len=0
A: s->addr=40 off=4294967132 len=0
A: s->addr=50 off=4294967142 len=0
A: s->addr=60 off=4294967152 len=0
A: s->addr=70 off=4294967162 len=0
A: s->addr=80 off=4294967172 len=0
A: s->addr=90 off=4294967182 len=0
A: s->addr=100 off=4294967192 len=0
A: s->addr=110 off=4294967202 len=0
B: s->addr=120 off=4294967212 poff=4294967212
Segmentation fault

IMO, the code is buggy as hell.


U.Mutlu wrote on 07/30/2018 02:59 PM:
> I think there's a mismatch with decimal and hexadecimal values.
>
> Write/simulate testcases for some border cases of offset, for example 0, 128,
> 256, 512, 768.
>
>
> Wei Liu wrote on 07/30/2018 10:08 AM:
>> Hello,
>>
>> We have a program which fails to build with gcc 8.1 -m32 -O2 (version
>> Debian 8.1.0-12). We couldn't figure out how the optimiser came up with
>> the idea that array bounds could become negative. Any help would be
>> appreciated. The attached code has been simplified from the original to
>> reproduce the issue.
>>
>> The same code snippet builds find with 8.1 debug build and older
>> versions of gcc.
>>
>> $ gcc  -m32 -march=i686 -std=gnu99 -Wall -O2   -Werror   -c -o t.o t.c
>> t.c: In function 'func':
>> t.c:41:9: error: 'memcpy' offset [-204, -717] is out of the bounds [0, 216]
>> of object 'ctrl' with type 'struct kdd_ctrl' [-Werror=array-bounds]
>>           memcpy(buf, ((uint8_t *)&ctrl.c32) + offset, len);
>>           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> t.c:27:21: note: 'ctrl' declared here
>>       struct kdd_ctrl ctrl;
>>
>> <code>
>> #include <stdint.h>
>> #include <string.h>
>>
>> struct kdd_ctrl_32 {
>>      uint8_t _[84];
>> };
>>
>> struct kdd_ctrl_64 {
>>      uint8_t _[216];
>> };
>>
>> struct kdd_ctrl {
>>      union {
>>          struct kdd_ctrl_32 c32;
>>          struct kdd_ctrl_64 c64;
>>      };
>> };
>>
>> typedef struct {
>>      uint8_t buf[17 + 65536];
>>      uint32_t length_req;
>>      uint64_t addr;
>> } kdd_state;
>>
>> void func(kdd_state *s)
>> {
>>      struct kdd_ctrl ctrl;
>>      uint8_t *buf = s->buf + 17 + 57;
>>      uint32_t len = s->length_req;
>>      uint64_t addr = s->addr;
>>
>>      uint32_t offset = addr;
>>
>>      /* 32-bit control-register space starts at 0x[2]cc, for 84 bytes */
>>      if (offset > 0x200)
>>          offset -= 0x200;
>>      offset -= 0xcc;
>>      if (offset > sizeof ctrl.c32 || offset + len > sizeof ctrl.c32) {
>>          len = 0;
>>      } else {
>>          memcpy(buf, ((uint8_t *)&ctrl.c32) + offset, len);
>>      }
>> }
>> </code>
>>
>> Regards,
>> Wei.
>>
>
>

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

* Re: Gcc 8.1, -O2 optimisation build failure
  2018-07-30 14:14   ` U.Mutlu
@ 2018-07-30 14:23     ` Wei Liu
  0 siblings, 0 replies; 10+ messages in thread
From: Wei Liu @ 2018-07-30 14:23 UTC (permalink / raw)
  To: U.Mutlu; +Cc: Wei Liu, gcc-help

On Mon, Jul 30, 2018 at 03:46:58PM +0200, U.Mutlu wrote:
> ...
>     if (/* offset > sizeof ctrl.c32 || */ offset + len > sizeof ctrl.c32)

But here you commented out offset > sizeof ctrl.c32? The original code
isn't like that. With it commented out, of course you're going to hit
"B" when offset underflows -- I get the same output as you, too.

With that predicate uncommented, your code snippet won't segfault.

>     {
>         len = 0;
>         printf("A: s->addr=%zu off=%zu len=0\n", s->addr, (size_t) offset);
>     }
>     else
>     {
>         const uint8_t* p = ((uint8_t *)&ctrl.c32) + offset;
>         printf("B: s->addr=%zu off=%zu poff=%ld\n", s->addr, (size_t)
> offset, p - ((uint8_t *)&ctrl.c32));
>         memcpy(buf, p, len);
>     }
> }
> 
> int main()
> {
>   kdd_state s;
>   s.buf[0]     = 0;
>   s.length_req = 84;
>   for (int i = 0; i <= 1000; i += 10)
>     {
>       s.addr = i;
>       func(&s);
>     }
> 
>   return 0;
> }
> 
> Just compiling and executing normal 64bit:
> 
> $ gcc -Wall -Wextra -std=gnu99 -O2 t.c
> $ ./a.out
> A: s->addr=0 off=4294967092 len=0
> A: s->addr=10 off=4294967102 len=0
> A: s->addr=20 off=4294967112 len=0
> A: s->addr=30 off=4294967122 len=0
> A: s->addr=40 off=4294967132 len=0
> A: s->addr=50 off=4294967142 len=0
> A: s->addr=60 off=4294967152 len=0
> A: s->addr=70 off=4294967162 len=0
> A: s->addr=80 off=4294967172 len=0
> A: s->addr=90 off=4294967182 len=0
> A: s->addr=100 off=4294967192 len=0
> A: s->addr=110 off=4294967202 len=0
> B: s->addr=120 off=4294967212 poff=4294967212
> Segmentation fault
> 
> IMO, the code is buggy as hell.

I don't necessarily disagree, because this code comes from
reverse-engineering of a protocol. :-/

Wei.

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

* Re: Gcc 8.1, -O2 optimisation build failure
  2018-07-30 11:26 Gcc 8.1, -O2 optimisation build failure Wei Liu
  2018-07-30 13:36 ` U.Mutlu
@ 2018-07-30 14:38 ` Wei Liu
  2018-07-30 14:42   ` U.Mutlu
  2018-08-01 21:07 ` Martin Sebor
  2 siblings, 1 reply; 10+ messages in thread
From: Wei Liu @ 2018-07-30 14:38 UTC (permalink / raw)
  To: gcc-help; +Cc: Wei Liu

On Mon, Jul 30, 2018 at 09:08:31AM +0100, Wei Liu wrote:
> Hello,
> 
> We have a program which fails to build with gcc 8.1 -m32 -O2 (version
> Debian 8.1.0-12). We couldn't figure out how the optimiser came up with
> the idea that array bounds could become negative. Any help would be
> appreciated. The attached code has been simplified from the original to
> reproduce the issue.
> 
> The same code snippet builds find with 8.1 debug build and older
> versions of gcc.
> 
> $ gcc  -m32 -march=i686 -std=gnu99 -Wall -O2   -Werror   -c -o t.o t.c
> t.c: In function 'func':
> t.c:41:9: error: 'memcpy' offset [-204, -717] is out of the bounds [0, 216] of object 'ctrl' with type 'struct kdd_ctrl' [-Werror=array-bounds]
>          memcpy(buf, ((uint8_t *)&ctrl.c32) + offset, len);
>          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> t.c:27:21: note: 'ctrl' declared here
>      struct kdd_ctrl ctrl;
> 
> <code>
> #include <stdint.h>
> #include <string.h>
> 
> struct kdd_ctrl_32 {
>     uint8_t _[84];
> };
> 
> struct kdd_ctrl_64 {
>     uint8_t _[216];
> };
> 
> struct kdd_ctrl {
>     union {
>         struct kdd_ctrl_32 c32;
>         struct kdd_ctrl_64 c64;
>     };
> };
> 
> typedef struct {
>     uint8_t buf[17 + 65536];
>     uint32_t length_req;
>     uint64_t addr;
> } kdd_state;
> 
> void func(kdd_state *s)
> {
>     struct kdd_ctrl ctrl;
>     uint8_t *buf = s->buf + 17 + 57;
>     uint32_t len = s->length_req;
>     uint64_t addr = s->addr;

Sorry for not mentioning this earlier, length_req(len) is bound within
[0, 65535] here. I deleted the bound check because it didn't affect how
the error is triggered.

> 
>     uint32_t offset = addr;
> 
>     /* 32-bit control-register space starts at 0x[2]cc, for 84 bytes */
>     if (offset > 0x200)
>         offset -= 0x200;
>     offset -= 0xcc;
>     if (offset > sizeof ctrl.c32 || offset + len > sizeof ctrl.c32) {
>         len = 0;
>     } else {
>         memcpy(buf, ((uint8_t *)&ctrl.c32) + offset, len);
>     }
> }
> </code>
> 
> Regards,
> Wei.

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

* Re: Gcc 8.1, -O2 optimisation build failure
  2018-07-30 14:38 ` Wei Liu
@ 2018-07-30 14:42   ` U.Mutlu
  2018-07-30 23:29     ` Wei Liu
  0 siblings, 1 reply; 10+ messages in thread
From: U.Mutlu @ 2018-07-30 14:42 UTC (permalink / raw)
  To: Wei Liu, gcc-help

So, if you assume the bug happens only with the gcc from the
Debian repository, then maybe you should contact them too:
https://packages.debian.org/buster/gcc
https://bugs.debian.org/cgi-bin/pkgreport.cgi?pkg=gcc;dist=unstable


Wei Liu wrote on 07/30/2018 04:22 PM:
> On Mon, Jul 30, 2018 at 09:08:31AM +0100, Wei Liu wrote:
>> Hello,
>>
>> We have a program which fails to build with gcc 8.1 -m32 -O2 (version
>> Debian 8.1.0-12). We couldn't figure out how the optimiser came up with
>> the idea that array bounds could become negative. Any help would be
>> appreciated. The attached code has been simplified from the original to
>> reproduce the issue.
>>
>> The same code snippet builds find with 8.1 debug build and older
>> versions of gcc.
>>
>> $ gcc  -m32 -march=i686 -std=gnu99 -Wall -O2   -Werror   -c -o t.o t.c
>> t.c: In function 'func':
>> t.c:41:9: error: 'memcpy' offset [-204, -717] is out of the bounds [0, 216] of object 'ctrl' with type 'struct kdd_ctrl' [-Werror=array-bounds]
>>           memcpy(buf, ((uint8_t *)&ctrl.c32) + offset, len);
>>           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> t.c:27:21: note: 'ctrl' declared here
>>       struct kdd_ctrl ctrl;
>>
>> <code>
>> #include <stdint.h>
>> #include <string.h>
>>
>> struct kdd_ctrl_32 {
>>      uint8_t _[84];
>> };
>>
>> struct kdd_ctrl_64 {
>>      uint8_t _[216];
>> };
>>
>> struct kdd_ctrl {
>>      union {
>>          struct kdd_ctrl_32 c32;
>>          struct kdd_ctrl_64 c64;
>>      };
>> };
>>
>> typedef struct {
>>      uint8_t buf[17 + 65536];
>>      uint32_t length_req;
>>      uint64_t addr;
>> } kdd_state;
>>
>> void func(kdd_state *s)
>> {
>>      struct kdd_ctrl ctrl;
>>      uint8_t *buf = s->buf + 17 + 57;
>>      uint32_t len = s->length_req;
>>      uint64_t addr = s->addr;
>
> Sorry for not mentioning this earlier, length_req(len) is bound within
> [0, 65535] here. I deleted the bound check because it didn't affect how
> the error is triggered.
>
>>
>>      uint32_t offset = addr;
>>
>>      /* 32-bit control-register space starts at 0x[2]cc, for 84 bytes */
>>      if (offset > 0x200)
>>          offset -= 0x200;
>>      offset -= 0xcc;
>>      if (offset > sizeof ctrl.c32 || offset + len > sizeof ctrl.c32) {
>>          len = 0;
>>      } else {
>>          memcpy(buf, ((uint8_t *)&ctrl.c32) + offset, len);
>>      }
>> }
>> </code>
>>
>> Regards,
>> Wei.
>

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

* Re: Gcc 8.1, -O2 optimisation build failure
  2018-07-30 14:42   ` U.Mutlu
@ 2018-07-30 23:29     ` Wei Liu
  0 siblings, 0 replies; 10+ messages in thread
From: Wei Liu @ 2018-07-30 23:29 UTC (permalink / raw)
  To: U.Mutlu; +Cc: Wei Liu, gcc-help

On Mon, Jul 30, 2018 at 04:38:17PM +0200, U.Mutlu wrote:
> So, if you assume the bug happens only with the gcc from the
> Debian repository, then maybe you should contact them too:
> https://packages.debian.org/buster/gcc
> https://bugs.debian.org/cgi-bin/pkgreport.cgi?pkg=gcc;dist=unstable

No problem. I will try to figure out if this is Debian only or not. I
suspect not because someone has tried to fix a similar issue on Fedora.

Thanks for your help.

Wei.

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

* Re: Gcc 8.1, -O2 optimisation build failure
  2018-07-30 11:26 Gcc 8.1, -O2 optimisation build failure Wei Liu
  2018-07-30 13:36 ` U.Mutlu
  2018-07-30 14:38 ` Wei Liu
@ 2018-08-01 21:07 ` Martin Sebor
  2018-08-02  8:27   ` Wei Liu
  2 siblings, 1 reply; 10+ messages in thread
From: Martin Sebor @ 2018-08-01 21:07 UTC (permalink / raw)
  To: Wei Liu, gcc-help

On 07/30/2018 02:08 AM, Wei Liu wrote:
> Hello,
>
> We have a program which fails to build with gcc 8.1 -m32 -O2 (version
> Debian 8.1.0-12). We couldn't figure out how the optimiser came up with
> the idea that array bounds could become negative. Any help would be
> appreciated. The attached code has been simplified from the original to
> reproduce the issue.

It looks like a bug in the implementation of the warning.
The offset is determined not to be in the range [-205, -716]
(pointer offsets are in ptrdiff_t) or (since the variable is
unsigned) in [4294966580, 4294967091].  That means that it
can be either in the range [0, 4294966579] or in [4294967092,
UINT_MAX].  But the warning code seems to get this anti-range
wrong and treats it as [-204, -717].

If you have an account in GCC Bugzilla, can you please open
a bug with this test case?  (If you don't let me know and I
will open one for you.)

Thanks
Martin

>
> The same code snippet builds find with 8.1 debug build and older
> versions of gcc.
>
> $ gcc  -m32 -march=i686 -std=gnu99 -Wall -O2   -Werror   -c -o t.o t.c
> t.c: In function 'func':
> t.c:41:9: error: 'memcpy' offset [-204, -717] is out of the bounds [0, 216] of object 'ctrl' with type 'struct kdd_ctrl' [-Werror=array-bounds]
>          memcpy(buf, ((uint8_t *)&ctrl.c32) + offset, len);
>          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> t.c:27:21: note: 'ctrl' declared here
>      struct kdd_ctrl ctrl;
>
> <code>
> #include <stdint.h>
> #include <string.h>
>
> struct kdd_ctrl_32 {
>     uint8_t _[84];
> };
>
> struct kdd_ctrl_64 {
>     uint8_t _[216];
> };
>
> struct kdd_ctrl {
>     union {
>         struct kdd_ctrl_32 c32;
>         struct kdd_ctrl_64 c64;
>     };
> };
>
> typedef struct {
>     uint8_t buf[17 + 65536];
>     uint32_t length_req;
>     uint64_t addr;
> } kdd_state;
>
> void func(kdd_state *s)
> {
>     struct kdd_ctrl ctrl;
>     uint8_t *buf = s->buf + 17 + 57;
>     uint32_t len = s->length_req;
>     uint64_t addr = s->addr;
>
>     uint32_t offset = addr;
>
>     /* 32-bit control-register space starts at 0x[2]cc, for 84 bytes */
>     if (offset > 0x200)
>         offset -= 0x200;
>     offset -= 0xcc;
>     if (offset > sizeof ctrl.c32 || offset + len > sizeof ctrl.c32) {
>         len = 0;
>     } else {
>         memcpy(buf, ((uint8_t *)&ctrl.c32) + offset, len);
>     }
> }
> </code>
>
> Regards,
> Wei.
>

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

* Re: Gcc 8.1, -O2 optimisation build failure
  2018-08-01 21:07 ` Martin Sebor
@ 2018-08-02  8:27   ` Wei Liu
  0 siblings, 0 replies; 10+ messages in thread
From: Wei Liu @ 2018-08-02  8:27 UTC (permalink / raw)
  To: Martin Sebor; +Cc: Wei Liu, gcc-help

On Wed, Aug 01, 2018 at 03:07:05PM -0600, Martin Sebor wrote:
> On 07/30/2018 02:08 AM, Wei Liu wrote:
> > Hello,
> > 
> > We have a program which fails to build with gcc 8.1 -m32 -O2 (version
> > Debian 8.1.0-12). We couldn't figure out how the optimiser came up with
> > the idea that array bounds could become negative. Any help would be
> > appreciated. The attached code has been simplified from the original to
> > reproduce the issue.
> 
> It looks like a bug in the implementation of the warning.
> The offset is determined not to be in the range [-205, -716]
> (pointer offsets are in ptrdiff_t) or (since the variable is
> unsigned) in [4294966580, 4294967091].  That means that it
> can be either in the range [0, 4294966579] or in [4294967092,
> UINT_MAX].  But the warning code seems to get this anti-range
> wrong and treats it as [-204, -717].
> 
> If you have an account in GCC Bugzilla, can you please open
> a bug with this test case?  (If you don't let me know and I
> will open one for you.)

Thanks for your reply. I have created an account and opened a bug.

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

Wei.

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

end of thread, other threads:[~2018-08-02  8:27 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-30 11:26 Gcc 8.1, -O2 optimisation build failure Wei Liu
2018-07-30 13:36 ` U.Mutlu
2018-07-30 13:47   ` Wei Liu
2018-07-30 14:14   ` U.Mutlu
2018-07-30 14:23     ` Wei Liu
2018-07-30 14:38 ` Wei Liu
2018-07-30 14:42   ` U.Mutlu
2018-07-30 23:29     ` Wei Liu
2018-08-01 21:07 ` Martin Sebor
2018-08-02  8:27   ` Wei Liu

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