summaryrefslogtreecommitdiff
path: root/gdb/go-exp.y
diff options
context:
space:
mode:
authorPedro Alves <pedro@palves.net>2022-04-07 18:01:12 +0100
committerPedro Alves <pedro@palves.net>2022-04-08 16:19:15 +0100
commit01772c548b91499272dcb0f6864ba990e2abf873 (patch)
treeea4bf0aad239a0dbb8e2a2876ae9e59cae501a00 /gdb/go-exp.y
parent7d41169b6d4dbc3950516d0cdf0d8ca462b52bbb (diff)
downloadbinutils-gdb-01772c548b91499272dcb0f6864ba990e2abf873.tar.gz
Fix undefined behavior in the Fortran, Go and Pascal number parsers
This commit ports these two fixes to the C parser: commit ebf13736b42af47c9907b5157c8e80c78dbe00e1 CommitDate: Thu Sep 4 21:46:28 2014 +0100 parse_number("0") reads uninitialized memory commit 20562150d8a894bc91657c843ee88c508188e32e CommitDate: Wed Oct 3 15:19:06 2018 -0600 Avoid undefined behavior in parse_number ... to the Fortran, Go, and Fortran number parsers, fixing the same problems there. Also add a new testcase that exercises printing 0xffffffffffffffff (max 64-bit) in all languages, which crashes a GDB built with UBsan without the fix. I moved get_set_option_choices out of all-architectures.exp.tcl to common code to be able to extract all the supported languages. I did a tweak to it to generalize it a bit -- you now have to pass down the "set" part of the command as well. This is so that the proc can be used with "maintenance set" commands as well in future. Change-Id: I8e8f2fdc1e8407f63d923c26fd55d98148b9e16a
Diffstat (limited to 'gdb/go-exp.y')
-rw-r--r--gdb/go-exp.y12
1 files changed, 5 insertions, 7 deletions
diff --git a/gdb/go-exp.y b/gdb/go-exp.y
index 456920456cd..1b9b6ea7e90 100644
--- a/gdb/go-exp.y
+++ b/gdb/go-exp.y
@@ -647,10 +647,8 @@ static int
parse_number (struct parser_state *par_state,
const char *p, 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;
@@ -702,7 +700,7 @@ parse_number (struct parser_state *par_state,
}
/* Handle base-switching prefixes 0x, 0t, 0d, 0. */
- if (p[0] == '0')
+ if (p[0] == '0' && len > 1)
switch (p[1])
{
case 'x':
@@ -790,7 +788,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;
@@ -808,7 +806,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 (par_state->gdbarch ()) - 2)) == 0)
{