Bug 103435 - [12 Regression] gcc/gimple-ssa-store-merging.c:879:13: runtime error: shift exponent 64 is too large for 64-bit type 'long unsigned int'
Summary: [12 Regression] gcc/gimple-ssa-store-merging.c:879:13: runtime error: shift e...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 12.0
: P3 normal
Target Milestone: 12.0
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks: ubsan
  Show dependency treegraph
 
Reported: 2021-11-26 08:13 UTC by Martin Liška
Modified: 2022-05-11 06:23 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Liška 2021-11-26 08:13:58 UTC
The following triggers an UBSAN:

$ ./xgcc -B. /home/marxin/Programming/gcc/gcc/testsuite/gcc.c-torture/execute/pr103376.c -c -O2
/home/marxin/Programming/gcc/gcc/gimple-ssa-store-merging.c:879:13: runtime error: shift exponent 64 is too large for 64-bit type 'long unsigned int'
    #0 0x6bd87c2 in find_bswap_or_nop_finalize /home/marxin/Programming/gcc/gcc/gimple-ssa-store-merging.c:879
    #1 0x6bd96aa in find_bswap_or_nop /home/marxin/Programming/gcc/gcc/gimple-ssa-store-merging.c:981
    #2 0x6bdde47 in execute /home/marxin/Programming/gcc/gcc/gimple-ssa-store-merging.c:1538
    #3 0x22d26de in execute_one_pass(opt_pass*) /home/marxin/Programming/gcc/gcc/passes.c:2567
    #4 0x22d31da in execute_pass_list_1 /home/marxin/Programming/gcc/gcc/passes.c:2656
    #5 0x22d32a3 in execute_pass_list_1 /home/marxin/Programming/gcc/gcc/passes.c:2657
    #6 0x22d335d in execute_pass_list(function*, opt_pass*) /home/marxin/Programming/gcc/gcc/passes.c:2667
    #7 0x1228bba in cgraph_node::expand() /home/marxin/Programming/gcc/gcc/cgraphunit.c:1834
    #8 0x122a7a2 in expand_all_functions /home/marxin/Programming/gcc/gcc/cgraphunit.c:1998
    #9 0x122cce6 in symbol_table::compile() /home/marxin/Programming/gcc/gcc/cgraphunit.c:2348
    #10 0x122d824 in symbol_table::finalize_compilation_unit() /home/marxin/Programming/gcc/gcc/cgraphunit.c:2529
    #11 0x27bc935 in compile_file /home/marxin/Programming/gcc/gcc/toplev.c:479
    #12 0x27c6da6 in do_compile /home/marxin/Programming/gcc/gcc/toplev.c:2156
    #13 0x27c7821 in toplev::main(int, char**) /home/marxin/Programming/gcc/gcc/toplev.c:2308
    #14 0x7332fb1 in main /home/marxin/Programming/gcc/gcc/main.c:39
    #15 0x7ffff6ef85bf in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #16 0x7ffff6ef867b in __libc_start_main_impl ../csu/libc-start.c:409
    #17 0xabf1e4 in _start (/dev/shm/objdir2/gcc/cc1+0xabf1e4)
Comment 1 Jakub Jelinek 2021-11-26 10:05:51 UTC
Untested fix:

2021-11-26  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.

--- gcc/gimple-ssa-store-merging.c.jj	2021-11-25 10:47:07.000000000 +0100
+++ gcc/gimple-ssa-store-merging.c	2021-11-26 10:54:11.959800560 +0100
@@ -871,12 +871,18 @@ find_bswap_or_nop_finalize (struct symbo
 	{
 	  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;
Comment 2 GCC Commits 2021-11-27 12:01:41 UTC
The master branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>:

https://gcc.gnu.org/g:567d5f3d62fba2a23a9e975f7e7c7b61bb67cf24

commit r12-5557-g567d5f3d62fba2a23a9e975f7e7c7b61bb67cf24
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Sat Nov 27 13:00:55 2021 +0100

    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.
Comment 3 Jakub Jelinek 2021-11-27 12:03:32 UTC
Fixed.
Comment 4 GCC Commits 2021-11-29 08:50:30 UTC
The releases/gcc-11 branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>:

https://gcc.gnu.org/g:3479e49be805b077b215a1547aad20409e69af35

commit r11-9339-g3479e49be805b077b215a1547aad20409e69af35
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Sat Nov 27 13:00:55 2021 +0100

    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.
    
    (cherry picked from commit 567d5f3d62fba2a23a9e975f7e7c7b61bb67cf24)
Comment 5 GCC Commits 2022-05-10 08:22:08 UTC
The releases/gcc-10 branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>:

https://gcc.gnu.org/g:9a0152509234c514dcdb34468155459dfd7afacf

commit r10-10659-g9a0152509234c514dcdb34468155459dfd7afacf
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Sat Nov 27 13:00:55 2021 +0100

    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.
    
    (cherry picked from commit 567d5f3d62fba2a23a9e975f7e7c7b61bb67cf24)
Comment 6 GCC Commits 2022-05-11 06:23:30 UTC
The releases/gcc-9 branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>:

https://gcc.gnu.org/g:790b8d49ebf7c0827c9aeaad3c8c5bf7168ed17b

commit r9-10113-g790b8d49ebf7c0827c9aeaad3c8c5bf7168ed17b
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Sat Nov 27 13:00:55 2021 +0100

    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.
    
    (cherry picked from commit 567d5f3d62fba2a23a9e975f7e7c7b61bb67cf24)