bug-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 2/3] Use strtol instead of atoi


From: Jouke Witteveen
Subject: [PATCH 2/3] Use strtol instead of atoi
Date: Fri, 16 Jul 2021 14:04:33 +0200

strtol is part of C89 and a fallback is provided by gnulib

* src/function.c (func_word, func_wordlist): Use strtol instead of atoi
* test/scripts/functions/word: Add out-of-range verification testing
---
 bootstrap.conf               |  1 +
 src/function.c               | 51 ++++++++++++++++++------------------
 tests/scripts/functions/word | 12 ++++++---
 3 files changed, 36 insertions(+), 28 deletions(-)

diff --git a/bootstrap.conf b/bootstrap.conf
index 7c4c9ab..c9c3668 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -50,4 +50,5 @@ findprog-in
 getloadavg
 host-cpu-c-abi
 strerror
+strtol
 make-glob"
diff --git a/src/function.c b/src/function.c
index 396f129..964169a 100644
--- a/src/function.c
+++ b/src/function.c
@@ -766,19 +766,24 @@ strip_whitespace (const char **begpp, const char **endpp)
   return (char *)*begpp;
 }
 
-static void
-check_numeric (const char *s, const char *msg)
+static long
+parse_numeric (const char *s, const char *msg)
 {
-  const char *end = s + strlen (s) - 1;
   const char *beg = s;
-  strip_whitespace (&s, &end);
-
-  for (; s <= end; ++s)
-    if (!ISDIGIT (*s))  /* ISDIGIT only evals its arg once: see makeint.h.  */
-      break;
+  const char *end = s + strlen (s) - 1;
+  char *endp;
+  long num;
+  strip_whitespace (&beg, &end);
 
-  if (s <= end || end - beg < 0)
-    OSS (fatal, *expanding_var, "%s: '%s'", msg, beg);
+  errno = 0;
+  num = strtol (beg, &endp, 10);
+  if (errno == ERANGE)
+    OSS (fatal, *expanding_var, "%s: '%s'", strerror (errno), s);
+  else if (endp == beg || endp <= end)
+    /* Empty or non-numeric input */
+    OSS (fatal, *expanding_var, "%s: '%s'", msg, s);
+
+  return num;
 }
 
 
@@ -788,13 +793,11 @@ func_word (char *o, char **argv, const char *funcname 
UNUSED)
 {
   const char *end_p;
   const char *p;
-  int i;
+  long i;
 
-  /* Check the first argument.  */
-  check_numeric (argv[0], _("non-numeric first argument to 'word' function"));
-  i = atoi (argv[0]);
-
-  if (i == 0)
+  i = parse_numeric (argv[0],
+                     _("non-numeric first argument to 'word' function"));
+  if (i <= 0)
     O (fatal, *expanding_var,
        _("first argument to 'word' function must be greater than 0"));
 
@@ -812,20 +815,18 @@ func_word (char *o, char **argv, const char *funcname 
UNUSED)
 static char *
 func_wordlist (char *o, char **argv, const char *funcname UNUSED)
 {
-  int start, count;
+  long start, stop, count;
 
-  /* Check the arguments.  */
-  check_numeric (argv[0],
-                 _("non-numeric first argument to 'wordlist' function"));
-  check_numeric (argv[1],
-                 _("non-numeric second argument to 'wordlist' function"));
+  start = parse_numeric (argv[0],
+                         _("non-numeric first argument to 'wordlist' 
function"));
+  stop = parse_numeric (argv[1],
+                        _("non-numeric second argument to 'wordlist' 
function"));
 
-  start = atoi (argv[0]);
   if (start < 1)
     ON (fatal, *expanding_var,
-        "invalid first argument to 'wordlist' function: '%d'", start);
+        "invalid first argument to 'wordlist' function: '%ld'", start);
 
-  count = atoi (argv[1]) - start + 1;
+  count = stop - start + 1;
 
   if (count > 0)
     {
diff --git a/tests/scripts/functions/word b/tests/scripts/functions/word
index 4dcc940..044bc94 100644
--- a/tests/scripts/functions/word
+++ b/tests/scripts/functions/word
@@ -51,6 +51,7 @@ run_make_test('FOO = foo bar biz baz
 word-e1: ; @echo $(word ,$(FOO))
 word-e2: ; @echo $(word abc ,$(FOO))
 word-e3: ; @echo $(word 1a,$(FOO))
+word-e4: ; @echo $(word 9999999999999999999,$(FOO))
 
 wordlist-e1: ; @echo $(wordlist ,,$(FOO))
 wordlist-e2: ; @echo $(wordlist abc ,,$(FOO))
@@ -69,19 +70,24 @@ run_make_test(undef,
               "#MAKEFILE#:5: *** non-numeric first argument to 'word' 
function: '1a'.  Stop.",
               512);
 
+run_make_test(undef,
+              'word-e4',
+              "#MAKEFILE#:6: *** Numerical result out of range: 
'9999999999999999999'.  Stop.",
+              512);
+
 run_make_test(undef,
               'wordlist-e1',
-              "#MAKEFILE#:7: *** non-numeric first argument to 'wordlist' 
function: ''.  Stop.",
+              "#MAKEFILE#:8: *** non-numeric first argument to 'wordlist' 
function: ''.  Stop.",
               512);
 
 run_make_test(undef,
               'wordlist-e2',
-              "#MAKEFILE#:8: *** non-numeric first argument to 'wordlist' 
function: 'abc '.  Stop.",
+              "#MAKEFILE#:9: *** non-numeric first argument to 'wordlist' 
function: 'abc '.  Stop.",
               512);
 
 run_make_test(undef,
               'wordlist-e3',
-              "#MAKEFILE#:9: *** non-numeric second argument to 'wordlist' 
function: ' 12a '.  Stop.",
+              "#MAKEFILE#:10: *** non-numeric second argument to 'wordlist' 
function: ' 12a '.  Stop.",
               512);
 
 # Test error conditions again, but this time in a variable reference
-- 
2.32.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]