From 6894816c653adef54f3a85becbf75a865d6d39d6 Mon Sep 17 00:00:00 2001 From: Pádraig Brady Date: Tue, 16 Dec 2014 12:36:39 +0000 Subject: diagnose too-large numbers better Following on from commit v8.23-82-gaddae94, consistently diagnose numbers that are too large, so as to distinguish from other errors, and make the limits obvious. * gl/modules/xdectoint: A new module implementing xdecto[iu]max(), which handles the common case of parsing a bounded integer and exiting with a diagnostic on error. * gl/lib/xdectoimax.c: The signed variant. * gl/lib/xdectoint.c: The parameterized implementation. * gl/lib/xdectoint.h: The interface. * gl/lib/xdectoumax.c: The unsigned variant. * bootstrap.conf: Reference the new module. * cfg.mk (exclude_file_name_regexp--sc_require_config_h_first): Exclude the parameterized templates. * src/csplit.c: Output EOVERFLOW or ERANGE errors if appropriate. * src/fmt.c: Likewise. * src/fold.c: Likewise. * src/head.c: Likewise. * src/ls.c: Likewise. * src/nl.c: Likewise. * src/nproc.c: Likewise. * src/shred.c: Likewise. * src/shuf.c: Likewise. * src/stdbuf.c: Likewise. * src/stty.c: Likewise. * src/tail.c: Likewise. * src/truncate.c: Likewise. * src/split.c: Likewise. * src/pr.c: Likewise. * tests/pr/pr-tests.pl: Adjust to avoid matching errno diagnostic. * tests/fmt/base.pl: Likewise. * tests/split/l-chunk.sh: Likewise. * tests/misc/shred-negative.sh: Likewise. * tests/misc/tail.pl: Likewise. Also remove the redundant existing ERR_SUBST from test err-6. * tests/ls/hex-option.sh: Check HEX/OCT options. * tests/misc/shred-size.sh: Likewise. * tests/misc/stty-row-col.sh: Likewise. --- src/csplit.c | 8 ++--- src/dd.c | 2 +- src/fmt.c | 18 +++-------- src/fold.c | 13 ++------ src/head.c | 32 +++++-------------- src/ls.c | 25 +++++---------- src/nl.c | 46 ++++++--------------------- src/nproc.c | 8 ++--- src/pr.c | 98 +++++++++++++++++++++------------------------------------- src/shred.c | 29 +++++------------ src/shuf.c | 19 +++++------- src/split.c | 94 +++++++++++++++++++------------------------------------ src/stdbuf.c | 4 +-- src/stty.c | 9 ++---- src/tail.c | 46 +++++++++------------------ src/truncate.c | 36 +++------------------ 16 files changed, 142 insertions(+), 345 deletions(-) (limited to 'src') diff --git a/src/csplit.c b/src/csplit.c index af72d8f67..15c477178 100644 --- a/src/csplit.c +++ b/src/csplit.c @@ -33,6 +33,7 @@ #include "quote.h" #include "safe-read.h" #include "stdio--.h" +#include "xdectoint.h" #include "xstrtol.h" /* The official name of this program (e.g., no 'g' prefix). */ @@ -1332,7 +1333,6 @@ int main (int argc, char **argv) { int optc; - unsigned long int val; initialize_main (&argc, &argv); set_program_name (argv[0]); @@ -1366,10 +1366,8 @@ main (int argc, char **argv) break; case 'n': - if (xstrtoul (optarg, NULL, 10, &val, "") != LONGINT_OK - || MIN (INT_MAX, SIZE_MAX) < val) - error (EXIT_FAILURE, 0, _("%s: invalid number"), optarg); - digits = val; + digits = xdectoimax (optarg, 0, MIN (INT_MAX, SIZE_MAX), "", + _("invalid number"), 0); break; case 's': diff --git a/src/dd.c b/src/dd.c index d652fee14..49d0d2a0c 100644 --- a/src/dd.c +++ b/src/dd.c @@ -1433,7 +1433,7 @@ scanargs (int argc, char *const *argv) if (invalid != LONGINT_OK) error (EXIT_FAILURE, invalid == LONGINT_OVERFLOW ? EOVERFLOW : 0, - _("invalid number %s"), quote (val)); + "%s: %s", _("invalid number"), quote (val)); } } diff --git a/src/fmt.c b/src/fmt.c index f235da9ac..e3719d2c3 100644 --- a/src/fmt.c +++ b/src/fmt.c @@ -30,7 +30,7 @@ #include "error.h" #include "fadvise.h" #include "quote.h" -#include "xstrtol.h" +#include "xdectoint.h" /* The official name of this program (e.g., no 'g' prefix). */ #define PROGRAM_NAME "fmt" @@ -399,23 +399,15 @@ main (int argc, char **argv) { /* Limit max_width to MAXCHARS / 2; otherwise, the resulting output can be quite ugly. */ - unsigned long int tmp; - if (! (xstrtoul (max_width_option, NULL, 10, &tmp, "") == LONGINT_OK - && tmp <= MAXCHARS / 2)) - error (EXIT_FAILURE, 0, _("invalid width: %s"), - quote (max_width_option)); - max_width = tmp; + max_width = xdectoumax (max_width_option, 0, MAXCHARS / 2, "", + _("invalid width"), 0); } if (goal_width_option) { /* Limit goal_width to max_width. */ - unsigned long int tmp; - if (! (xstrtoul (goal_width_option, NULL, 10, &tmp, "") == LONGINT_OK - && tmp <= max_width)) - error (EXIT_FAILURE, 0, _("invalid width: %s"), - quote (goal_width_option)); - goal_width = tmp; + goal_width = xdectoumax (goal_width_option, 0, max_width, "", + _("invalid width"), 0); if (max_width_option == NULL) max_width = goal_width + 10; } diff --git a/src/fold.c b/src/fold.c index 3bc9ba29f..20cb61eca 100644 --- a/src/fold.c +++ b/src/fold.c @@ -25,8 +25,7 @@ #include "system.h" #include "error.h" #include "fadvise.h" -#include "quote.h" -#include "xstrtol.h" +#include "xdectoint.h" #define TAB_WIDTH 8 @@ -280,14 +279,8 @@ main (int argc, char **argv) } /* Fall through. */ case 'w': /* Line width. */ - { - unsigned long int tmp_ulong; - if (! (xstrtoul (optarg, NULL, 10, &tmp_ulong, "") == LONGINT_OK - && 0 < tmp_ulong && tmp_ulong < SIZE_MAX - TAB_WIDTH)) - error (EXIT_FAILURE, 0, - _("invalid number of columns: %s"), quote (optarg)); - width = tmp_ulong; - } + width = xdectoumax (optarg, 1, SIZE_MAX - TAB_WIDTH - 1, "", + _("invalid number of columns"), 0); break; case_GETOPT_HELP_CHAR; diff --git a/src/head.c b/src/head.c index 2782f8e8c..7fc161a49 100644 --- a/src/head.c +++ b/src/head.c @@ -38,7 +38,7 @@ #include "safe-read.h" #include "stat-size.h" #include "xfreopen.h" -#include "xstrtol.h" +#include "xdectoint.h" /* The official name of this program (e.g., no 'g' prefix). */ #define PROGRAM_NAME "head" @@ -893,7 +893,7 @@ head_file (const char *filename, uintmax_t n_units, bool count_lines, return ok; } -/* Convert a string of decimal digits, N_STRING, with an optional suffinx +/* Convert a string of decimal digits, N_STRING, with an optional suffix to an integral value. Upon successful conversion, return that value. If it cannot be converted, give a diagnostic and exit. COUNT_LINES indicates whether N_STRING is a number of bytes or a number @@ -902,27 +902,9 @@ head_file (const char *filename, uintmax_t n_units, bool count_lines, static uintmax_t string_to_integer (bool count_lines, const char *n_string) { - strtol_error s_err; - uintmax_t n; - - s_err = xstrtoumax (n_string, NULL, 10, &n, "bkKmMGTPEZY0"); - - if (s_err == LONGINT_OVERFLOW) - { - error (EXIT_FAILURE, 0, - _("%s: %s is so large that it is not representable"), n_string, - count_lines ? _("number of lines") : _("number of bytes")); - } - - if (s_err != LONGINT_OK) - { - error (EXIT_FAILURE, 0, "%s: %s", n_string, - (count_lines - ? _("invalid number of lines") - : _("invalid number of bytes"))); - } - - return n; + return xdectoumax (n_string, 0, UINTMAX_MAX, "bkKmMGTPEZY0", + count_lines ? _("invalid number of lines") + : _("invalid number of bytes"), 0); } int @@ -1076,8 +1058,8 @@ main (int argc, char **argv) if ( ! count_lines && elide_from_end && OFF_T_MAX < n_units) { char umax_buf[INT_BUFSIZE_BOUND (n_units)]; - error (EXIT_FAILURE, 0, _("%s: number of bytes is too large"), - umaxtostr (n_units, umax_buf)); + error (EXIT_FAILURE, EOVERFLOW, "%s: %s", _("invalid number of bytes"), + quote (umaxtostr (n_units, umax_buf))); } file_list = (optind < argc diff --git a/src/ls.c b/src/ls.c index 5bae06fbe..82402ee77 100644 --- a/src/ls.c +++ b/src/ls.c @@ -105,6 +105,7 @@ #include "stat-size.h" #include "stat-time.h" #include "strftime.h" +#include "xdectoint.h" #include "xstrtol.h" #include "areadlink.h" #include "mbsalign.h" @@ -1742,15 +1743,9 @@ decode_switches (int argc, char **argv) break; case 'w': - { - unsigned long int tmp_ulong; - if (xstrtoul (optarg, NULL, 0, &tmp_ulong, NULL) != LONGINT_OK - || ! (0 < tmp_ulong && tmp_ulong <= SIZE_MAX)) - error (LS_FAILURE, 0, _("invalid line width: %s"), - quotearg (optarg)); - line_length = tmp_ulong; - break; - } + line_length = xnumtoumax (optarg, 0, 1, SIZE_MAX, "", + _("invalid line width"), LS_FAILURE); + break; case 'x': format = horizontal; @@ -1816,15 +1811,9 @@ decode_switches (int argc, char **argv) break; case 'T': - { - unsigned long int tmp_ulong; - if (xstrtoul (optarg, NULL, 0, &tmp_ulong, NULL) != LONGINT_OK - || SIZE_MAX < tmp_ulong) - error (LS_FAILURE, 0, _("invalid tab size: %s"), - quotearg (optarg)); - tabsize = tmp_ulong; - break; - } + tabsize = xnumtoumax (optarg, 0, 0, SIZE_MAX, "", + _("invalid tab size"), LS_FAILURE); + break; case 'U': sort_type = sort_none; diff --git a/src/nl.c b/src/nl.c index 7fc113442..5c341620a 100644 --- a/src/nl.c +++ b/src/nl.c @@ -31,7 +31,7 @@ #include "fadvise.h" #include "linebuffer.h" #include "quote.h" -#include "xstrtol.h" +#include "xdectoint.h" /* The official name of this program (e.g., no 'g' prefix). */ #define PROGRAM_NAME "nl" @@ -497,53 +497,27 @@ main (int argc, char **argv) } break; case 'v': - if (xstrtoimax (optarg, NULL, 10, &starting_line_number, "") - != LONGINT_OK) - { - error (0, 0, _("invalid starting line number: %s"), - quote (optarg)); - ok = false; - } + starting_line_number = xdectoimax (optarg, INTMAX_MIN, INTMAX_MAX, "", + _("invalid starting line number"), + 0); break; case 'i': - if (! (xstrtoimax (optarg, NULL, 10, &page_incr, "") == LONGINT_OK - && 0 < page_incr)) - { - error (0, 0, _("invalid line number increment: %s"), - quote (optarg)); - ok = false; - } + page_incr = xdectoimax (optarg, 1, INTMAX_MAX, "", + _("invalid line number increment"), 0); break; case 'p': reset_numbers = false; break; case 'l': - if (! (xstrtoimax (optarg, NULL, 10, &blank_join, "") == LONGINT_OK - && 0 < blank_join)) - { - error (0, 0, _("invalid number of blank lines: %s"), - quote (optarg)); - ok = false; - } + blank_join = xdectoimax (optarg, 1, INTMAX_MAX, "", + _("invalid line number of blank lines"), 0); break; case 's': separator_str = optarg; break; case 'w': - { - long int tmp_long; - if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK - || tmp_long <= 0 || tmp_long > INT_MAX) - { - error (0, 0, _("invalid line number field width: %s"), - quote (optarg)); - ok = false; - } - else - { - lineno_width = tmp_long; - } - } + lineno_width = xdectoimax (optarg, 1, INT_MAX, "", + _("invalid line number field width"), 0); break; case 'n': if (STREQ (optarg, "ln")) diff --git a/src/nproc.c b/src/nproc.c index e1bc1d0b7..4ba146a34 100644 --- a/src/nproc.c +++ b/src/nproc.c @@ -25,7 +25,7 @@ #include "error.h" #include "nproc.h" #include "quote.h" -#include "xstrtol.h" +#include "xdectoint.h" /* The official name of this program (e.g., no 'g' prefix). */ #define PROGRAM_NAME "nproc" @@ -102,11 +102,7 @@ main (int argc, char **argv) break; case IGNORE_OPTION: - if (xstrtoul (optarg, NULL, 10, &ignore, "") != LONGINT_OK) - { - error (0, 0, _("%s: invalid number to ignore"), optarg); - usage (EXIT_FAILURE); - } + ignore = xdectoumax (optarg, 0, ULONG_MAX, "", _("invalid number"),0); break; default: diff --git a/src/pr.c b/src/pr.c index 529964985..d6823b513 100644 --- a/src/pr.c +++ b/src/pr.c @@ -322,6 +322,7 @@ #include "stdio--.h" #include "strftime.h" #include "xstrtol.h" +#include "xdectoint.h" /* The official name of this program (e.g., no 'g' prefix). */ #define PROGRAM_NAME "pr" @@ -424,6 +425,8 @@ static bool skip_to_page (uintmax_t page); static void print_header (void); static void pad_across_to (int position); static void add_line_number (COLUMN *p); +static void getoptnum (const char *n_str, int min, int *num, + const char *errfmt); static void getoptarg (char *arg, char switch_char, char *character, int *number); static void print_files (int number_of_files, char **av); @@ -820,18 +823,12 @@ first_last_page (int oi, char c, char const *pages) /* Parse column count string S, and if it's valid (1 or larger and within range of the type of 'columns') set the global variables - columns and explicit_columns and return true. - Otherwise, exit with a diagnostic. */ + columns and explicit_columns. Otherwise, exit with a diagnostic. */ + static void parse_column_count (char const *s) { - long int tmp_long; - if (xstrtol (s, NULL, 10, &tmp_long, "") != LONGINT_OK - || !(1 <= tmp_long && tmp_long <= INT_MAX)) - error (EXIT_FAILURE, 0, - _("invalid number of columns: %s"), quote (s)); - - columns = tmp_long; + getoptnum (s, 1, &columns, _("invalid number of columns")); explicit_columns = true; } @@ -966,18 +963,9 @@ main (int argc, char **argv) join_lines = true; break; case 'l': - { - long int tmp_long; - if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK - || tmp_long <= 0 || tmp_long > INT_MAX) - { - error (EXIT_FAILURE, 0, - _("'-l PAGE_LENGTH' invalid number of lines: %s"), - quote (optarg)); - } - lines_per_page = tmp_long; - break; - } + getoptnum (optarg, 1, &lines_per_page, + _("'-l PAGE_LENGTH' invalid number of lines")); + break; case 'm': parallel_files = true; storing_columns = false; @@ -990,28 +978,13 @@ main (int argc, char **argv) break; case 'N': skip_count = false; - { - long int tmp_long; - if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK - || tmp_long > INT_MAX) - { - error (EXIT_FAILURE, 0, - _("'-N NUMBER' invalid starting line number: %s"), - quote (optarg)); - } - start_line_num = tmp_long; - break; - } + getoptnum (optarg, INT_MIN, &start_line_num, + _("'-N NUMBER' invalid starting line number")); + break; case 'o': - { - long int tmp_long; - if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK - || tmp_long < 0 || tmp_long > INT_MAX) - error (EXIT_FAILURE, 0, - _("'-o MARGIN' invalid line offset: %s"), quote (optarg)); - chars_per_margin = tmp_long; - break; - } + getoptnum (optarg, 0, &chars_per_margin, + _("'-o MARGIN' invalid line offset")); + break; case 'r': ignore_failed_opens = true; break; @@ -1045,29 +1018,19 @@ main (int argc, char **argv) old_options = true; old_w = true; { - long int tmp_long; - if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK - || tmp_long <= 0 || tmp_long > INT_MAX) - error (EXIT_FAILURE, 0, - _("'-w PAGE_WIDTH' invalid number of characters: %s"), - quote (optarg)); - if (!truncate_lines) - chars_per_line = tmp_long; - break; + int tmp_cpl; + getoptnum (optarg, 1, &tmp_cpl, + _("'-w PAGE_WIDTH' invalid number of characters")); + if (! truncate_lines) + chars_per_line = tmp_cpl; } + break; case 'W': old_w = false; /* dominates -w */ truncate_lines = true; - { - long int tmp_long; - if (xstrtol (optarg, NULL, 10, &tmp_long, "") != LONGINT_OK - || tmp_long <= 0 || tmp_long > INT_MAX) - error (EXIT_FAILURE, 0, - _("'-W PAGE_WIDTH' invalid number of characters: %s"), - quote (optarg)); - chars_per_line = tmp_long; - break; - } + getoptnum (optarg, 1, &chars_per_line, + _("'-W PAGE_WIDTH' invalid number of characters")); + break; case_GETOPT_HELP_CHAR; case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); default: @@ -1173,6 +1136,15 @@ main (int argc, char **argv) return failed_opens ? EXIT_FAILURE : EXIT_SUCCESS; } +/* Parse numeric arguments, ensuring MIN <= number <= INT_MAX. */ + +static void +getoptnum (const char *n_str, int min, int *num, const char *err) +{ + intmax_t tnum = xdectoimax (n_str, min, INT_MAX, "", err, 0); + *num = tnum; +} + /* Parse options of the form -scNNN. Example: -nck, where 'n' is the option, c is the optional number @@ -1188,9 +1160,9 @@ getoptarg (char *arg, char switch_char, char *character, int *number) { long int tmp_long; if (xstrtol (arg, NULL, 10, &tmp_long, "") != LONGINT_OK - || tmp_long <= 0 || tmp_long > INT_MAX) + || tmp_long <= 0 || INT_MAX < tmp_long) { - error (0, 0, + error (0, INT_MAX < tmp_long ? EOVERFLOW : errno, _("'-%c' extra characters or invalid number in the argument: %s"), switch_char, quote (arg)); usage (EXIT_FAILURE); diff --git a/src/shred.c b/src/shred.c index b235b29ae..2e5719914 100644 --- a/src/shred.c +++ b/src/shred.c @@ -86,7 +86,7 @@ #include "system.h" #include "argmatch.h" -#include "xstrtol.h" +#include "xdectoint.h" #include "error.h" #include "fcntl--.h" #include "human.h" @@ -1228,16 +1228,10 @@ main (int argc, char **argv) break; case 'n': - { - uintmax_t tmp; - if (xstrtoumax (optarg, NULL, 10, &tmp, NULL) != LONGINT_OK - || MIN (ULONG_MAX, SIZE_MAX / sizeof (int)) <= tmp) - { - error (EXIT_FAILURE, 0, _("%s: invalid number of passes"), - quotearg_colon (optarg)); - } - flags.n_iterations = tmp; - } + flags.n_iterations = xdectoumax (optarg, 0, + MIN (ULONG_MAX, + SIZE_MAX / sizeof (int)), "", + _("invalid number of passes"), 0); break; case RANDOM_SOURCE_OPTION: @@ -1255,17 +1249,8 @@ main (int argc, char **argv) break; case 's': - { - uintmax_t tmp; - if ((xstrtoumax (optarg, NULL, 0, &tmp, "cbBkKMGTPEZY0") - != LONGINT_OK) - || OFF_T_MAX < tmp) - { - error (EXIT_FAILURE, 0, _("%s: invalid file size"), - quotearg_colon (optarg)); - } - flags.size = tmp; - } + flags.size = xnumtoumax (optarg, 0, 0, OFF_T_MAX, "cbBkKMGTPEZY0", + _("invalid file size"), 0); break; case 'v': diff --git a/src/shuf.c b/src/shuf.c index df0092b90..0678c3da6 100644 --- a/src/shuf.c +++ b/src/shuf.c @@ -32,6 +32,7 @@ #include "randperm.h" #include "read-file.h" #include "stdio--.h" +#include "xdectoint.h" #include "xstrtol.h" /* The official name of this program (e.g., no 'g' prefix). */ @@ -422,7 +423,6 @@ main (int argc, char **argv) case 'i': { - unsigned long int argval = 0; char *p = strchr (optarg, '-'); char const *hi_optarg = optarg; bool invalid = !p; @@ -434,22 +434,19 @@ main (int argc, char **argv) if (p) { *p = '\0'; - invalid = ((xstrtoul (optarg, NULL, 10, &argval, NULL) - != LONGINT_OK) - || SIZE_MAX < argval); + lo_input = xdectoumax (optarg, 0, SIZE_MAX, "", + _("invalid input range"), 0); *p = '-'; - lo_input = argval; hi_optarg = p + 1; } - invalid |= ((xstrtoul (hi_optarg, NULL, 10, &argval, NULL) - != LONGINT_OK) - || SIZE_MAX < argval); - hi_input = argval; + hi_input = xdectoumax (hi_optarg, 0, SIZE_MAX, "", + _("invalid input range"), 0); + n_lines = hi_input - lo_input + 1; invalid |= ((lo_input <= hi_input) == (n_lines == 0)); if (invalid) - error (EXIT_FAILURE, 0, _("invalid input range %s"), + error (EXIT_FAILURE, errno, "%s: %s", _("invalid input range"), quote (optarg)); } break; @@ -462,7 +459,7 @@ main (int argc, char **argv) if (e == LONGINT_OK) head_lines = MIN (head_lines, argval); else if (e != LONGINT_OVERFLOW) - error (EXIT_FAILURE, 0, _("invalid line count %s"), + error (EXIT_FAILURE, 0, _("invalid line count: %s"), quote (optarg)); } break; diff --git a/src/split.c b/src/split.c index 0eec3ecc2..008d2a7e2 100644 --- a/src/split.c +++ b/src/split.c @@ -39,7 +39,7 @@ #include "safe-read.h" #include "sig2str.h" #include "xfreopen.h" -#include "xstrtol.h" +#include "xdectoint.h" /* The official name of this program (e.g., no 'g' prefix). */ #define PROGRAM_NAME "split" @@ -1174,19 +1174,20 @@ no_filters: } \ while (0) + /* Parse K/N syntax of chunk options. */ static void parse_chunk (uintmax_t *k_units, uintmax_t *n_units, char *slash) { - *slash = '\0'; - if (xstrtoumax (slash + 1, NULL, 10, n_units, "") != LONGINT_OK - || *n_units == 0) - error (EXIT_FAILURE, 0, _("%s: invalid number of chunks"), slash + 1); - if (slash != optarg /* a leading number is specified. */ - && (xstrtoumax (optarg, NULL, 10, k_units, "") != LONGINT_OK - || *k_units == 0 || *n_units < *k_units)) - error (EXIT_FAILURE, 0, _("%s: invalid chunk number"), optarg); + *n_units = xdectoumax (slash + 1, 1, UINTMAX_MAX, "", + _("invalid number of chunks"), 0); + if (slash != optarg) /* a leading number is specified. */ + { + *slash = '\0'; + *k_units = xdectoumax (optarg, 1, *n_units, "", + _("invalid chunk number"), 0); + } } @@ -1197,7 +1198,7 @@ main (int argc, char **argv) size_t in_blk_size = 0; /* optimal block size of input file device */ size_t page_size = getpagesize (); uintmax_t k_units = 0; - uintmax_t n_units; + uintmax_t n_units = 0; static char const multipliers[] = "bEGKkMmPTYZ0"; int c; @@ -1231,16 +1232,8 @@ main (int argc, char **argv) switch (c) { case 'a': - { - unsigned long tmp; - if (xstrtoul (optarg, NULL, 10, &tmp, "") != LONGINT_OK - || SIZE_MAX / sizeof (size_t) < tmp) - { - error (0, 0, _("%s: invalid suffix length"), optarg); - usage (EXIT_FAILURE); - } - suffix_length = tmp; - } + suffix_length = xdectoumax (optarg, 0, SIZE_MAX / sizeof (size_t), + "", _("invalid suffix length"), 0); break; case ADDITIONAL_SUFFIX_OPTION: @@ -1258,46 +1251,27 @@ main (int argc, char **argv) if (split_type != type_undef) FAIL_ONLY_ONE_WAY (); split_type = type_bytes; - if (xstrtoumax (optarg, NULL, 10, &n_units, multipliers) != LONGINT_OK - || n_units == 0) - { - error (0, 0, _("%s: invalid number of bytes"), optarg); - usage (EXIT_FAILURE); - } - /* If input is a pipe, we could get more data than is possible - to write to a single file, so indicate that immediately - rather than having possibly future invocations fail. */ - if (OFF_T_MAX < n_units) - error (EXIT_FAILURE, EFBIG, - _("%s: invalid number of bytes"), optarg); - + /* Limit to OFF_T_MAX, becaue if input is a pipe, we could get more + data than is possible to write to a single file, so indicate that + immediately rather than having possibly future invocations fail. */ + n_units = xdectoumax (optarg, 1, OFF_T_MAX, multipliers, + _("invalid number of bytes"), 0); break; case 'l': if (split_type != type_undef) FAIL_ONLY_ONE_WAY (); split_type = type_lines; - if (xstrtoumax (optarg, NULL, 10, &n_units, "") != LONGINT_OK - || n_units == 0) - { - error (0, 0, _("%s: invalid number of lines"), optarg); - usage (EXIT_FAILURE); - } + n_units = xdectoumax (optarg, 1, UINTMAX_MAX, "", + _("invalid number of lines"), 0); break; case 'C': if (split_type != type_undef) FAIL_ONLY_ONE_WAY (); split_type = type_byteslines; - if (xstrtoumax (optarg, NULL, 10, &n_units, multipliers) != LONGINT_OK - || n_units == 0 || SIZE_MAX < n_units) - { - error (0, 0, _("%s: invalid number of bytes"), optarg); - usage (EXIT_FAILURE); - } - if (OFF_T_MAX < n_units) - error (EXIT_FAILURE, EFBIG, - _("%s: invalid number of bytes"), optarg); + n_units = xdectoumax (optarg, 1, MIN (SIZE_MAX, OFF_T_MAX), + multipliers, _("invalid number of bytes"), 0); break; case 'n': @@ -1320,9 +1294,9 @@ main (int argc, char **argv) split_type = type_chunk_bytes; if ((slash = strchr (optarg, '/'))) parse_chunk (&k_units, &n_units, slash); - else if (xstrtoumax (optarg, NULL, 10, &n_units, "") != LONGINT_OK - || n_units == 0) - error (EXIT_FAILURE, 0, _("%s: invalid number of chunks"), optarg); + else + n_units = xdectoumax (optarg, 1, UINTMAX_MAX, "", + _("invalid number of chunks"), 0); break; case 'u': @@ -1388,15 +1362,8 @@ main (int argc, char **argv) break; case IO_BLKSIZE_OPTION: - { - uintmax_t tmp_blk_size; - if (xstrtoumax (optarg, NULL, 10, &tmp_blk_size, - multipliers) != LONGINT_OK - || tmp_blk_size == 0 || SIZE_MAX - page_size < tmp_blk_size) - error (0, 0, _("%s: invalid IO block size"), optarg); - else - in_blk_size = tmp_blk_size; - } + in_blk_size = xdectoumax (optarg, 1, SIZE_MAX - page_size, + multipliers, _("invalid IO block size"), 0); break; case VERBOSE_OPTION: @@ -1427,7 +1394,7 @@ main (int argc, char **argv) if (n_units == 0) { - error (0, 0, _("%s: invalid number of lines"), "0"); + error (0, 0, "%s: %s", _("invalid number of lines"), quote ("0")); usage (EXIT_FAILURE); } @@ -1505,8 +1472,9 @@ main (int argc, char **argv) if (OFF_T_MAX < n_units) { char buffer[INT_BUFSIZE_BOUND (uintmax_t)]; - error (EXIT_FAILURE, EFBIG, _("%s: invalid number of chunks"), - umaxtostr (n_units, buffer)); + error (EXIT_FAILURE, EOVERFLOW, "%s: %s", + _("invalid number of chunks"), + quote (umaxtostr (n_units, buffer))); } /* increase file_size to n_units here, so that we still process any input data, and create empty files for the rest. */ diff --git a/src/stdbuf.c b/src/stdbuf.c index 3fb5d3c42..94a7a4fca 100644 --- a/src/stdbuf.c +++ b/src/stdbuf.c @@ -66,7 +66,7 @@ parse_size (char const *str, size_t *size) { uintmax_t tmp_size; enum strtol_error e = xstrtoumax (str, NULL, 10, &tmp_size, "EGkKMPTYZ0"); - if (e == LONGINT_OK && tmp_size > SIZE_MAX) + if (e == LONGINT_OK && SIZE_MAX < tmp_size) e = LONGINT_OVERFLOW; if (e == LONGINT_OK) @@ -76,7 +76,7 @@ parse_size (char const *str, size_t *size) return 0; } - errno = (e == LONGINT_OVERFLOW ? EOVERFLOW : 0); + errno = (e == LONGINT_OVERFLOW ? EOVERFLOW : errno); return -1; } diff --git a/src/stty.c b/src/stty.c index 42ec3b447..41909b75e 100644 --- a/src/stty.c +++ b/src/stty.c @@ -58,6 +58,7 @@ #include "error.h" #include "fd-reopen.h" #include "quote.h" +#include "xdectoint.h" #include "xstrtol.h" /* The official name of this program (e.g., no 'g' prefix). */ @@ -2087,11 +2088,5 @@ visible (cc_t ch) static unsigned long int integer_arg (const char *s, unsigned long int maxval) { - unsigned long int value; - if (xstrtoul (s, NULL, 0, &value, "bB") != LONGINT_OK || maxval < value) - { - error (0, 0, _("invalid integer argument %s"), quote (s)); - usage (EXIT_FAILURE); - } - return value; + return xnumtoumax (s, 0, 0, maxval, "bB", _("invalid integer argument"), 0); } diff --git a/src/tail.c b/src/tail.c index 4c5f943c7..28524d71f 100644 --- a/src/tail.c +++ b/src/tail.c @@ -44,6 +44,7 @@ #include "stat-time.h" #include "xfreopen.h" #include "xnanosleep.h" +#include "xdectoint.h" #include "xstrtol.h" #include "xstrtod.h" @@ -1949,7 +1950,10 @@ parse_obsolete_option (int argc, char * const *argv, uintmax_t *n_units) else if ((xstrtoumax (n_string, NULL, 10, n_units, "b") & ~LONGINT_INVALID_SUFFIX_CHAR) != LONGINT_OK) - error (EXIT_FAILURE, 0, _("number in %s is too large"), quote (argv[1])); + { + error (EXIT_FAILURE, errno, "%s: %s", _("invalid number"), + quote (argv[1])); + } /* Set globals. */ from_start = t_from_start; @@ -1986,17 +1990,10 @@ parse_options (int argc, char **argv, else if (*optarg == '-') ++optarg; - { - strtol_error s_err; - s_err = xstrtoumax (optarg, NULL, 10, n_units, "bkKmMGTPEZY0"); - if (s_err != LONGINT_OK) - { - error (EXIT_FAILURE, 0, "%s: %s", optarg, - (c == 'n' - ? _("invalid number of lines") - : _("invalid number of bytes"))); - } - } + *n_units = xdectoumax (optarg, 0, UINTMAX_MAX, "bkKmMGTPEZY0", + count_lines + ? _("invalid number of lines") + : _("invalid number of bytes"), 0); break; case 'f': @@ -2015,15 +2012,9 @@ parse_options (int argc, char **argv, case MAX_UNCHANGED_STATS_OPTION: /* --max-unchanged-stats=N */ - if (xstrtoumax (optarg, NULL, 10, - &max_n_unchanged_stats_between_opens, - "") - != LONGINT_OK) - { - error (EXIT_FAILURE, 0, - _("%s: invalid maximum number of unchanged stats between opens"), - optarg); - } + max_n_unchanged_stats_between_opens = + xdectoumax (optarg, 0, UINTMAX_MAX, "", + _("invalid maximum number of unchanged stats between opens"), 0); break; case DISABLE_INOTIFY_OPTION: @@ -2031,16 +2022,7 @@ parse_options (int argc, char **argv, break; case PID_OPTION: - { - strtol_error s_err; - unsigned long int tmp_ulong; - s_err = xstrtoul (optarg, NULL, 10, &tmp_ulong, ""); - if (s_err != LONGINT_OK || tmp_ulong > PID_T_MAX) - { - error (EXIT_FAILURE, 0, _("%s: invalid PID"), optarg); - } - pid = tmp_ulong; - } + pid = xdectoumax (optarg, 0, PID_T_MAX, "", _("invalid PID"), 0); break; case PRESUME_INPUT_PIPE_OPTION: @@ -2056,7 +2038,7 @@ parse_options (int argc, char **argv, double s; if (! (xstrtod (optarg, NULL, &s, c_strtod) && 0 <= s)) error (EXIT_FAILURE, 0, - _("%s: invalid number of seconds"), optarg); + _("invalid number of seconds: %s"), quote (optarg)); *sleep_interval = s; } break; diff --git a/src/truncate.c b/src/truncate.c index f06668de5..e4ef5e733 100644 --- a/src/truncate.c +++ b/src/truncate.c @@ -29,7 +29,7 @@ #include "error.h" #include "quote.h" #include "stat-size.h" -#include "xstrtol.h" +#include "xdectoint.h" /* The official name of this program (e.g., no 'g' prefix). */ #define PROGRAM_NAME "truncate" @@ -59,33 +59,6 @@ static struct option const longopts[] = typedef enum { rm_abs = 0, rm_rel, rm_min, rm_max, rm_rdn, rm_rup } rel_mode_t; -/* Set size to the value of STR, interpreted as a decimal integer, - optionally multiplied by various values. - Return -1 on error, 0 on success. - - This supports dd BLOCK size suffixes + lowercase g,t,m for bsd compat - Note we don't support dd's b=512, c=1, w=2 or 21x512MiB formats. */ -static int -parse_len (char const *str, off_t *size) -{ - enum strtol_error e; - intmax_t tmp_size; - e = xstrtoimax (str, NULL, 10, &tmp_size, "EgGkKmMPtTYZ0"); - if (e == LONGINT_OK - && !(OFF_T_MIN <= tmp_size && tmp_size <= OFF_T_MAX)) - e = LONGINT_OVERFLOW; - - if (e == LONGINT_OK) - { - errno = 0; - *size = tmp_size; - return 0; - } - - errno = (e == LONGINT_OVERFLOW ? EOVERFLOW : 0); - return -1; -} - void usage (int status) { @@ -306,9 +279,10 @@ main (int argc, char **argv) } rel_mode = rm_rel; } - if (parse_len (optarg, &size) == -1) - error (EXIT_FAILURE, errno, _("invalid number %s"), - quote (optarg)); + /* Support dd BLOCK size suffixes + lowercase g,t,m for bsd compat. + Note we don't support dd's b=512, c=1, w=2 or 21x512MiB formats. */ + size = xdectoimax (optarg, OFF_T_MIN, OFF_T_MAX, "EgGkKmMPtTYZ0", + _("Invalid number"), 0); /* Rounding to multiple of 0 is nonsensical */ if ((rel_mode == rm_rup || rel_mode == rm_rdn) && size == 0) error (EXIT_FAILURE, 0, _("division by zero")); -- cgit v1.2.3-70-g09d2