gas: Fix internal error on long local labels
authorAlex Coplan <alex.coplan@arm.com>
Thu, 6 Aug 2020 16:39:03 +0000 (17:39 +0100)
committerAlex Coplan <alex.coplan@arm.com>
Thu, 6 Aug 2020 16:39:03 +0000 (17:39 +0100)
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  <alex.coplan@arm.com>

* 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
gas/read.c
gas/testsuite/gas/all/gas.exp
gas/testsuite/gas/all/local-label-overflow.d [new file with mode: 0644]
gas/testsuite/gas/all/local-label-overflow.l [new file with mode: 0644]
gas/testsuite/gas/all/local-label-overflow.s [new file with mode: 0644]

index 771e865d4b7a7fe0039ab13bcc68d4354fc8bf61..eac8ec4f9be1a7efd8f9bb5a1f52606938200362 100644 (file)
@@ -1,3 +1,12 @@
+2020-08-06  Alex Coplan  <alex.coplan@arm.com>
+
+       * 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  <chris@groessler.org>
 
        * gas/testsuite/gas/z8k/inout.d: Adapt to correct encoding of
index f192cc16d579d05443051fc33fe759bb08d4cc09..bd896580e5db04c7b4099c3a972f75de31a5cdab 100644 (file)
@@ -40,6 +40,8 @@
 #include "dw2gencfi.h"
 #include "wchar.h"
 
+#include <limits.h>
+
 #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);
index 5496d0bf7a7e4094e37559c6ca99b6937859b6a8..a0158f38dde220d863ed942bb9f0df41e1fa0517 100644 (file)
@@ -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 (file)
index 0000000..956025c
--- /dev/null
@@ -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 (file)
index 0000000..be24355
--- /dev/null
@@ -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 (file)
index 0000000..e556921
--- /dev/null
@@ -0,0 +1 @@
+8888888888888888888888888888: