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

--- Comment #9 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
That is completely unreadable.
Slightly cleaned up:

long s;
struct A *foo (void);
struct B {};
struct B bar (struct B *);
void baz (void) __attribute__((__error__ ("baz")));
struct A { int a; struct B b; char c[]; };
void
qux (void)
{
  struct A *p = foo ();
  bar (&p->b);
  unsigned long q = __builtin_object_size (p->c, 1);
  if (q < s)
    baz ();
}

I think the error started with r0-118806-g17742d62a2438144b6235.
The early_objsz pass doesn't do anything special here, because it sees it is
used on a flexible array member (and even char c[24]; wouldn't do anything, as
it is still considered flexible-like array member, only having some other field
after that would cause MIN_EXPR <__builtin_object_size (p->c, 1), 24>.
But then fre1 comes and changes
   _1 = &p_8->b;
   bar (_1);
-  _2 = &p_8->c;
-  q_10 = __builtin_object_size (_2, 1);
+  q_10 = __builtin_object_size (_1, 1);
(i.e. value numbers &p_8->b and &p_8->c the same, p->b is zero sized structure,
so
&p->b == &p->c and for GIMPLE most pointer conversions are useless).

Similar testcase could be
struct S { int a; int b[2]; int c; };
struct T { int a; int b[24]; int c; };
union U { struct S s; struct T t; };
void bar (int *);
void baz (union U *);

__SIZE_TYPE__
foo (union U *p)
{
  bar (&p->s.b[0]);
  baz (p); /* Assume this changes current member from p->s to p->t.  */
  return __builtin_object_size (&p->t.b[0], 1);
}
although SCCVN doesn't value number &p->t.b[0] the same as &p->s.b[0] for some
reason.

The only fix I have in mind right now is simply treat __bos and __bdos 1 and 3
modes as 0 and 2 during late objsz.  Though it surely will lead to some
regressions in security coverage, e.g. if early inlining doesn't figure out
what field (or fields) certain pointer points to (or could point to) and it is
only late inlining that allows us to see it.
Or a targetted fix just for this case, if during late objsz we see __bos/__bdos
1 or 3 on zero sized field and there is a non-zero sized one or flexible array
member or flexible-like array member at the same address, conservatively assume
the larger.

Reply via email to