summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2019-10-22 14:55:24 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2019-10-22 15:04:43 -0700
commit04b136e29853a53a7885371526c4616303c39bcc (patch)
tree41a421cefc35d11b72537a37bfa2eeeb42a18c3b
parented2db6886bc4dfa5be7c0a3a72a45024fdafe29f (diff)
downloadcoreutils-04b136e29853a53a7885371526c4616303c39bcc.tar.gz
all: improve parsing of numeric arguments
This addresses a longstanding "update all callers" FIXME in lib/xstrtol.c, by having programs check that numbers do not have unknown suffixes. The problem was also reported for 'shuf' by my student Maggie Huang while reimplementing a shuf subset in Python as an exercise in UCLA Computer Science 35L: https://web.cs.ucla.edu/classes/fall19/cs35L/assign/assign3.html This patch also improves the portability of the code to unusual platforms where ULONG_MAX < SIZE_MAX. * NEWS: Mention user-visible changes. * src/chgrp.c (parse_group): * src/chroot.c (parse_additional_groups): * src/du.c (main): * src/install.c (get_ids): * src/join.c (string_to_join_field): * src/ls.c (decode_switches): * src/md5sum.c (split_3): * src/shuf.c (main): * src/sort.c (specify_nthreads): * src/uniq.c (size_opt, main): Use uintmax_t instead of unsigned long, for portability to oddball platforms where unsigned long is not wide enough. * src/du.c (main): * src/expr.c (mpz_init_set_str) [!HAVE_GMP]: * src/install.c (get_ids): * src/ls.c (decode_switches): * src/mknod.c (main): * src/ptx.c (main): * src/shuf.c (main): * src/sort.c (specify_nmerge, specify_nthreads): Reject numbers with suffixes. * src/md5sum.c (split_3): Simplify.
-rw-r--r--NEWS7
-rw-r--r--src/chgrp.c4
-rw-r--r--src/chroot.c5
-rw-r--r--src/du.c8
-rw-r--r--src/expr.c2
-rw-r--r--src/install.c8
-rw-r--r--src/join.c5
-rw-r--r--src/ls.c19
-rw-r--r--src/md5sum.c21
-rw-r--r--src/mknod.c4
-rw-r--r--src/ptx.c4
-rw-r--r--src/shuf.c4
-rw-r--r--src/sort.c6
-rw-r--r--src/uniq.c9
14 files changed, 53 insertions, 53 deletions
diff --git a/NEWS b/NEWS
index 476c02aed..300a799ae 100644
--- a/NEWS
+++ b/NEWS
@@ -43,6 +43,13 @@ GNU coreutils NEWS -*- outline -*-
** Changes in behavior
+ Several programs now check that numbers end properly. For example,
+ 'du -d 1x' now reports an error instead of silently ignoring the 'x'.
+ Affected programs and options include du -d, expr's numeric operands
+ on non-GMP builds, install -g and -o, ls's TABSIZE environment
+ variable, mknod b and c, ptx -g and -w, shuf -n, and sort --batch-size
+ and --parallel.
+
date now parses military time zones in accordance with common usage:
"A" to "M" are equivalent to UTC+1 to UTC+12
"N" to "Y" are equivalent to UTC-1 to UTC-12
diff --git a/src/chgrp.c b/src/chgrp.c
index dfd39ae5e..b7393eef6 100644
--- a/src/chgrp.c
+++ b/src/chgrp.c
@@ -87,8 +87,8 @@ parse_group (const char *name)
gid = grp->gr_gid;
else
{
- unsigned long int tmp;
- if (! (xstrtoul (name, NULL, 10, &tmp, "") == LONGINT_OK
+ uintmax_t tmp;
+ if (! (xstrtoumax (name, NULL, 10, &tmp, "") == LONGINT_OK
&& tmp <= GID_T_MAX))
die (EXIT_FAILURE, 0, _("invalid group: %s"),
quote (name));
diff --git a/src/chroot.c b/src/chroot.c
index 42ea5fa92..ea55e7527 100644
--- a/src/chroot.c
+++ b/src/chroot.c
@@ -106,9 +106,10 @@ parse_additional_groups (char const *groups, GETGROUPS_T **pgids,
for (tmp = strtok (buffer, ","); tmp; tmp = strtok (NULL, ","))
{
struct group *g;
- unsigned long int value;
+ uintmax_t value;
- if (xstrtoul (tmp, NULL, 10, &value, "") == LONGINT_OK && value <= MAXGID)
+ if (xstrtoumax (tmp, NULL, 10, &value, "") == LONGINT_OK
+ && value <= MAXGID)
{
while (isspace (to_uchar (*tmp)))
tmp++;
diff --git a/src/du.c b/src/du.c
index 43c348159..a44b22e46 100644
--- a/src/du.c
+++ b/src/du.c
@@ -807,12 +807,12 @@ main (int argc, char **argv)
case 'd': /* --max-depth=N */
{
- unsigned long int tmp_ulong;
- if (xstrtoul (optarg, NULL, 0, &tmp_ulong, NULL) == LONGINT_OK
- && tmp_ulong <= SIZE_MAX)
+ uintmax_t tmp;
+ if (xstrtoumax (optarg, NULL, 0, &tmp, "") == LONGINT_OK
+ && tmp <= SIZE_MAX)
{
max_depth_specified = true;
- max_depth = tmp_ulong;
+ max_depth = tmp;
}
else
{
diff --git a/src/expr.c b/src/expr.c
index 3ce61b203..08d7277ec 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -60,7 +60,7 @@ static void mpz_init_set_ui (mpz_t z, unsigned long int i) { z[0] = i; }
static int
mpz_init_set_str (mpz_t z, char *s, int base)
{
- return xstrtoimax (s, NULL, base, z, NULL) == LONGINT_OK ? 0 : -1;
+ return xstrtoimax (s, NULL, base, z, "") == LONGINT_OK ? 0 : -1;
}
static void
mpz_add (mpz_t r, mpz_t a0, mpz_t b0)
diff --git a/src/install.c b/src/install.c
index bde69c994..8b02be965 100644
--- a/src/install.c
+++ b/src/install.c
@@ -583,8 +583,8 @@ get_ids (void)
pw = getpwnam (owner_name);
if (pw == NULL)
{
- unsigned long int tmp;
- if (xstrtoul (owner_name, NULL, 0, &tmp, NULL) != LONGINT_OK
+ uintmax_t tmp;
+ if (xstrtoumax (owner_name, NULL, 0, &tmp, "") != LONGINT_OK
|| UID_T_MAX < tmp)
die (EXIT_FAILURE, 0, _("invalid user %s"),
quote (owner_name));
@@ -602,8 +602,8 @@ get_ids (void)
gr = getgrnam (group_name);
if (gr == NULL)
{
- unsigned long int tmp;
- if (xstrtoul (group_name, NULL, 0, &tmp, NULL) != LONGINT_OK
+ uintmax_t tmp;
+ if (xstrtoumax (group_name, NULL, 0, &tmp, "") != LONGINT_OK
|| GID_T_MAX < tmp)
die (EXIT_FAILURE, 0, _("invalid group %s"),
quote (group_name));
diff --git a/src/join.c b/src/join.c
index dd0ce42bc..64156a22c 100644
--- a/src/join.c
+++ b/src/join.c
@@ -839,10 +839,9 @@ static size_t
string_to_join_field (char const *str)
{
size_t result;
- unsigned long int val;
- verify (SIZE_MAX <= ULONG_MAX);
+ uintmax_t val;
- strtol_error s_err = xstrtoul (str, NULL, 10, &val, "");
+ strtol_error s_err = xstrtoumax (str, NULL, 10, &val, "");
if (s_err == LONGINT_OVERFLOW || (s_err == LONGINT_OK && SIZE_MAX < val))
val = SIZE_MAX;
else if (s_err != LONGINT_OK || val == 0)
diff --git a/src/ls.c b/src/ls.c
index 034087f26..d02653b48 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -1902,18 +1902,15 @@ decode_switches (int argc, char **argv)
tabsize = 8;
if (p)
{
- unsigned long int tmp_ulong;
- if (xstrtoul (p, NULL, 0, &tmp_ulong, NULL) == LONGINT_OK
- && tmp_ulong <= SIZE_MAX)
- {
- tabsize = tmp_ulong;
- }
+ uintmax_t tmp;
+ if (xstrtoumax (p, NULL, 0, &tmp, "") == LONGINT_OK
+ && tmp <= SIZE_MAX)
+ tabsize = tmp;
else
- {
- error (0, 0,
- _("ignoring invalid tab size in environment variable TABSIZE: %s"),
- quote (p));
- }
+ error (0, 0,
+ _("ignoring invalid tab size in environment variable TABSIZE:"
+ " %s"),
+ quote (p));
}
}
diff --git a/src/md5sum.c b/src/md5sum.c
index f75b6de02..de847ccb2 100644
--- a/src/md5sum.c
+++ b/src/md5sum.c
@@ -450,26 +450,23 @@ split_3 (char *s, size_t s_len,
ptrdiff_t algo = argmatch (algo_name, algorithm_out_string, NULL, 0);
if (algo < 0)
return false;
- else
- b2_algorithm = algo;
+ b2_algorithm = algo;
if (openssl_format)
s[--i] = '(';
+ b2_length = blake2_max_len[b2_algorithm] * 8;
if (length_specified)
{
- unsigned long int tmp_ulong;
- if (xstrtoul (s + i, NULL, 0, &tmp_ulong, NULL) == LONGINT_OK
- && 0 < tmp_ulong && tmp_ulong <= blake2_max_len[b2_algorithm] * 8
- && tmp_ulong % 8 == 0)
- b2_length = tmp_ulong;
- else
+ uintmax_t length;
+ char *siend;
+ if (! (xstrtoumax (s + i, &siend, 0, &length, NULL) == LONGINT_OK
+ && 0 < length && length <= b2_length
+ && length % 8 == 0))
return false;
- while (ISDIGIT (s[i]))
- ++i;
+ i = siend - s;
+ b2_length = length;
}
- else
- b2_length = blake2_max_len[b2_algorithm] * 8;
digest_hex_bytes = b2_length / 4;
#endif
diff --git a/src/mknod.c b/src/mknod.c
index 7f7cbc739..3f430af46 100644
--- a/src/mknod.c
+++ b/src/mknod.c
@@ -230,12 +230,12 @@ main (int argc, char **argv)
uintmax_t i_major, i_minor;
dev_t device;
- if (xstrtoumax (s_major, NULL, 0, &i_major, NULL) != LONGINT_OK
+ if (xstrtoumax (s_major, NULL, 0, &i_major, "") != LONGINT_OK
|| i_major != (major_t) i_major)
die (EXIT_FAILURE, 0,
_("invalid major device number %s"), quote (s_major));
- if (xstrtoumax (s_minor, NULL, 0, &i_minor, NULL) != LONGINT_OK
+ if (xstrtoumax (s_minor, NULL, 0, &i_minor, "") != LONGINT_OK
|| i_minor != (minor_t) i_minor)
die (EXIT_FAILURE, 0,
_("invalid minor device number %s"), quote (s_minor));
diff --git a/src/ptx.c b/src/ptx.c
index 3f2344055..779b78c90 100644
--- a/src/ptx.c
+++ b/src/ptx.c
@@ -1940,7 +1940,7 @@ main (int argc, char **argv)
case 'g':
{
intmax_t tmp;
- if (! (xstrtoimax (optarg, NULL, 0, &tmp, NULL) == LONGINT_OK
+ if (! (xstrtoimax (optarg, NULL, 0, &tmp, "") == LONGINT_OK
&& 0 < tmp && tmp <= PTRDIFF_MAX))
die (EXIT_FAILURE, 0, _("invalid gap width: %s"),
quote (optarg));
@@ -1967,7 +1967,7 @@ main (int argc, char **argv)
case 'w':
{
intmax_t tmp;
- if (! (xstrtoimax (optarg, NULL, 0, &tmp, NULL) == LONGINT_OK
+ if (! (xstrtoimax (optarg, NULL, 0, &tmp, "") == LONGINT_OK
&& 0 < tmp && tmp <= PTRDIFF_MAX))
die (EXIT_FAILURE, 0, _("invalid line width: %s"),
quote (optarg));
diff --git a/src/shuf.c b/src/shuf.c
index 6a1aa0158..37a5a5554 100644
--- a/src/shuf.c
+++ b/src/shuf.c
@@ -440,8 +440,8 @@ main (int argc, char **argv)
case 'n':
{
- unsigned long int argval;
- strtol_error e = xstrtoul (optarg, NULL, 10, &argval, NULL);
+ uintmax_t argval;
+ strtol_error e = xstrtoumax (optarg, NULL, 10, &argval, "");
if (e == LONGINT_OK)
head_lines = MIN (head_lines, argval);
diff --git a/src/sort.c b/src/sort.c
index 360a1f140..b2336894f 100644
--- a/src/sort.c
+++ b/src/sort.c
@@ -1330,7 +1330,7 @@ specify_nmerge (int oi, char c, char const *s)
{
uintmax_t n;
struct rlimit rlimit;
- enum strtol_error e = xstrtoumax (s, NULL, 10, &n, NULL);
+ enum strtol_error e = xstrtoumax (s, NULL, 10, &n, "");
/* Try to find out how many file descriptors we'll be able
to open. We need at least nmerge + 3 (STDIN_FILENO,
@@ -1443,8 +1443,8 @@ specify_sort_size (int oi, char c, char const *s)
static size_t
specify_nthreads (int oi, char c, char const *s)
{
- unsigned long int nthreads;
- enum strtol_error e = xstrtoul (s, NULL, 10, &nthreads, "");
+ uintmax_t nthreads;
+ enum strtol_error e = xstrtoumax (s, NULL, 10, &nthreads, "");
if (e == LONGINT_OVERFLOW)
return SIZE_MAX;
if (e != LONGINT_OK)
diff --git a/src/uniq.c b/src/uniq.c
index 9600ec094..836473624 100644
--- a/src/uniq.c
+++ b/src/uniq.c
@@ -240,10 +240,9 @@ strict_posix2 (void)
static size_t
size_opt (char const *opt, char const *msgid)
{
- unsigned long int size;
- verify (SIZE_MAX <= ULONG_MAX);
+ uintmax_t size;
- switch (xstrtoul (opt, NULL, 10, &size, ""))
+ switch (xstrtoumax (opt, NULL, 10, &size, ""))
{
case LONGINT_OK:
case LONGINT_OVERFLOW:
@@ -539,10 +538,10 @@ main (int argc, char **argv)
{
case 1:
{
- unsigned long int size;
+ uintmax_t size;
if (optarg[0] == '+'
&& ! strict_posix2 ()
- && xstrtoul (optarg, NULL, 10, &size, "") == LONGINT_OK
+ && xstrtoumax (optarg, NULL, 10, &size, "") == LONGINT_OK
&& size <= SIZE_MAX)
skip_chars = size;
else if (nfiles == 2)