Use strtol() instead of atoi()

strtol() is part of C89 and a fallback is provided by gnulib.

* src/function.c (func_word, func_wordlist): Change atoi to strtol.
* test/scripts/functions/word: Add out-of-range verification testing.
This commit is contained in:
Jouke Witteveen 2021-07-16 14:04:33 +02:00 committed by Paul Smith
parent f3ad572099
commit d9291d09b8
3 changed files with 35 additions and 29 deletions

View File

@ -51,4 +51,5 @@ getloadavg
host-cpu-c-abi
mempcpy
strerror
strtol
make-glob"

View File

@ -765,35 +765,36 @@ 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);
const char *end = s + strlen (s) - 1;
char *endp;
long num;
strip_whitespace (&beg, &end);
for (; s <= end; ++s)
if (!ISDIGIT (*s)) /* ISDIGIT only evals its arg once: see makeint.h. */
break;
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);
if (s <= end || end - beg < 0)
OSS (fatal, *expanding_var, "%s: '%s'", msg, beg);
return num;
}
static char *
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"));
@ -811,20 +812,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)
{

View File

@ -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