diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2006-12-13 22:03:54 +0100 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 2006-12-13 22:03:54 +0100 |
commit | ec95137cc376119f634610a7683a296fc7b78ea4 (patch) | |
tree | 52d315f085e18022db44722d7e58f3e4635d84d9 /src | |
parent | ae3ee95eb8372ec5947e3c790c6ea77bc703c160 (diff) | |
download | coreutils-ec95137cc376119f634610a7683a296fc7b78ea4.tar.xz |
Remove some arbitrary restrictions on size fields,
so that commands like "sort -k 18446744073709551616" no longer fail merely
because 18446744073709551616 doesn't fit in uintmax_t. The trick is that
these fields can all be treated as effectively infinity; their exact
values don't matter, since no internal buffer can be that long.
* src/join.c (string_to_join_field): Verify that SIZE_MAX <= ULONG_MAX
if the code assumes this. Silently truncate too-large values to SIZE_MAX,
as the remaining code will do the right thing in this case.
* src/sort.c (parse_field_count): Likewise.
* src/uniq.c (size_opt, main): Likewise.
* tests/join/Test.pm (bigfield): New test.
* tests/sort/Test.pm (bigfield): New test.
* tests/uniq/Test.pm (121): New test.
Signed-off-by: Jim Meyering <jim@meyering.net>
Diffstat (limited to 'src')
-rw-r--r-- | src/join.c | 13 | ||||
-rw-r--r-- | src/sort.c | 9 | ||||
-rw-r--r-- | src/uniq.c | 25 |
3 files changed, 26 insertions, 21 deletions
diff --git a/src/join.c b/src/join.c index 77a389604..b113c543b 100644 --- a/src/join.c +++ b/src/join.c @@ -599,7 +599,8 @@ add_field (int file, size_t field) /* Convert a string of decimal digits, STR (the 1-based join field number), to an integral value. Upon successful conversion, return one less - (the zero-based field number). If it cannot be converted, give a + (the zero-based field number). Silently convert too-large values + to SIZE_MAX - 1. Otherwise, if a value cannot be converted, give a diagnostic and exit. */ static size_t @@ -607,16 +608,12 @@ string_to_join_field (char const *str) { size_t result; unsigned long int val; + verify (SIZE_MAX <= ULONG_MAX); strtol_error s_err = xstrtoul (str, NULL, 10, &val, ""); if (s_err == LONGINT_OVERFLOW || (s_err == LONGINT_OK && SIZE_MAX < val)) - { - error (EXIT_FAILURE, 0, - _("value %s is so large that it is not representable"), - quote (str)); - } - - if (s_err != LONGINT_OK || val == 0) + val = SIZE_MAX; + else if (s_err != LONGINT_OK || val == 0) error (EXIT_FAILURE, 0, _("invalid field number: %s"), quote (str)); result = val - 1; diff --git a/src/sort.c b/src/sort.c index feaf5a5bc..f03237cb3 100644 --- a/src/sort.c +++ b/src/sort.c @@ -2170,7 +2170,8 @@ check_ordering_compatibility (void) /* Parse the leading integer in STRING and store the resulting value (which must fit into size_t) into *VAL. Return the address of the - suffix after the integer. If MSGID is NULL, return NULL after + suffix after the integer. If the value is too large, silently + substitute SIZE_MAX. If MSGID is NULL, return NULL after failure; otherwise, report MSGID and exit on failure. */ static char const * @@ -2189,10 +2190,8 @@ parse_field_count (char const *string, size_t *val, char const *msgid) /* Fall through. */ case LONGINT_OVERFLOW: case LONGINT_OVERFLOW | LONGINT_INVALID_SUFFIX_CHAR: - if (msgid) - error (SORT_FAILURE, 0, _("%s: count `%.*s' too large"), - _(msgid), (int) (suffix - string), string); - return NULL; + *val = SIZE_MAX; + break; case LONGINT_INVALID: if (msgid) diff --git a/src/uniq.c b/src/uniq.c index 0d60961f6..6c38ed807 100644 --- a/src/uniq.c +++ b/src/uniq.c @@ -172,17 +172,26 @@ Fields are skipped before chars.\n\ exit (status); } -/* Convert OPT to size_t, reporting an error using MSGID if it does - not fit. */ +/* Convert OPT to size_t, reporting an error using MSGID if OPT is + invalid. Silently convert too-large values to SIZE_MAX. */ static size_t size_opt (char const *opt, char const *msgid) { unsigned long int size; - if (xstrtoul (opt, NULL, 10, &size, "") != LONGINT_OK - || SIZE_MAX < size) - error (EXIT_FAILURE, 0, "%s: %s", opt, _(msgid)); - return size; + verify (SIZE_MAX <= ULONG_MAX); + + switch (xstrtoul (opt, NULL, 10, &size, "")) + { + case LONGINT_OK: + case LONGINT_OVERFLOW: + break; + + default: + error (EXIT_FAILURE, 0, "%s: %s", opt, _(msgid)); + } + + return MIN (size, SIZE_MAX); } /* Given a linebuffer LINE, @@ -472,8 +481,8 @@ main (int argc, char **argv) skip_fields = 0; if (!DECIMAL_DIGIT_ACCUMULATE (skip_fields, optc - '0', size_t)) - error (EXIT_FAILURE, 0, "%s", - _("invalid number of fields to skip")); + skip_fields = SIZE_MAX; + skip_field_option_type = SFO_OBSOLETE; } break; |