From d27aad4ec307d91a6b9056127c6c248044391d7f Mon Sep 17 00:00:00 2001 From: Alex Coplan Date: Thu, 6 Aug 2020 17:39:03 +0100 Subject: [PATCH] gas: Fix internal error on long local labels Prior to this commit, on an input such as "88888888888:", GAS hits a signed integer overflow and likely an assertion failure. I see: $ echo "88888888888:" | bin/aarch64-none-elf-as {standard input}: Assembler messages: {standard input}:1: Internal error in fb_label_name at ../gas/symbols.c:2049. Please report this bug. To fix this issue, I've taken two steps: 1. Change the type used for processing local labels in read_a_source_file() from int to long, to allow representing more local labels, and also since all uses of this variable (temp) are actually of type long. 2. Detect if we would overflow and bail out with an error message instead of actually overflowing and hitting the assertion in fb_label_name(). gas/ChangeLog: 2020-08-06 Alex Coplan * read.c (read_a_source_file): Use long for local labels, detect overflow and raise an error for overly-long labels. * testsuite/gas/all/gas.exp: Add local-label-overflow test. * testsuite/gas/all/local-label-overflow.d: New test. * testsuite/gas/all/local-label-overflow.l: Error output. * testsuite/gas/all/local-label-overflow.s: Input. --- gas/ChangeLog | 9 +++++++++ gas/read.c | 19 ++++++++++++++++--- gas/testsuite/gas/all/gas.exp | 1 + gas/testsuite/gas/all/local-label-overflow.d | 3 +++ gas/testsuite/gas/all/local-label-overflow.l | 2 ++ gas/testsuite/gas/all/local-label-overflow.s | 1 + 6 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 gas/testsuite/gas/all/local-label-overflow.d create mode 100644 gas/testsuite/gas/all/local-label-overflow.l create mode 100644 gas/testsuite/gas/all/local-label-overflow.s diff --git a/gas/ChangeLog b/gas/ChangeLog index 771e865d4b7..eac8ec4f9be 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,12 @@ +2020-08-06 Alex Coplan + + * read.c (read_a_source_file): Use long for local labels, detect + overflow and raise an error for overly-long labels. + * testsuite/gas/all/gas.exp: Add local-label-overflow test. + * testsuite/gas/all/local-label-overflow.d: New test. + * testsuite/gas/all/local-label-overflow.l: Error output. + * testsuite/gas/all/local-label-overflow.s: Input. + 2020-08-04 Christian Groessler * gas/testsuite/gas/z8k/inout.d: Adapt to correct encoding of diff --git a/gas/read.c b/gas/read.c index f192cc16d57..bd896580e5d 100644 --- a/gas/read.c +++ b/gas/read.c @@ -40,6 +40,8 @@ #include "dw2gencfi.h" #include "wchar.h" +#include + #ifndef TC_START_LABEL #define TC_START_LABEL(STR, NUL_CHAR, NEXT_CHAR) (NEXT_CHAR == ':') #endif @@ -816,7 +818,7 @@ read_a_source_file (const char *name) char nul_char; char next_char; char *s; /* String of symbol, '\0' appended. */ - int temp; + long temp; pseudo_typeS *pop; #ifdef WARN_COMMENTS @@ -1212,10 +1214,21 @@ read_a_source_file (const char *name) /* Read the whole number. */ while (ISDIGIT (*input_line_pointer)) { - temp = (temp * 10) + *input_line_pointer - '0'; + const long digit = *input_line_pointer - '0'; + if (temp > (LONG_MAX - digit) / 10) + { + as_bad (_("local label too large near %s"), backup); + temp = -1; + break; + } + temp = temp * 10 + digit; ++input_line_pointer; } + /* Overflow: stop processing the label. */ + if (temp == -1) + continue; + if (LOCAL_LABELS_DOLLAR && *input_line_pointer == '$' && *(input_line_pointer + 1) == ':') @@ -1224,7 +1237,7 @@ read_a_source_file (const char *name) if (dollar_label_defined (temp)) { - as_fatal (_("label \"%d$\" redefined"), temp); + as_fatal (_("label \"%ld$\" redefined"), temp); } define_dollar_label (temp); diff --git a/gas/testsuite/gas/all/gas.exp b/gas/testsuite/gas/all/gas.exp index 5496d0bf7a7..a0158f38dde 100644 --- a/gas/testsuite/gas/all/gas.exp +++ b/gas/testsuite/gas/all/gas.exp @@ -102,6 +102,7 @@ if { ![istarget "bfin-*-*"] } then { } gas_test_error "assign-bad.s" "" "== assignment for symbol already set" run_dump_test assign-bad-recursive +run_dump_test local-label-overflow run_dump_test simple-forward run_dump_test forward diff --git a/gas/testsuite/gas/all/local-label-overflow.d b/gas/testsuite/gas/all/local-label-overflow.d new file mode 100644 index 00000000000..956025c5767 --- /dev/null +++ b/gas/testsuite/gas/all/local-label-overflow.d @@ -0,0 +1,3 @@ +#source: local-label-overflow.s +#error_output: local-label-overflow.l +#notarget: hppa*-*-* ia64-*-vms mmix-*-* sh-*-pe diff --git a/gas/testsuite/gas/all/local-label-overflow.l b/gas/testsuite/gas/all/local-label-overflow.l new file mode 100644 index 00000000000..be24355bbd4 --- /dev/null +++ b/gas/testsuite/gas/all/local-label-overflow.l @@ -0,0 +1,2 @@ +[^:]*: Assembler messages: +.*: Error: local label too large near 888888888888888888888888888: diff --git a/gas/testsuite/gas/all/local-label-overflow.s b/gas/testsuite/gas/all/local-label-overflow.s new file mode 100644 index 00000000000..e5569217f44 --- /dev/null +++ b/gas/testsuite/gas/all/local-label-overflow.s @@ -0,0 +1 @@ +8888888888888888888888888888: -- 2.30.2