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

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |siddhesh at redhat dot com

--- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Note, for the above patch I was worried about something like:
struct S { int a; char b[36]; int c; };

static inline __SIZE_TYPE__
foo (char *p)
{
  return __builtin_object_size (p, 1);
}

__SIZE_TYPE__
bar (void)
{
  struct S s;
  return foo (&s.b[0]);
}

with -O2 -fno-early-inlining, but in that case we actually don't perform that
at all - the MIN_EXPR is added only if __bos can be computed during the objsz1
pass to something other than the "unknown" value.  If it is, then there
shouldn't be pointer passed from caller as one of the possible values, so maybe
it is safe.
Of course this shows that the objsz1 pass is just mitigation pass, because when
the function with __builtin_object_size calls isn't early inlined or some
caller of that and ultimately objsz1 pass isn't able to compute a known value,
then any SCCVN pointer replacement with different subobject sizes that could
feed a subobject __bos (1 or 3) could change the user visible value.

E.g.
struct S { char b[36]; int c; };
void baz (char *);

static inline __SIZE_TYPE__
foo (char *p)
{
  return __builtin_object_size (p, 1);
}

__SIZE_TYPE__
bar (void)
{
  struct S *p = __builtin_malloc (2 * sizeof (struct S)) + sizeof (struct S);
  baz ((char *) p);
  return foo (&p->b[0]);
}
doesn't reproduce it, we still pass
  p_5 = _1 + 40;
  baz (p_5);
  _2 = &MEM[(struct S *)_1 + 40B].b[0];
  _8 = __builtin_object_size (_2, 1);
and don't figure out that _2 == p_5.
But modified #c0 testcase triggers it at -O2:
typedef __SIZE_TYPE__ size_t;
void baz (int, int) __attribute__((__warning__("detected overflow")));

union U {
  int i;
  char c;
};

static void
qux (void *p, size_t q)
{
  if (__builtin_object_size (p, 1) < q)
    baz (__builtin_object_size (p, 1), q);
  __builtin_memset (p, 0, q);
}

static void
foo (union U *u)
{
  qux (&u->c, sizeof (u->c));
  qux (&u->i, sizeof (u->i));
}

void
bar (union U *u)
{
  int i, j;
  for (i = 0; i < 1; i++)
    {
      foo (u);

      for (j = 0; j < 2; j++)
        asm volatile ("");
    }
}
and this patch doesn't fix it.

Reply via email to