]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
replace atoi with strtoul in varasm.cc (decode_reg_name_and_count) [PR114540]
authorHeiko Eißfeldt <heiko@hexco.de>
Tue, 3 Dec 2024 08:47:59 +0000 (09:47 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 3 Dec 2024 08:47:59 +0000 (09:47 +0100)
The function uses atoi, which can silently return valid numbers even for
some too large numbers in the string.

Furthermore, the verification that all the characters in asmspec are
decimal digits can be simplified when using strotoul, we can check just
the first digit and whether the end pointer points to '\0'.

2024-12-03  Heiko Eißfeldt  <heiko@hexco.de>

PR middle-end/114540
* varasm.cc (decode_reg_name_and_count): Use strtoul instead of atoi
and simplify verification that the whole asmspec contains just decimal
digits.

* gcc.dg/pr114540.c: New test.

Signed-off-by: Heiko Eißfeldt <heiko@hexco.de>
Co-authored-by: Jakub Jelinek <jakub@redhat.com>
gcc/testsuite/gcc.dg/pr114540.c [new file with mode: 0644]
gcc/varasm.cc

diff --git a/gcc/testsuite/gcc.dg/pr114540.c b/gcc/testsuite/gcc.dg/pr114540.c
new file mode 100644 (file)
index 0000000..e59dffa
--- /dev/null
@@ -0,0 +1,31 @@
+/* PR middle-end/114540 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+void
+foo ()
+{
+  asm ("" : : : "2147483648");                 /* { dg-error "unknown register name" } */
+  asm ("" : : : "4294967296");                 /* { dg-error "unknown register name" } */
+  asm ("" : : : "18446744073709551616");       /* { dg-error "unknown register name" } */
+  asm ("" : : : "9223372036854775808");                /* { dg-error "unknown register name" } */
+  asm ("" : : : "9223372036854775807");                /* { dg-error "unknown register name" } */
+  asm ("" : : : "2147483647");                 /* { dg-error "unknown register name" } */
+  asm ("" : : : "4&");                         /* { dg-error "unknown register name" } */
+  asm ("" : : : "1'0");                                /* { dg-error "unknown register name" } */
+#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || defined(__s390__) || defined(__aarch64__) || defined(__arm__)
+  asm ("" : : : "0");
+#endif
+
+  register int a asm("2147483648");            /* { dg-error "invalid register name for" } */
+  register int b asm("4294967296");            /* { dg-error "invalid register name for" } */
+  register int c asm("18446744073709551616");  /* { dg-error "invalid register name for" } */
+  register int d asm("9223372036854775808");   /* { dg-error "invalid register name for" } */
+  register int e asm("9223372036854775807");   /* { dg-error "invalid register name for" } */
+  register int f asm("2147483647");            /* { dg-error "invalid register name for" } */
+  register int g asm("4&");                    /* { dg-error "invalid register name for" } */
+  register int h asm("1'0");                   /* { dg-error "invalid register name for" } */
+#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || defined(__s390__) || defined(__aarch64__) || defined(__arm__)
+  register int i asm("0");
+#endif
+}
index be11123180cdf31eb3263ab4505568434ff1f21c..261621a18c730cf4b70ff787ccc3c6d591267d1d 100644 (file)
@@ -990,16 +990,21 @@ decode_reg_name_and_count (const char *asmspec, int *pnregs)
       asmspec = strip_reg_name (asmspec);
 
       /* Allow a decimal number as a "register name".  */
-      for (i = strlen (asmspec) - 1; i >= 0; i--)
-       if (! ISDIGIT (asmspec[i]))
-         break;
-      if (asmspec[0] != 0 && i < 0)
+      if (ISDIGIT (asmspec[0]))
        {
-         i = atoi (asmspec);
-         if (i < FIRST_PSEUDO_REGISTER && i >= 0 && reg_names[i][0])
-           return i;
-         else
-           return -2;
+         char *pend;
+         errno = 0;
+         unsigned long j = strtoul (asmspec, &pend, 10);
+         if (*pend == '\0')
+           {
+             static_assert (FIRST_PSEUDO_REGISTER <= INT_MAX, "");
+             if (errno != ERANGE
+                 && j < FIRST_PSEUDO_REGISTER
+                 && reg_names[j][0])
+               return j;
+             else
+               return -2;
+           }
        }
 
       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)