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

            Bug ID: 88921
           Summary: inconsistent warning on a power-of-2 memcpy with
                    out-of-bounds offset
           Product: gcc
           Version: 9.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: msebor at gcc dot gnu.org
  Target Milestone: ---

None of the obviously invalid calls to memcpy in the test case below is
diagnosed on common targets that fold memcpy calls with small power-of-2 sizes
into MEM_REF.  They are, however, diagnosed on targets like arm-eabi that don't
fold such calls.

This not makes writing tests for these kinds of warnings tedious (they may pass
or fail on common targets used for development only to fail on secondary
targets), it also makes developing portable software difficult when it compiles
cleanly during development but fails on targets for which builds are done only
rarely (usually because of scarcity of target boards).

GCC should issue warnings for invalid constructs consistently and regardless of
the target.

$ cat t.c && gcc -O2 -S -Wall -Wextra -fdump-tree-wrestrict=/dev/stdout t.c 
extern char a[];

void f (const char *s, __SIZE_TYPE__ i)
{
  i = __PTRDIFF_MAX__ - 1;

  __builtin_memcpy (a + i, s, 2);
}

void g (const char *s, __PTRDIFF_TYPE__ i)
{
  i = __PTRDIFF_MAX__ - 1;

  __builtin_memcpy (a + i, s, 2);
}

void h (const char *s, __PTRDIFF_TYPE__ i)
{
  if (i < __PTRDIFF_MAX__ - 1)
    i = __PTRDIFF_MAX__ - 1;

  __builtin_memcpy (a + i, s, 2);
}

;; Function f (f, funcdef_no=0, decl_uid=1908, cgraph_uid=1, symbol_order=0)

f (const char * s, long unsigned int i)
{
  short unsigned int _3;

  <bb 2> [local count: 1073741824]:
  _3 = MEM[(char * {ref-all})s_2(D)];
  MEM[(char * {ref-all})&a + 9223372036854775806B] = _3;
  return;

}



;; Function g (g, funcdef_no=1, decl_uid=1912, cgraph_uid=2, symbol_order=1)

g (const char * s, long int i)
{
  short unsigned int _3;

  <bb 2> [local count: 1073741824]:
  _3 = MEM[(char * {ref-all})s_2(D)];
  MEM[(char * {ref-all})&a + 9223372036854775806B] = _3;
  return;

}



;; Function h (h, funcdef_no=2, decl_uid=1916, cgraph_uid=3, symbol_order=2)

h (const char * s, long int i)
{
  sizetype i.1_1;
  void * _2;
  short unsigned int _7;

  <bb 2> [local count: 1073741824]:
  i_4 = MAX_EXPR <i_3(D), 9223372036854775806>;
  i.1_1 = (sizetype) i_4;
  _2 = &a + i.1_1;
  _7 = MEM[(char * {ref-all})s_6(D)];
  MEM[(char * {ref-all})_2] = _7;
  return;

}


Contrast that to:

$ /build/arm-none-eabi/gcc-svn/gcc/xgcc -B /build/arm-none-eabi/gcc-svn/gcc -O2
-S -Wall -Wextra -fdump-tree-wrestrict=/dev/stdout t.c 

;; Function f (f, funcdef_no=0, decl_uid=4141, cgraph_uid=1, symbol_order=0)

t.c: In function ‘f’:
t.c:7:3: warning: ‘__builtin_memcpy’ pointer overflow between offset 2147483646
and size 2 accessing array ‘a’ with type ‘char[]’ [-Warray-bounds]
    7 |   __builtin_memcpy (a + i, s, 2);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
t.c:1:13: note: array ‘a’ declared here
    1 | extern char a[];
      |             ^
f (const char * s, unsigned int i)
{
  <bb 2> [local count: 1073741824]:
  __builtin_memcpy (&MEM[(void *)&a + 2147483646B], s_2(D), 2);
  return;

}



;; Function g (g, funcdef_no=1, decl_uid=4145, cgraph_uid=2, symbol_order=1)

t.c: In function ‘g’:
t.c:14:3: warning: ‘__builtin_memcpy’ pointer overflow between offset
2147483646 and size 2 accessing array ‘a’ with type ‘char[]’ [-Warray-bounds]
   14 |   __builtin_memcpy (a + i, s, 2);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
t.c:1:13: note: array ‘a’ declared here
    1 | extern char a[];
      |             ^
g (const char * s, int i)
{
  <bb 2> [local count: 1073741824]:
  __builtin_memcpy (&MEM[(void *)&a + 2147483646B], s_2(D), 2);
  return;

}



;; Function h (h, funcdef_no=2, decl_uid=4149, cgraph_uid=3, symbol_order=2)

t.c: In function ‘h’:
t.c:22:3: warning: ‘__builtin_memcpy’ pointer overflow between offset
[2147483646, 2147483647] and size 2 accessing array ‘a’ with type ‘char[]’
[-Warray-bounds]
   22 |   __builtin_memcpy (a + i, s, 2);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
t.c:1:13: note: array ‘a’ declared here
    1 | extern char a[];
      |             ^
h (const char * s, int i)
{
  sizetype i.1_1;
  void * _2;

  <bb 2> [local count: 1073741824]:
  i_4 = MAX_EXPR <i_3(D), 2147483646>;
  i.1_1 = (sizetype) i_4;
  _2 = &a + i.1_1;
  __builtin_memcpy (_2, s_6(D), 2);
  return;

}

Reply via email to