diff options
author | Jakub Jelinek <jakub@redhat.com> | 2021-11-27 13:00:55 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2021-11-27 13:00:55 +0100 |
commit | 567d5f3d62fba2a23a9e975f7e7c7b61bb67cf24 (patch) | |
tree | 6b02eb90bb598a6a26524e4c7f0872d41125730b /gcc/gimple-ssa-store-merging.c | |
parent | d9c8a0238fc8f76e03c4dd0380eacc6cacec55c9 (diff) | |
download | gcc-567d5f3d62fba2a23a9e975f7e7c7b61bb67cf24.zip gcc-567d5f3d62fba2a23a9e975f7e7c7b61bb67cf24.tar.gz gcc-567d5f3d62fba2a23a9e975f7e7c7b61bb67cf24.tar.bz2 |
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 <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.
Diffstat (limited to 'gcc/gimple-ssa-store-merging.c')
-rw-r--r-- | gcc/gimple-ssa-store-merging.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c index e7c90ba..a00370e 100644 --- a/gcc/gimple-ssa-store-merging.c +++ b/gcc/gimple-ssa-store-merging.c @@ -871,12 +871,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; |