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.