summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2016-06-23 20:16:45 +0200
committerPaul Eggert <eggert@cs.ucla.edu>2016-06-23 20:18:03 +0200
commit818b2f48974298065a43a8a2d5355e4aaa65c09d (patch)
treec33bf70c1f67871a54e954b0bf3cd0c776babaae
parenta3311c966e34f2d9f8aa6b1de31b211124803d02 (diff)
downloadcoreutils-818b2f48974298065a43a8a2d5355e4aaa65c09d.tar.xz
maint: work even if argc == INT_MAX
GCC 7 warned about undefined behavior in this unlikely case. Problem reported by Jim Meyering in: http://bugs.gnu.org/23825 * src/md5sum.c (main): * src/paste.c (main): * src/yes.c (main): Avoid undefined behavior when argc == INT_MAX.
-rw-r--r--src/md5sum.c7
-rw-r--r--src/paste.c15
-rw-r--r--src/yes.c45
3 files changed, 32 insertions, 35 deletions
diff --git a/src/md5sum.c b/src/md5sum.c
index 39132e340..3ed1b65e7 100644
--- a/src/md5sum.c
+++ b/src/md5sum.c
@@ -864,12 +864,13 @@ main (int argc, char **argv)
if (!O_BINARY && binary < 0)
binary = 0;
+ char **operand_lim = argv + argc;
if (optind == argc)
- argv[argc++] = bad_cast ("-");
+ *operand_lim++ = bad_cast ("-");
- for (; optind < argc; ++optind)
+ for (char **operandp = argv + optind; operandp < operand_lim; operandp++)
{
- char *file = argv[optind];
+ char *file = *operandp;
if (do_check)
ok &= digest_check (file);
diff --git a/src/paste.c b/src/paste.c
index bf99fe028..7914aef12 100644
--- a/src/paste.c
+++ b/src/paste.c
@@ -465,7 +465,6 @@ int
main (int argc, char **argv)
{
int optc;
- bool ok;
char const *delim_arg = "\t";
initialize_main (&argc, &argv);
@@ -505,8 +504,12 @@ main (int argc, char **argv)
}
}
- if (optind == argc)
- argv[argc++] = bad_cast ("-");
+ int nfiles = argc - optind;
+ if (nfiles == 0)
+ {
+ argv[optind] = bad_cast ("-");
+ nfiles++;
+ }
if (collapse_escapes (delim_arg))
{
@@ -517,10 +520,8 @@ main (int argc, char **argv)
quotearg_n_style_colon (0, c_maybe_quoting_style, delim_arg));
}
- if (!serial_merge)
- ok = paste_parallel (argc - optind, &argv[optind]);
- else
- ok = paste_serial (argc - optind, &argv[optind]);
+ bool ok = ((serial_merge ? paste_serial : paste_parallel)
+ (nfiles, &argv[optind]));
free (delims);
diff --git a/src/yes.c b/src/yes.c
index 1d2c612c9..e127310f1 100644
--- a/src/yes.c
+++ b/src/yes.c
@@ -60,7 +60,6 @@ main (int argc, char **argv)
{
char buf[BUFSIZ];
char *pbuf = buf;
- int i;
initialize_main (&argc, &argv);
set_program_name (argv[0]);
@@ -75,24 +74,25 @@ main (int argc, char **argv)
if (getopt_long (argc, argv, "+", NULL, NULL) != -1)
usage (EXIT_FAILURE);
- if (argc <= optind)
- {
- optind = argc;
- argv[argc++] = bad_cast ("y");
- }
+ char **operand_lim = argv + argc;
+ if (optind == argc)
+ *operand_lim++ = bad_cast ("-");
/* Buffer data locally once, rather than having the
large overhead of stdio buffering each item. */
- for (i = optind; i < argc; i++)
+ char **operandp;
+ for (operandp = argv + optind; operandp < operand_lim; operandp++)
{
- size_t len = strlen (argv[i]);
+ size_t len = strlen (*operandp);
if (BUFSIZ < len || BUFSIZ - len <= pbuf - buf)
break;
- memcpy (pbuf, argv[i], len);
+ memcpy (pbuf, *operandp, len);
pbuf += len;
- *pbuf++ = i == argc - 1 ? '\n' : ' ';
+ *pbuf++ = operandp + 1 == operand_lim ? '\n' : ' ';
}
- if (i == argc)
+
+ /* The normal case is to continuously output the local buffer. */
+ if (operandp == operand_lim)
{
size_t line_len = pbuf - buf;
size_t lines = BUFSIZ / line_len;
@@ -101,32 +101,27 @@ main (int argc, char **argv)
memcpy (pbuf, pbuf - line_len, line_len);
pbuf += line_len;
}
- }
- /* The normal case is to continuously output the local buffer. */
- while (i == argc)
- {
- if (write (STDOUT_FILENO, buf, pbuf - buf) == -1)
- {
- error (0, errno, _("standard output"));
- return EXIT_FAILURE;
- }
+ while (0 <= write (STDOUT_FILENO, buf, pbuf - buf))
+ continue;
+
+ error (0, errno, _("standard output"));
+ return EXIT_FAILURE;
}
/* If the data doesn't fit in BUFSIZ then output
what we've buffered, and iterate over the remaining items. */
- while (true /* i != argc */)
+ while (true)
{
- int j;
if ((pbuf - buf) && fwrite (buf, pbuf - buf, 1, stdout) != 1)
{
error (0, errno, _("standard output"));
clearerr (stdout);
return EXIT_FAILURE;
}
- for (j = i; j < argc; j++)
- if (fputs (argv[j], stdout) == EOF
- || putchar (j == argc - 1 ? '\n' : ' ') == EOF)
+ for (char **trailing = operandp; trailing < operand_lim; trailing++)
+ if (fputs (*trailing, stdout) == EOF
+ || putchar (trailing + 1 == operand_lim ? '\n' : ' ') == EOF)
{
error (0, errno, _("standard output"));
clearerr (stdout);