]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Fix 64-bit shifts where long only has 32-bit size
authorHannes Domani <ssbssa@yahoo.de>
Tue, 11 Jun 2024 18:36:51 +0000 (20:36 +0200)
committerHannes Domani <ssbssa@yahoo.de>
Tue, 11 Jun 2024 18:36:51 +0000 (20:36 +0200)
On systems where long has 32-bit size you get these failures:

print 1 << (unsigned long long) 0xffffffffffffffff
Cannot export value 18446744073709551615 as 32-bits unsigned integer (must be between 0 and 4294967295)
(gdb) FAIL: gdb.base/bitshift.exp: lang=c: max-uint64: print 1 << (unsigned long long) 0xffffffffffffffff
print 1 >> (unsigned long long) 0xffffffffffffffff
Cannot export value 18446744073709551615 as 32-bits unsigned integer (must be between 0 and 4294967295)
(gdb) FAIL: gdb.base/bitshift.exp: lang=c: max-uint64: print 1 >> (unsigned long long) 0xffffffffffffffff
print -1 << (unsigned long long) 0xffffffffffffffff
Cannot export value 18446744073709551615 as 32-bits unsigned integer (must be between 0 and 4294967295)
(gdb) FAIL: gdb.base/bitshift.exp: lang=c: max-uint64: print -1 << (unsigned long long) 0xffffffffffffffff
print -1 >> (unsigned long long) 0xffffffffffffffff
Cannot export value 18446744073709551615 as 32-bits unsigned integer (must be between 0 and 4294967295)
(gdb) FAIL: gdb.base/bitshift.exp: lang=c: max-uint64: print -1 >> (unsigned long long) 0xffffffffffffffff

Fixed by changing the number-of-bits variable to ULONGEST.

Approved-By: Tom Tromey <tom@tromey.com>
gdb/testsuite/gdb.base/bitshift.exp
gdb/valarith.c

index d6e252102d9cc28b15087fe3cf485f02cd6ecd3f..cab82e1971e14fea8b0c9295057c3d4e50415044 100644 (file)
@@ -363,6 +363,18 @@ proc test_shifts {} {
            test_rshift_tl $lang \
                "print -1 >> [make_uint64 $lang 0xffffffffffffffff]" " = -1"
        }
+
+       # Check if shift value isn't silently truncated to 32bit.
+       with_test_prefix "lower-32bit-zero" {
+           test_lshift_tl $lang \
+               "print 1 << [make_uint64 $lang 0x100000000]" " = 0"
+           test_rshift_tl $lang \
+               "print 1 >> [make_uint64 $lang 0x100000000]" " = 0"
+           test_lshift_tl $lang \
+               "print -1 << [make_uint64 $lang 0x100000000]" " = 0"
+           test_rshift_tl $lang \
+               "print -1 >> [make_uint64 $lang 0x100000000]" " = -1"
+       }
     }
 }
 
index 6160b0e4438e3d634bee6294173ae7dabb425e3d..a95d10881330c77bc4a38eb87f2178a3e06935f8 100644 (file)
@@ -1086,7 +1086,7 @@ type_length_bits (type *type)
 static bool
 check_valid_shift_count (enum exp_opcode op, type *result_type,
                         type *shift_count_type, const gdb_mpz &shift_count,
-                        unsigned long &nbits)
+                        ULONGEST &nbits)
 {
   if (!shift_count_type->is_unsigned ())
     {
@@ -1112,7 +1112,7 @@ check_valid_shift_count (enum exp_opcode op, type *result_type,
        }
     }
 
-  nbits = shift_count.as_integer<unsigned long> ();
+  nbits = shift_count.as_integer<ULONGEST> ();
   if (nbits >= type_length_bits (result_type))
     {
       /* In Go, shifting by large amounts is defined.  Be silent and
@@ -1291,7 +1291,7 @@ scalar_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
 
        case BINOP_LSH:
          {
-           unsigned long nbits;
+           ULONGEST nbits;
            if (!check_valid_shift_count (op, result_type, type2, v2, nbits))
              v = 0;
            else
@@ -1301,7 +1301,7 @@ scalar_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
 
        case BINOP_RSH:
          {
-           unsigned long nbits;
+           ULONGEST nbits;
            if (!check_valid_shift_count (op, result_type, type2, v2, nbits))
              {
                /* Pretend the too-large shift was decomposed in a