From: Jakub Jelinek Date: Sat, 27 Nov 2021 12:00:55 +0000 (+0100) Subject: bswap: Fix UB in find_bswap_or_nop_finalize [PR103435] X-Git-Tag: releases/gcc-10.4.0~212 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9a0152509234c514dcdb34468155459dfd7afacf;p=thirdparty%2Fgcc.git bswap: Fix UB in find_bswap_or_nop_finalize [PR103435] 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 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) --- diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c index 1678e439e8fe..0623e6ec80b5 100644 --- a/gcc/gimple-ssa-store-merging.c +++ b/gcc/gimple-ssa-store-merging.c @@ -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;