Avoid undefined behavior in parse_number
-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.
This commit is contained in:
parent
d359392f97
commit
20562150d8
@ -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"
|
||||
|
10
gdb/c-exp.y
10
gdb/c-exp.y
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user