From d183ecddcd77fe02ed158ee6470ff4a8192ed763 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Sun, 3 Dec 2000 10:18:04 +0000 Subject: Make od print valid addresses for offsets of 2^32 and larger. (cont'd) (MAX_ADDRESS_LENGTH): Don't hard-code as a literal. Rather, define in terms of the type, off_t. (string_min): Declare to be of type size_t. (flag_dump_strings): Declare to be of type int. (print_s_char): Declare the n_bytes parameter and the local, `i', to be of type off_t. (print_char): Likewise. (print_s_short): Likewise. (print_short): Likewise. (print_int): Likewise. (print_long): Likewise. (print_long_long): Likewise. (print_float): Likewise. (print_double): Likewise. (print_long_double): Likewise. (dump_hexl_mode_trailer): Likewise. (print_named_ascii): Likewise. (print_ascii): Likewise. (write_block): Likewise. (print_ascii): Declare local, `print_function' with a prototype. Change a few `>' comparisons to the equivalent `<' form. (parse_options): Declare `tmp' to be of type uintmax_t. Use xstrtoumax, not xstrtoul. Fail if the specified offset if larger than OFF_T_MAX. (dump_strings): Declare local `i' to be of type size_t. Remove the now-unnecessary cast-to-off_t. (main) [IF_LINT]: Initialize desired_width to avoid a warning. Declare `tmp' to be of type uintmax_t. Use xstrtoumax, not xstrtoul. Fail if minimum string length is larger than SIZE_MAX. Fail if specified width is larger than ULONG_MAX. --- src/od.c | 130 ++++++++++++++++++++++++++++++++------------------------------- 1 file changed, 66 insertions(+), 64 deletions(-) (limited to 'src') diff --git a/src/od.c b/src/od.c index 7f7cec67d..26afa8128 100644 --- a/src/od.c +++ b/src/od.c @@ -153,16 +153,17 @@ static const char *const charname[33] = /* A printf control string for printing a file offset. */ static const char *output_address_fmt_string; -/* FIXME: make this the number of octal digits in an unsigned long. */ -#define MAX_ADDRESS_LENGTH 13 +/* The number of octal digits required to represent the largest off_t value. */ +#define MAX_ADDRESS_LENGTH \ + ((sizeof (off_t) * BITSPERBYTE + BITSPERBYTE - 1) / 3) /* Space for a normal address, a space, a pseudo address, parentheses around the pseudo address, and a trailing zero byte. */ static char address_fmt_buffer[2 * MAX_ADDRESS_LENGTH + 4]; static char address_pad[MAX_ADDRESS_LENGTH + 1]; -static unsigned long int string_min; -static unsigned long int flag_dump_strings; +static size_t string_min; +static int flag_dump_strings; /* Non-zero if we should recognize the pre-POSIX non-option arguments that specified at most one file and optional arguments specifying @@ -359,10 +360,9 @@ lcm (unsigned int u, unsigned int v) } static void -print_s_char (long unsigned int n_bytes, const char *block, - const char *fmt_string) +print_s_char (off_t n_bytes, const char *block, const char *fmt_string) { - int i; + off_t i; for (i = n_bytes; i > 0; i--) { int tmp = (unsigned) *(const unsigned char *) block; @@ -375,10 +375,9 @@ print_s_char (long unsigned int n_bytes, const char *block, } static void -print_char (long unsigned int n_bytes, const char *block, - const char *fmt_string) +print_char (off_t n_bytes, const char *block, const char *fmt_string) { - int i; + off_t i; for (i = n_bytes; i > 0; i--) { unsigned int tmp = *(const unsigned char *) block; @@ -388,10 +387,9 @@ print_char (long unsigned int n_bytes, const char *block, } static void -print_s_short (long unsigned int n_bytes, const char *block, - const char *fmt_string) +print_s_short (off_t n_bytes, const char *block, const char *fmt_string) { - int i; + off_t i; for (i = n_bytes / sizeof (unsigned short); i > 0; i--) { int tmp = (unsigned) *(const unsigned short *) block; @@ -404,10 +402,9 @@ print_s_short (long unsigned int n_bytes, const char *block, } static void -print_short (long unsigned int n_bytes, const char *block, - const char *fmt_string) +print_short (off_t n_bytes, const char *block, const char *fmt_string) { - int i; + off_t i; for (i = n_bytes / sizeof (unsigned short); i > 0; i--) { unsigned int tmp = *(const unsigned short *) block; @@ -417,10 +414,9 @@ print_short (long unsigned int n_bytes, const char *block, } static void -print_int (long unsigned int n_bytes, const char *block, - const char *fmt_string) +print_int (off_t n_bytes, const char *block, const char *fmt_string) { - int i; + off_t i; for (i = n_bytes / sizeof (unsigned int); i > 0; i--) { unsigned int tmp = *(const unsigned int *) block; @@ -430,10 +426,9 @@ print_int (long unsigned int n_bytes, const char *block, } static void -print_long (long unsigned int n_bytes, const char *block, - const char *fmt_string) +print_long (off_t n_bytes, const char *block, const char *fmt_string) { - int i; + off_t i; for (i = n_bytes / sizeof (unsigned long); i > 0; i--) { unsigned long tmp = *(const unsigned long *) block; @@ -444,10 +439,9 @@ print_long (long unsigned int n_bytes, const char *block, #ifdef HAVE_UNSIGNED_LONG_LONG static void -print_long_long (long unsigned int n_bytes, const char *block, - const char *fmt_string) +print_long_long (off_t n_bytes, const char *block, const char *fmt_string) { - int i; + off_t i; for (i = n_bytes / sizeof (unsigned long long); i > 0; i--) { unsigned long long tmp = *(const unsigned long long *) block; @@ -458,10 +452,9 @@ print_long_long (long unsigned int n_bytes, const char *block, #endif static void -print_float (long unsigned int n_bytes, const char *block, - const char *fmt_string) +print_float (off_t n_bytes, const char *block, const char *fmt_string) { - int i; + off_t i; for (i = n_bytes / sizeof (float); i > 0; i--) { float tmp = *(const float *) block; @@ -471,10 +464,9 @@ print_float (long unsigned int n_bytes, const char *block, } static void -print_double (long unsigned int n_bytes, const char *block, - const char *fmt_string) +print_double (off_t n_bytes, const char *block, const char *fmt_string) { - int i; + off_t i; for (i = n_bytes / sizeof (double); i > 0; i--) { double tmp = *(const double *) block; @@ -485,10 +477,9 @@ print_double (long unsigned int n_bytes, const char *block, #ifdef HAVE_LONG_DOUBLE static void -print_long_double (long unsigned int n_bytes, const char *block, - const char *fmt_string) +print_long_double (off_t n_bytes, const char *block, const char *fmt_string) { - int i; + off_t i; for (i = n_bytes / sizeof (LONG_DOUBLE); i > 0; i--) { LONG_DOUBLE tmp = *(const LONG_DOUBLE *) block; @@ -500,9 +491,9 @@ print_long_double (long unsigned int n_bytes, const char *block, #endif static void -dump_hexl_mode_trailer (long unsigned int n_bytes, const char *block) +dump_hexl_mode_trailer (off_t n_bytes, const char *block) { - int i; + off_t i; fputs (" >", stdout); for (i = n_bytes; i > 0; i--) { @@ -515,10 +506,10 @@ dump_hexl_mode_trailer (long unsigned int n_bytes, const char *block) } static void -print_named_ascii (long unsigned int n_bytes, const char *block, +print_named_ascii (off_t n_bytes, const char *block, const char *unused_fmt_string ATTRIBUTE_UNUSED) { - int i; + off_t i; for (i = n_bytes; i > 0; i--) { unsigned int c = *(const unsigned char *) block; @@ -542,10 +533,10 @@ print_named_ascii (long unsigned int n_bytes, const char *block, } static void -print_ascii (long unsigned int n_bytes, const char *block, +print_ascii (off_t n_bytes, const char *block, const char *unused_fmt_string ATTRIBUTE_UNUSED) { - int i; + off_t i; for (i = n_bytes; i > 0; i--) { unsigned int c = *(const unsigned char *) block; @@ -647,7 +638,7 @@ decode_one_format (const char *s_orig, const char *s, const char **next, enum output_format fmt; const char *pre_fmt_string; char *fmt_string; - void (*print_function) (); + void (*print_function) PARAMS ((off_t, const char *, const char *)); const char *p; unsigned int c; unsigned int field_width = 0; @@ -697,7 +688,7 @@ decode_one_format (const char *s_orig, const char *s, const char **next, size = sizeof (int); else { - if (size > MAX_INTEGRAL_TYPE_SIZE + if (MAX_INTEGRAL_TYPE_SIZE < size || integral_type_size[size] == NO_SIZE) { error (0, 0, _("invalid type string `%s';\n\ @@ -1005,7 +996,7 @@ skip (off_t n_skip) n_skip and go on to the next file. */ if (S_ISREG (file_stats.st_mode)) { - if (n_skip >= file_stats.st_size) + if (file_stats.st_size <= n_skip) { n_skip -= file_stats.st_size; if (in_stream != stdin && fclose (in_stream) == EOF) @@ -1028,10 +1019,10 @@ skip (off_t n_skip) /* Seek didn't work or wasn't attempted; position the file pointer by reading. */ - for (j = n_skip / BUFSIZ; j >= 0; j--) + for (j = n_skip / BUFSIZ; 0 <= j; j--) { char buf[BUFSIZ]; - size_t n_bytes_to_read = (j > 0 + size_t n_bytes_to_read = (0 < j ? BUFSIZ : n_skip % BUFSIZ); size_t n_bytes_read; @@ -1091,7 +1082,7 @@ format_address_label (off_t address) only when it has not been padded to length BYTES_PER_BLOCK. */ static void -write_block (off_t current_offset, long unsigned int n_bytes, +write_block (off_t current_offset, off_t n_bytes, const char *prev_block, const char *curr_block) { static int first = 1; @@ -1256,7 +1247,7 @@ read_block (size_t n, char *block, size_t *n_bytes_in_buffer) { int err; - assert (n > 0 && n <= bytes_per_block); + assert (0 < n && n <= bytes_per_block); *n_bytes_in_buffer = 0; @@ -1333,7 +1324,7 @@ parse_old_offset (const char *s) int radix; off_t offset; enum strtol_error s_err; - long unsigned int tmp; + uintmax_t tmp; if (*s == '\0') return -1; @@ -1355,12 +1346,15 @@ parse_old_offset (const char *s) radix = 8; } - s_err = xstrtoul (s, NULL, radix, &tmp, "Bb"); + s_err = xstrtoumax (s, NULL, radix, &tmp, "Bb"); if (s_err != LONGINT_OK) { STRTOL_FAIL_WARN (s, _("old-style offset"), s_err); return -1; } + if (OFF_T_MAX < tmp) + error (EXIT_FAILURE, 0, + _("%s is larger than the maximum file size on this system"), s); offset = tmp; return offset; } @@ -1477,15 +1471,14 @@ dump_strings (void) err = 0; while (1) { - unsigned int i; + size_t i; int c; /* See if the next `string_min' chars are all printing chars. */ tryline: if (limit_bytes_to_format - && address >= (n_bytes_to_skip + max_bytes_to_format - - (off_t) string_min)) + && address >= (n_bytes_to_skip + max_bytes_to_format - string_min)) break; for (i = 0; i < string_min; i++) @@ -1610,7 +1603,7 @@ main (int argc, char **argv) unsigned int i; unsigned int l_c_m; unsigned int address_pad_len; - unsigned long int desired_width; + unsigned long int desired_width IF_LINT (= 0); int width_specified = 0; int n_failed_decodes = 0; int err; @@ -1661,7 +1654,7 @@ main (int argc, char **argv) while ((c = getopt_long (argc, argv, "abcdfhilos::xw::A:j:N:t:v", long_options, NULL)) != -1) { - unsigned long int tmp; + uintmax_t tmp; enum strtol_error s_err; switch (c) @@ -1702,7 +1695,7 @@ it must be one character from [doxn]"), break; case 'j': - s_err = xstrtoul (optarg, NULL, 0, &tmp, "bkm"); + s_err = xstrtoumax (optarg, NULL, 0, &tmp, "bkm"); n_bytes_to_skip = tmp; if (s_err != LONGINT_OK) STRTOL_FATAL_ERROR (optarg, _("skip argument"), s_err); @@ -1711,17 +1704,15 @@ it must be one character from [doxn]"), case 'N': limit_bytes_to_format = 1; - /* FIXME: if off_t is long long and that's an 8-byte type, - use xstrtouq here. */ - s_err = xstrtoul (optarg, NULL, 0, &tmp, "bkm"); + s_err = xstrtoumax (optarg, NULL, 0, &tmp, "bkm"); max_bytes_to_format = tmp; if (s_err != LONGINT_OK) STRTOL_FATAL_ERROR (optarg, _("limit argument"), s_err); - if (tmp > LONG_MAX) + if (OFF_T_MAX < tmp) error (EXIT_FAILURE, 0, - _("specified number of bytes `%s' is larger than \ -the maximum\nrepresentable value of type `long'"), optarg); + _("%s is larger than the maximum file size on this system"), + optarg); break; case 's': @@ -1729,11 +1720,18 @@ the maximum\nrepresentable value of type `long'"), optarg); string_min = 3; else { - s_err = xstrtoul (optarg, NULL, 0, &string_min, "bkm"); + s_err = xstrtoumax (optarg, NULL, 0, &tmp, "bkm"); if (s_err != LONGINT_OK) STRTOL_FATAL_ERROR (optarg, _("minimum string length"), s_err); + + /* The minimum string length may be no larger than SIZE_MAX, + since we may allocate a buffer of this size. */ + if (SIZE_MAX < tmp) + error (EXIT_FAILURE, 0, _("%s is too large"), optarg); + + string_min = tmp; } - ++flag_dump_strings; + flag_dump_strings = 1; break; case 't': @@ -1783,9 +1781,13 @@ the maximum\nrepresentable value of type `long'"), optarg); } else { - s_err = xstrtoul (optarg, NULL, 10, &desired_width, ""); + uintmax_t w_tmp; + s_err = xstrtoumax (optarg, NULL, 10, &w_tmp, ""); if (s_err != LONGINT_OK) STRTOL_FATAL_ERROR (optarg, _("width specification"), s_err); + if (ULONG_MAX < w_tmp) + error (EXIT_FAILURE, 0, _("%s is too large"), optarg); + desired_width = w_tmp; } break; -- cgit v1.2.3-54-g00ecf