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

--- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
struct S { bool s[8]; };

void
foo (const S *x)
{
  unsigned n = 0;
  for (unsigned j = 0; j < 8; j++)
    n |= ((!x->s[j]) ? 1 : 0) << (16 + j);
}

-O2 -fsanitize=shift-exponent,bounds-strict -Wuninitialized
is all that is needed.
Seems the SAVE_EXPR <j> used in the .UBSAN_BOUNDS call is evaluated separately
both in
the __builtin___ubsan_handle_shift_out_of_bounds argument and then later on
again,
but because the call is conditional and is gimplified first, j is initialized
only in case 16 + j > 31 and uninitialized otherwise.

Now, if I try:
int bar (void);

int
baz (int x)
{
  return bar () << x;
}
we properly evaluate SAVE_EXPR <bar ()> first, then conditionally in
__builtin___ubsan_handle_shift_out_of_bounds argument and again afterwards.
So I guess the bug is that (x->s[j] ? 0 : 1) isn't considered as having
side-effects
by the shift sanitization.  And we then add the bounds-strict sanitization into
it
which definitely turns it into something with side-effects.

Reply via email to