From: Heiko Eißfeldt Date: Tue, 3 Dec 2024 08:47:59 +0000 (+0100) Subject: replace atoi with strtoul in varasm.cc (decode_reg_name_and_count) [PR114540] X-Git-Tag: basepoints/gcc-16~3676 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4acab372d31a9fe9184ccc247780940821cda367;p=thirdparty%2Fgcc.git replace atoi with strtoul in varasm.cc (decode_reg_name_and_count) [PR114540] 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 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 Co-authored-by: Jakub Jelinek --- diff --git a/gcc/testsuite/gcc.dg/pr114540.c b/gcc/testsuite/gcc.dg/pr114540.c new file mode 100644 index 000000000000..e59dffa1e90c --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr114540.c @@ -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 +} diff --git a/gcc/varasm.cc b/gcc/varasm.cc index be11123180cd..261621a18c73 100644 --- a/gcc/varasm.cc +++ b/gcc/varasm.cc @@ -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++)