Straight forward replacements of atoi() with strtoul() in order to avoid UB
and detect invalid argument values.

Tested with x86_64-pc-linux-gnu.
2024-12-16 Heiko Eißfeldt <he...@hexco.de>

    PR lto/114542
    * lto-wrapper.cc (run_gcc):
    Use strtoul with ERANGE check instead of atoi

    * lto/lto.cc (do_whole_program_analysis):
    ditto

    * opts.cc (common_handle_option):
    ditto

    * gcc.dg/pr114542.c: new test case

Signed-off-by: Heiko Eißfeldt <he...@hexco.de>
diff --git a/gcc/lto-wrapper.cc b/gcc/lto-wrapper.cc
index 661ba3c6f34..5c1d08ece30 100644
--- a/gcc/lto-wrapper.cc
+++ b/gcc/lto-wrapper.cc
@@ -1637,9 +1637,19 @@ run_gcc (unsigned argc, char *argv[])
            }
          else
            {
-             parallel = atoi (option->arg);
-             if (parallel <= 1)
-               parallel = 0;
+             char *pend;
+             errno = 0;
+             const auto i = strtoul (option->arg, &pend, 10);
+             if (option->arg[0] == '-'
+                 || errno == ERANGE
+                 || *pend != '\0')
+               {
+                 parallel = 0;
+               }
+             else
+               {
+                 parallel = i > INT_MAX ? INT_MAX : i;
+               }
            }
          /* Fallthru.  */
 
diff --git a/gcc/lto/lto.cc b/gcc/lto/lto.cc
index 1ee215d8f1d..2ee2740782d 100644
--- a/gcc/lto/lto.cc
+++ b/gcc/lto/lto.cc
@@ -497,11 +497,21 @@ do_whole_program_analysis (void)
     }
   else
     {
-      lto_parallelism = atoi (flag_wpa);
-      if (lto_parallelism <= 0)
-       lto_parallelism = 0;
-      if (lto_parallelism >= param_max_lto_streaming_parallelism)
-       lto_parallelism = param_max_lto_streaming_parallelism;
+      char *pend;
+      errno = 0;
+      const auto i = strtoul (flag_wpa, &pend, 10);
+      if (flag_wpa[0] == '-'
+         || errno == ERANGE
+         || *pend != '\0')
+       {
+         lto_parallelism = 0;
+         /* FIXME add a diagnostic? */
+       }
+      else
+       {
+         lto_parallelism = i > (unsigned 
long)param_max_lto_streaming_parallelism ?
+           (unsigned long)param_max_lto_streaming_parallelism : i;
+       }
     }
 
   timevar_start (TV_PHASE_OPT_GEN);
diff --git a/gcc/opts.cc b/gcc/opts.cc
index fa64bb7734a..4ffb3df880c 100644
--- a/gcc/opts.cc
+++ b/gcc/opts.cc
@@ -3312,7 +3312,16 @@ common_handle_option (struct gcc_options *opts,
       if (strcmp (arg, "none") != 0
          && strcmp (arg, "jobserver") != 0
          && strcmp (arg, "auto") != 0
-         && atoi (arg) == 0)
+         && [](const char *arg) {
+           char *pend;
+           errno = 0;
+           const auto i = strtoul (arg, &pend, 10);
+           return
+             arg[0] == '-'
+             || errno == ERANGE
+             || *pend != '\0'
+             || i > INT_MAX;
+         } (arg))
        error_at (loc,
                  "unrecognized argument to %<-flto=%> option: %qs", arg);
       break;
diff --git a/gcc/testsuite/gcc.dg/pr114542.c b/gcc/testsuite/gcc.dg/pr114542.c
new file mode 100644
index 00000000000..49eec89e00d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr114542.c
@@ -0,0 +1,4 @@
+/* PR lto/144542 */
+/* { dg-do compile } */
+/* { dg-options "-flto=2147483648" } */
+/* { dg-error "unrecognized argument to '-flto=' option: '2147483648'" "" { 
target *-*-* } 0 } */

Reply via email to