Bug 95988 - [10/11 Regression] Bogus -Warray-bounds/-Wstringop-overflow warning with loop
Summary: [10/11 Regression] Bogus -Warray-bounds/-Wstringop-overflow warning with loop
Status: RESOLVED DUPLICATE of bug 94655
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 10.0
: P2 normal
Target Milestone: 10.2
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on: 94655
Blocks: Warray-bounds
  Show dependency treegraph
 
Reported: 2020-06-29 22:18 UTC by Andrew Pinski
Modified: 2020-07-24 03:33 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2020-06-30 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Pinski 2020-06-29 22:18:28 UTC
Compile with -O2 -W -Wall:

void f(int*);
void g(int*);
struct  sched_group_t {
  int lock;
  struct {
   char name[32 + 1];
   int aa;
  } group[(3 + 9)];
} ;
struct sched_global_t {
 char t[(3 + 9)][3];
 struct sched_group_t sched_group;
};

struct sched_global_t *sched_global;

int hh(const char *name)
{
 struct sched_group_t *sched_group = &sched_global->sched_group;
 int i;

 g(&sched_group->lock);

 for (i = 3; i < (3 + 9); i++) {
  if (!sched_group->group[i].aa) 
  {
   char *grp_name = sched_group->group[i].name;
    __builtin_strncpy(grp_name, name, 32 - 1);
    grp_name[32 - 1] = 0;
   break;
  }
 }
 f(&sched_group->lock);
 return 0;
}

--- CUT ---
t.c: In function ‘hh’:
t.c:28:5: warning: ‘__builtin_strncpy’ offset [124, 484] is out of the bounds [0, 4] [-Warray-bounds]
   28 |     __builtin_strncpy(grp_name, name, 32 - 1);
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
t.c:29:22: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
   29 |     grp_name[32 - 1] = 0;
      |     ~~~~~~~~~~~~~~~~~^~~
t.c:4:7: note: at offset 155 to object ‘lock’ with size 4 declared here
    4 |   int lock;
      |       ^~~~
Comment 1 Andrew Pinski 2020-06-29 22:21:01 UTC
The problem is related to &sched_global->sched_group and &sched_global->sched_group->lock are at the same location, so GCC seems to select the MEM for &sched_global->sched_group->lock for both. THIS is just a diagnostic issue of the warning.
Comment 2 Andrew Pinski 2020-06-29 22:24:06 UTC
Note unlike other -Warray-bounds/-Wstringop-overflow warnings, there is no flexiable array in effect here.  Rather it is due to using the offset for sched_global->sched_group and sched_global->sched_group.lock issue.
Comment 3 Andrew Pinski 2020-06-29 23:02:07 UTC
I should mention this was reduced from upstream ODP (https://opendataplane.org/) Linux generic version.
Comment 4 Andrew Pinski 2020-07-21 19:17:41 UTC
I think this is related to PR 94655.
Comment 5 Martin Sebor 2020-07-21 20:08:02 UTC
Yes, it's a duplicate of pr94655 (and pr96259 reported just this morning).

The warning in this case is based on the following IL:

  _2 = &MEM[(struct sched_group_t *)sched_global.0_1 + 36B].lock;
  ...
 _4 = (sizetype) i_19;
  _5 = _4 * 40;
  _18 = _5 + 4;
  grp_name_10 = _2 + _18;
  __builtin_strncpy (grp_name_10, name_11(D), 31);
  MEM[(char *)grp_name_10 + 31B] = 0;

specifically grp_name_10 pointing to the lock member plus an offset it determines is out of the bounds of the member for all elements of the enclosing array.

The apparently out of bounds destination is substituted for the in bounds one in the source by the PRE pass.  Just prior to it, the IL is:
  
  _4 = (sizetype) i_19;
  _5 = _4 * 40;
  _18 = _5 + 4;
  _17 = &MEM[(struct sched_group_t *)sched_global.0_1 + 36B];
  grp_name_10 = _17 + _18;
  __builtin_strncpy (grp_name_10, name_11(D), 31);
  MEM[(char *)grp_name_10 + 31B] = 0;

which doesn't provide a justification for the warning.  All middle end warnings that attempt to detect invalid/out of bounds accesses (e.g., -Warray-bounds and -Wstringo-overflow and others) rely on the subject (ether object or subobject) in expressions like ARRAY_REF, COMPONENT_REF, and MEM_REF corresponding to the source.  Transformations that break that assumption lead to false positives.  To avoid compromising the utility of the warnings, either the transformations need to change (e.g., to use MEM_REF (base, offset) rather than COMPONENT_REF (MEM_REF ...)) or the IL needs to somehow/somewhere preserve the original destination of the access.  (I plan to look into the former.)  Otherwise, the only way to avoid issuing the warning would be to give up analyzing anything with a MEM_REF in it.  Since MEM_REFs are pervasive in the IL (all but the most trivial pointer accesses are transformed into one) this would reduce the effectiveness of the warnings to just the trivial subset of code.

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