Avoid undefined behavior in parse_number
authorTom Tromey <tom@tromey.com>
Mon, 30 Jul 2018 02:23:33 +0000 (20:23 -0600)
committerTom Tromey <tom@tromey.com>
Wed, 3 Oct 2018 21:19:06 +0000 (15:19 -0600)
-fsanitize=undefined pointed out that c-exp.y relied on undefined
behavior here:

      if (c != 'l' && c != 'u')
n *= base;

...when a large hex constant "just fit" into a LONGEST, causing the
high bit to be set.

This fixes the problem by having the function work in an unsigned
type.

gdb/ChangeLog
2018-10-03  Tom Tromey  <tom@tromey.com>

* c-exp.y (parse_number): Work in unsigned.  Remove casts.

gdb/ChangeLog
gdb/c-exp.y

index 4be30330e59012793d81754cb3b9b83b26b09c0f..97ee73bab38511a212fc44f878a03d880350b413 100644 (file)
@@ -1,3 +1,7 @@
+2018-10-03  Tom Tromey  <tom@tromey.com>
+
+       * c-exp.y (parse_number): Work in unsigned.  Remove casts.
+
 2018-10-03  Tom Tromey  <tom@tromey.com>
 
        * dwarf2read.c (read_subrange_type): Make "negative_mask"
index 0326ee090e175e3344051485e7473d75e56ff93d..09e31d2283a7296443d3e7c28bd9f349e2c016d1 100644 (file)
@@ -1760,10 +1760,8 @@ static int
 parse_number (struct parser_state *par_state,
              const char *buf, int len, int parsed_float, YYSTYPE *putithere)
 {
-  /* FIXME: Shouldn't these be unsigned?  We don't deal with negative values
-     here, and we do kind of silly things like cast to unsigned.  */
-  LONGEST n = 0;
-  LONGEST prevn = 0;
+  ULONGEST n = 0;
+  ULONGEST prevn = 0;
   ULONGEST un;
 
   int i = 0;
@@ -1922,7 +1920,7 @@ parse_number (struct parser_state *par_state,
         on 0x123456789 when LONGEST is 32 bits.  */
       if (c != 'l' && c != 'u' && n != 0)
        {       
-         if ((unsigned_p && (ULONGEST) prevn >= (ULONGEST) n))
+         if (unsigned_p && prevn >= n)
            error (_("Numeric constant too large."));
        }
       prevn = n;
@@ -1940,7 +1938,7 @@ parse_number (struct parser_state *par_state,
      the case where it is we just always shift the value more than
      once, with fewer bits each time.  */
 
-  un = (ULONGEST)n >> 2;
+  un = n >> 2;
   if (long_p == 0
       && (un >> (gdbarch_int_bit (parse_gdbarch (par_state)) - 2)) == 0)
     {