[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH] tools/kdd: silence gcc 8 warning a different way

Wei Liu writes ("Re: [PATCH] tools/kdd: silence gcc 8 warning a different way"):
> On Thu, Apr 12, 2018 at 06:04:49AM -0600, Jan Beulich wrote:
> > Older gcc doesn't like "#pragma GCC diagnostic" inside functions.

Surely this commit message should refer to the previous commit ?

I reviewed the previous code to check that the validation was correct:

   if (offset > sizeof ctrl.c32 || offset + len > sizeof ctrl.c32) {
     len = 0;
   } else {
     memcpy(buf, ((uint8_t *)&ctrl.c32) + offset, len);

I see two problems:

1. Adversarial optimissation hazard:

   The compiler may reason as follows:
   It is not legal to compute an out-of-bounds pointer.
   Doing so is UB.
   Therefore  ((uint8_t *)&ctrl.c32) + offset
   (which is caclulated unconditionally)
   is within the stack object `ctrl'.
   Therefore offset <= sizeof(ctrl).

1a. The compiler can continue to reason:
   Suppose offset > sizeof(ctrl.c32) but offset + len <=
   sizeof(ctrl.c32).  Because len is limited to 32-bit
   that can only happen if offset is large enough to
   wrap when len is added.  But I know that offset <= 216.
   So this situation cannot exist.
   Therefore I can remove the check for offset and
   rely only on the check for offset + len.

1b. The compiler can continue to reason:
   So offset <= 216.  I can therefore check that
   offset <= sizeof(ctrl.c32) using an instruction sequence
   that only looks at the bottom byte of offset (which on
   some architectures might be faster).

1c. If sizeof(ctrl.c32) ever becomes the same as sizeof(ctrl),
   the compiler can remove both checks entirely.

2. Style problem:

   Suppose  len = (uint64_t)-1   offset = 1
   The check passes, but the memcpy gets len = bazillion-1.
   In fact, len is a uint32_t so this is not possible but it is
   not possible to review these lines in isolation and see that
   they are correct.  A future programmer might increase the size
   of len, introducing a bug.  You should compile-time assert
   that len is 32-bit, somehow, right next to that check, IMO.

> > +            /* Suppress bogus gcc 8 "out of bounds" warning. */
> > +            const uint8_t *src;
> > +            asm ("" : "=g" (src) : "0" ((uint8_t *)&ctrl.c32 + offset));
> > +            memcpy(buf, src, len);
> The code looks correct to me:

IMO the new code is very hard to follow.  Are we really expecting
every reader of this to know w3hat the asm does ?

At the very least it should be accompanied with an explanation of what
the asm does, for the benefit of readers who don't speak asm.

I think that rather than introducing an asm, we should disable -Werror
for known-buggy compilers.  But it is possible that fixing the
problems I identify above will make the warning go away anyway.


Xen-devel mailing list



Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.