Bug 88273 - [8 Regression] warning: 'memcpy' offset [-527, -529] is out of the bounds [0, 16] of object 'vrsave' with type 'union <anonymous>' [-Warray-bounds]
Summary: [8 Regression] warning: 'memcpy' offset [-527, -529] is out of the bounds [0,...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 8.2.0
: P2 normal
Target Milestone: 8.4
Assignee: Martin Sebor
URL:
Keywords: diagnostic
: 86827 (view as bug list)
Depends on:
Blocks:
 
Reported: 2018-11-30 01:48 UTC by Mathieu Malaterre
Modified: 2020-02-25 16:39 UTC (History)
3 users (show)

See Also:
Host: x86_64-pc-linux-gnu
Target: powerpc-*-linux-gnu
Build:
Known to work: 7.3.0
Known to fail: 8.2.0, 8.3.0
Last reconfirmed: 2019-01-03 00:00:00


Attachments
creduce code (186 bytes, text/plain)
2018-11-30 01:48 UTC, Mathieu Malaterre
Details
save-temps (283.26 KB, application/gzip)
2018-11-30 07:55 UTC, Mathieu Malaterre
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Mathieu Malaterre 2018-11-30 01:48:24 UTC
Created attachment 45127 [details]
creduce code

There seems to be a regression in 8.2.0 from the previous release. See original post at:

* https://lkml.org/lkml/2018/8/16/117

Reduced test case:

$ cat bug.c
typedef struct {
  int a[4]
} b, c;
d, e;
inline f(void *g, int h, int p3) {
  unsigned *i = 0;
  int copy = ({ d ?: p3; });
  g += *i - h;
  memcpy(e, g, copy);
  *i = copy;
}
j() {
  f(j, 0, sizeof(c));
  union {
    b k
  } vrsave;
  f(&vrsave, 33 * sizeof(c), 1);
}


With:

$ powerpc-linux-gnu-gcc -Warray-bounds -mcpu=powerpc -fno-delete-null-pointer-checks -O2 -c bug.c
...
bug.c:9:3: warning: 'memcpy' offset [-527, -529] is out of the bounds [0, 16] of object 'vrsave' with type 'union <anonymous>' [-Warray-bounds]
   memcpy(e, g, copy);


For reference:

$ powerpc-linux-gnu-gcc --version
powerpc-linux-gnu-gcc (Debian 8.2.0-9) 8.2.0
Comment 1 Andrew Pinski 2018-11-30 01:59:00 UTC
I think the creduced testcase is bogus and undefined behavior happens.
There is derefering of a NULL pointer there.
Comment 2 Andrew Pinski 2018-11-30 02:01:18 UTC
Yes you have -fno-delete-null-pointer-checks but that just will not cause an trap to happen.

Can you attach the original preprocessed source because that will help to decide if this is a valid warning or not?
Comment 3 Martin Sebor 2018-11-30 02:49:30 UTC
Based on the text of the warning this looks similar to pr86827 except that I don't see it with the powerpc64-linux or x86_64-linux compilers and I don't have a powerpc cross-compiler handy at the moment.

I do see several other warnings for the test case.  Not sure if they have any bearing on the reported problem but they do imply the test case is invalid (valid test cases are preferable when reporting problems other than ICE).

pr88273.c:3:1: warning: no semicolon at end of struct or union
    3 | } b, c;
      | ^
pr88273.c:4:1: warning: data definition has no type or storage class
    4 | d, e;
      | ^
pr88273.c:4:1: warning: type defaults to ‘int’ in declaration of ‘d’ [-Wimplicit-int]
pr88273.c:4:4: warning: type defaults to ‘int’ in declaration of ‘e’ [-Wimplicit-int]
    4 | d, e;
      |    ^
pr88273.c:5:8: warning: return type defaults to ‘int’ [-Wimplicit-int]
    5 | inline f(void *g, int h, int p3) {
      |        ^
pr88273.c: In function ‘f’:
pr88273.c:9:20: warning: passing argument 1 of ‘__builtin_memcpy’ makes pointer from integer without a cast [-Wint-conversion]
    9 |   __builtin_memcpy(e, g, copy);
      |                    ^
      |                    |
      |                    int
pr88273.c:9:20: note: expected ‘void *’ but argument is of type ‘int’
pr88273.c: At top level:
pr88273.c:12:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
   12 | j() {
      | ^
pr88273.c: In function ‘j’:
pr88273.c:16:3: warning: no semicolon at end of struct or union
   16 |   } vrsave;
      |   ^
Comment 4 Arseny Solokha 2018-11-30 07:22:06 UTC
(In reply to Martin Sebor from comment #3)
> Based on the text of the warning this looks similar to pr86827 except that I
> don't see it with the powerpc64-linux or x86_64-linux compilers and I don't
> have a powerpc cross-compiler handy at the moment.

It's there on 32-bit powerpc.

% powerpc-e300c3-linux-gnu-gcc-9.0.0-alpha20181125 -Warray-bounds -mcpu=powerpc -fno-delete-null-pointer-checks -O2 -c pr88273.c                                                                                                              
pr88273.c:3:1: warning: no semicolon at end of struct or union
    3 | } b, c;
      | ^
pr88273.c:4:1: warning: data definition has no type or storage class
    4 | d, e;
      | ^
pr88273.c:4:1: warning: type defaults to 'int' in declaration of 'd' [-Wimplicit-int]
pr88273.c:4:4: warning: type defaults to 'int' in declaration of 'e' [-Wimplicit-int]
    4 | d, e;
      |    ^
pr88273.c:5:8: warning: return type defaults to 'int' [-Wimplicit-int]
    5 | inline f(void *g, int h, int p3) {
      |        ^
pr88273.c: In function 'f':
pr88273.c:9:3: warning: implicit declaration of function 'memcpy' [-Wimplicit-function-declaration]
    9 |   memcpy(e, g, copy);
      |   ^~~~~~
pr88273.c:9:3: warning: incompatible implicit declaration of built-in function 'memcpy'
pr88273.c:1:1: note: include '<string.h>' or provide a declaration of 'memcpy'
  +++ |+#include <string.h>
    1 | typedef struct {
pr88273.c:9:10: warning: passing argument 1 of 'memcpy' makes pointer from integer without a cast [-Wint-conversion]
    9 |   memcpy(e, g, copy);
      |          ^
      |          |
      |          int
pr88273.c:9:10: note: expected 'void *' but argument is of type 'int'
pr88273.c: At top level:
pr88273.c:12:1: warning: return type defaults to 'int' [-Wimplicit-int]
   12 | j() {
      | ^
pr88273.c: In function 'j':
pr88273.c:16:3: warning: no semicolon at end of struct or union
   16 |   } vrsave;
      |   ^
In function 'f',
    inlined from 'j' at pr88273.c:17:3:
pr88273.c:9:3: warning: 'memcpy' offset [-527, -529] is out of the bounds [0, 16] of object 'vrsave' with type 'union <anonymous>' [-Warray-bounds]
    9 |   memcpy(e, g, copy);
      |   ^~~~~~~~~~~~~~~~~~
pr88273.c: In function 'j':
pr88273.c:16:5: note: 'vrsave' declared here
   16 |   } vrsave;
      |     ^~~~~~
Comment 5 Mathieu Malaterre 2018-11-30 07:55:32 UTC
Created attachment 45128 [details]
save-temps
Comment 6 Andrew Pinski 2018-11-30 08:25:24 UTC
The creduced file definitely does not represent at all the original file.

It is the second call to user_regset_copyin which is complaining.  Without looking into the gimple dump, I think there is jump threading going on which might cause this warning.
Comment 7 Mathieu Malaterre 2019-01-02 21:50:27 UTC
Here is the new creduced test case:

$ cat bug.c
#include <string.h>

typedef struct {
  int b[4]
} c;
void* d;
unsigned e;
inline int h(void *i, int p2, int j) {
  if (j < 0 || e < j) {
    int copy = ({
      typeof(e) k = j - e;
      k;
    });
    i += e - p2;
    memcpy(d, i, copy);
    e = copy;
  }
}
void a() {
  int g = h(&g, 0, sizeof(c));
  union {
    c f;
  } vrsave;
  h(&vrsave, 33 * sizeof(c), -1);
}


Compilation:

$ powerpc-linux-gnu-gcc -Warray-bounds -mcpu=powerpc -O2 -c bug.c

Using creduce with:

#!/bin/bash
powerpc-linux-gnu-gcc -Warray-bounds -mcpu=powerpc -O2 -c ptrace2.i >& output.txt
grep error output.txt && exit 1
grep -F "warning: 'memcpy' offset [-527, -529] is out of the bounds [0, 16] of object 'vrsave' with type 'union <anonymous>'" output.txt >/dev/null 2>&1
Comment 8 Mathieu Malaterre 2019-01-02 21:54:53 UTC
For reference:

$ cat ptrace2.c
#include <linux/regset.h>
#define CREATE_TRACE_POINTS
#include <trace/events/syscalls.h>
void a(int b, int c, void *d) {
  void *e = 0;
  int g = user_regset_copyout(&b, &c, d, e, g, 0, sizeof(vector128));
  union {
    elf_vrreg_t f
  } vrsave;
  user_regset_copyout(&b, &c, d, e, &vrsave, 33 * sizeof(vector128), -1);
}
Comment 9 Martin Liška 2019-01-03 09:10:22 UTC
Slightly cleaned up test-case:

$ cat /home/marxin/Programming/testcases/pr88273-2.c
typedef struct {
  int b[4];
} c;

void* d;
unsigned e;

inline int h(void *i, int p2, int j) {
  if (j < 0 || e < j) {
    int copy = j - e;
    i += e - p2;
    __builtin_memcpy(d, i, copy);
    e = copy;
  }
}
void a() {
  int g = h(&g, 0, sizeof(c));
  c vrsave;
  h(&vrsave, 33 * sizeof(c), -1);
}

So the warning is triggered for the cross compiler from here:

$ Breakpoint 5, warning_at (location=location@entry=2147483704, opt=opt@entry=171, gmsgid=gmsgid@entry=0x15a3448 "%G%qD offset %s is out of the bounds [0, %wu] of object %qD with type %qT") at ../../gcc/diagnostic.c:1289
1289	{
(gdb) bt
#0  warning_at (location=location@entry=2147483704, opt=opt@entry=171, gmsgid=gmsgid@entry=0x15a3448 "%G%qD offset %s is out of the bounds [0, %wu] of object %qD with type %qT") at ../../gcc/diagnostic.c:1289
#1  0x0000000000a39dc3 in (anonymous namespace)::maybe_diag_offset_bounds (loc=2147483704, call=<gimple_call 0x7ffff6b411c8>, func=<function_decl 0x7ffff6a23500 __builtin_memcpy>, strict=<optimized out>, expr=<optimized out>, ref=...) at ../../gcc/wide-int.h:831
#2  0x0000000000a3a9d9 in (anonymous namespace)::maybe_diag_offset_bounds (ref=..., expr=<ssa_name 0x7ffff6b3dbd0>, strict=0, func=<optimized out>, call=<gimple_call 0x7ffff6b411c8>, loc=2147483704) at ../../gcc/gimple-ssa-warn-restrict.c:1586
#3  check_bounds_or_overlap (call=<gimple_call 0x7ffff6b411c8>, dst=<ssa_name 0x7ffff6b3da68>, src=<ssa_name 0x7ffff6b3dbd0>, dstsize=<optimized out>, srcsize=<optimized out>, bounds_only=<optimized out>) at ../../gcc/gimple-ssa-warn-restrict.c:1851
#4  0x0000000000a3c718 in (anonymous namespace)::wrestrict_dom_walker::check_call (this=<optimized out>, call=<gimple_call 0x7ffff6b411c8>) at ../../gcc/gimple-ssa-warn-restrict.c:1814
#5  (anonymous namespace)::wrestrict_dom_walker::before_dom_children (this=<optimized out>, bb=<optimized out>) at ../../gcc/gimple-ssa-warn-restrict.c:105
#6  0x00000000013256d8 in dom_walker::walk (this=this@entry=0x7fffffffd720, bb=<basic_block 0x7ffff6b0ab60 (4)>) at ../../gcc/domwalk.c:373
#7  0x0000000000a31c38 in (anonymous namespace)::pass_wrestrict::execute (this=<optimized out>, fun=0x7ffff6b360b0) at ../../gcc/gimple-ssa-warn-restrict.c:119
#8  0x0000000000be2885 in execute_one_pass (pass=<opt_pass* 0x1d49510 "wrestrict"(188)>) at ../../gcc/passes.c:2483
#9  0x0000000000be3008 in execute_pass_list_1 (pass=<opt_pass* 0x1d49510 "wrestrict"(188)>) at ../../gcc/passes.c:2569
#10 0x0000000000be301a in execute_pass_list_1 (pass=<opt_pass* 0x1d47020 "*all_optimizations"(-1)>) at ../../gcc/passes.c:2570
#11 0x0000000000be3059 in execute_pass_list (fn=0x7ffff6b360b0, pass=<optimized out>) at ../../gcc/passes.c:2580
#12 0x00000000008cd5cb in cgraph_node::expand (this=<cgraph_node * const 0x7ffff698f5a0 "a"/3>) at ../../gcc/context.h:48
#13 0x00000000008ce5a4 in expand_all_functions () at ../../gcc/cgraphunit.c:2334
#14 symbol_table::compile (this=0x7ffff6991000) at ../../gcc/cgraphunit.c:2685
#15 0x00000000008d0bed in symbol_table::compile (this=0x7ffff6991000) at ../../gcc/cgraphunit.c:2863
#16 symbol_table::finalize_compilation_unit (this=0x7ffff6991000) at ../../gcc/cgraphunit.c:2863
#17 0x0000000000cb9b4b in compile_file () at ../../gcc/toplev.c:481
#18 0x00000000007522c4 in do_compile () at ../../gcc/toplev.c:2176
#19 toplev::main (this=this@entry=0x7fffffffd93e, argc=<optimized out>, argc@entry=23, argv=<optimized out>, argv@entry=0x7fffffffda38) at ../../gcc/toplev.c:2311
#20 0x00000000007545db in main (argc=23, argv=0x7fffffffda38) at ../../gcc/main.c:39

For the following gimple IL:

$ (gdb) p debug_gimple_stmt(call)
No symbol "call" in current context.
(gdb) p debug_function(cfun->decl,0)
a ()
{
  void * i;
  void * i;
  int D.2622;
  struct c vrsave;
  int g;
  unsigned int e.0_5;
  void * pretmp_10;
  unsigned int _12;
  unsigned int prephitmp_13;
  void * pretmp_14;
  void * prephitmp_17;
  unsigned int _19;
  unsigned int _21;

  <bb 2> [local count: 1073741824]:
  e.0_5 = e;
  pretmp_10 = d;
  if (e.0_5 <= 15)
    goto <bb 3>; [50.00%]
  else
    goto <bb 4>; [50.00%]

  <bb 3> [local count: 536870913]:
  _12 = 16 - e.0_5;
  i_15 = &g + e.0_5;
  __builtin_memcpy (pretmp_10, i_15, _12);
  e = _12;
  pretmp_14 = d;

  <bb 4> [local count: 1073741824]:
  # prephitmp_13 = PHI <_12(3), e.0_5(2)>
  # prephitmp_17 = PHI <pretmp_14(3), pretmp_10(2)>
  _19 = ~prephitmp_13;
  _21 = prephitmp_13 + 4294966768;
  i_22 = &vrsave + _21;
  __builtin_memcpy (prephitmp_17, i_22, _19);
  e = _19;
  g ={v} {CLOBBER};
  vrsave ={v} {CLOBBER};
  return;

}

I can confirm the warning is false, because the problematic __builtin_memcpy for which we trigger the warning:
  __builtin_memcpy (prephitmp_17, i_22, _19);

and complains about i_22, but this one should be fine (with a reasonable initial value of global variable 'e').
Martin: can you please take a look?
Comment 10 Martin Liška 2019-01-03 10:38:39 UTC
Started with r255755.
Comment 11 Martin Sebor 2019-01-17 22:53:18 UTC
Author: msebor
Date: Thu Jan 17 22:52:47 2019
New Revision: 268048

URL: https://gcc.gnu.org/viewcvs?rev=268048&root=gcc&view=rev
Log:
PR middle-end/88273 - [8/9 Regression] warning: 'memcpy' offset [-527, -529]
is out of the bounds [0, 16]

gcc/ChangeLog:

	PR middle-end/88273
	* gimple-ssa-warn-restrict.c (builtin_memref::extend_offset_range):
	Handle anti-ranges the same as no range at all.

gcc/testsuite/ChangeLog:

	PR middle-end/88273
	* gcc.dg/Warray-bounds-38.c: New test.

Added:
    trunk/gcc/testsuite/gcc.dg/Warray-bounds-38.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/gimple-ssa-warn-restrict.c
    trunk/gcc/testsuite/ChangeLog
Comment 12 Martin Sebor 2019-01-17 22:58:14 UTC
Fixed via r268048 for GCC 9.
Comment 13 Jakub Jelinek 2019-02-22 15:18:44 UTC
GCC 8.3 has been released.
Comment 14 Martin Sebor 2019-03-18 19:44:33 UTC
Author: msebor
Date: Mon Mar 18 19:44:02 2019
New Revision: 269778

URL: https://gcc.gnu.org/viewcvs?rev=269778&root=gcc&view=rev
Log:
Backport from mainline:

PR middle-end/88273 - [8/9 Regression] warning: 'memcpy' offset [-527, -529]
is out of the bounds [0, 16]

gcc/ChangeLog:

	PR middle-end/88273
	* gimple-ssa-warn-restrict.c (builtin_memref::extend_offset_range):
	Handle anti-ranges the same as no range at all.

gcc/testsuite/ChangeLog:

	PR middle-end/88273
	* gcc.dg/Warray-bounds-38.c: New test.

Added:
    branches/gcc-8-branch/gcc/testsuite/gcc.dg/Warray-bounds-38.c
Modified:
    branches/gcc-8-branch/gcc/ChangeLog
    branches/gcc-8-branch/gcc/gimple-ssa-warn-restrict.c
    branches/gcc-8-branch/gcc/testsuite/ChangeLog
Comment 15 Martin Sebor 2019-03-18 19:45:33 UTC
Fixed in GCC 8.4 via r269778.
Comment 16 Martin Sebor 2020-02-25 16:39:22 UTC
*** Bug 86827 has been marked as a duplicate of this bug. ***