]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
bswap: Fix UB in find_bswap_or_nop_finalize [PR103435]
authorJakub Jelinek <jakub@redhat.com>
Sat, 27 Nov 2021 12:00:55 +0000 (13:00 +0100)
committerJakub Jelinek <jakub@redhat.com>
Tue, 10 May 2022 08:14:29 +0000 (10:14 +0200)
On gcc.c-torture/execute/pr103376.c in the following code we trigger UB
in the compiler.  n->range is 8 because it is 64-bit load and rsize is 0
because it is a bswap sequence with load and known to be 0:
  /* Find real size of result (highest non-zero byte).  */
  if (n->base_addr)
    for (tmpn = n->n, rsize = 0; tmpn; tmpn >>= BITS_PER_MARKER, rsize++);
  else
    rsize = n->range;
The shifts then shift uint64_t by 64 bits.  For this case mask is 0
and we want both *cmpxchg and *cmpnop as 0, the operation can be done as
both nop and bswap and callers will prefer nop.

2021-11-27  Jakub Jelinek  <jakub@redhat.com>

PR tree-optimization/103435
* gimple-ssa-store-merging.c (find_bswap_or_nop_finalize): Avoid UB if
n->range - rsize == 8, just clear both *cmpnop and *cmpxchg in that
case.

(cherry picked from commit 567d5f3d62fba2a23a9e975f7e7c7b61bb67cf24)

gcc/gimple-ssa-store-merging.c

index 1678e439e8fe443af637f4e1eb5182eb3e882ec9..0623e6ec80b55721e9dcca6caf9edd9f771f5664 100644 (file)
@@ -822,12 +822,18 @@ find_bswap_or_nop_finalize (struct symbolic_number *n, uint64_t *cmpxchg,
        {
          mask = ((uint64_t) 1 << (rsize * BITS_PER_MARKER)) - 1;
          *cmpxchg &= mask;
-         *cmpnop >>= (n->range - rsize) * BITS_PER_MARKER;
+         if (n->range - rsize == sizeof (int64_t))
+           *cmpnop = 0;
+         else
+           *cmpnop >>= (n->range - rsize) * BITS_PER_MARKER;
        }
       else
        {
          mask = ((uint64_t) 1 << (rsize * BITS_PER_MARKER)) - 1;
-         *cmpxchg >>= (n->range - rsize) * BITS_PER_MARKER;
+         if (n->range - rsize == sizeof (int64_t))
+           *cmpxchg = 0;
+         else
+           *cmpxchg >>= (n->range - rsize) * BITS_PER_MARKER;
          *cmpnop &= mask;
        }
       n->range = rsize;