>From 601eceb57cfb87ded594701acc401277c53ff837 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sat, 5 Jan 2019 19:55:08 -0800 Subject: [PATCH 3/3] diff: fix cmp, diff3, sdiff with stdin closed * NEWS: Mention this. * src/cmp.c, src/diff3.c, src/sdiff.c: Include stdopen.h. (main): Call stdopen early. * src/cmp.c (main): Simplify now that we need not worry about stdin being closed. * src/diff.c (main): Translate stdopen diagnostic. --- NEWS | 8 ++++++++ src/cmp.c | 28 ++++++++++++++-------------- src/diff.c | 2 +- src/diff3.c | 4 ++++ src/sdiff.c | 4 ++++ 5 files changed, 31 insertions(+), 15 deletions(-) diff --git a/NEWS b/NEWS index af675da..9ab0748 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,14 @@ GNU diffutils NEWS -*- outline -*- transition, or HP-UX even if not setuid. [bug#33965 introduced in 2.8] +** Bug fixes + + diff and related programs no longer get confused if stdin, stdout, + or stderr are closed. Previously, they sometimes opened files into + file descriptors 0, 1, or 2 and then mistakenly did I/O with them + that was intended for stdin, stdout, or stderr. + [bug#33965 present since "the beginning"] + * Noteworthy changes in release 3.7 (2018-12-31) [stable] diff --git a/src/cmp.c b/src/cmp.c index 53ff210..7bad6dd 100644 --- a/src/cmp.c +++ b/src/cmp.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -199,7 +200,7 @@ GB 1,000,000,000, G 1,073,741,824, and so on for T, P, E, Z, Y."), int main (int argc, char **argv) { - int c, f, exit_status; + int c, exit_status; size_t words_per_buffer; exit_failure = EXIT_TROUBLE; @@ -209,6 +210,9 @@ main (int argc, char **argv) bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); c_stack_action (0); + int stdopen_errno = stdopen (); + if (stdopen_errno != 0) + error (EXIT_TROUBLE, stdopen_errno, _("standard file descriptors")); /* Parse command line options. */ @@ -268,7 +272,7 @@ main (int argc, char **argv) file[0] = argv[optind++]; file[1] = optind < argc ? argv[optind++] : "-"; - for (f = 0; f < 2 && optind < argc; f++) + for (int f = 0; f < 2 && optind < argc; f++) { char *arg = argv[optind++]; specify_ignore_initial (f, &arg, 0); @@ -277,33 +281,29 @@ main (int argc, char **argv) if (optind < argc) try_help ("extra operand '%s'", argv[optind]); - for (f = 0; f < 2; f++) + for (int f = 0; f < 2; f++) { - /* If file[1] is "-", treat it first; this avoids a misdiagnostic if - stdin is closed and opening file[0] yields file descriptor 0. */ - int f1 = f ^ (STREQ (file[1], "-")); - /* Two files with the same name and offset are identical. But wait until we open the file once, for proper diagnostics. */ if (f && ignore_initial[0] == ignore_initial[1] && file_name_cmp (file[0], file[1]) == 0) return EXIT_SUCCESS; - if (STREQ (file[f1], "-")) + if (STREQ (file[f], "-")) { - file_desc[f1] = STDIN_FILENO; + file_desc[f] = STDIN_FILENO; if (O_BINARY && ! isatty (STDIN_FILENO)) set_binary_mode (STDIN_FILENO, O_BINARY); } else - file_desc[f1] = open (file[f1], O_RDONLY | O_BINARY, 0); + file_desc[f] = open (file[f], O_RDONLY | O_BINARY, 0); - if (file_desc[f1] < 0 || fstat (file_desc[f1], stat_buf + f1) != 0) + if (file_desc[f] < 0 || fstat (file_desc[f], stat_buf + f) != 0) { - if (file_desc[f1] < 0 && comparison_type == type_status) + if (file_desc[f] < 0 && comparison_type == type_status) exit (EXIT_TROUBLE); else - die (EXIT_TROUBLE, errno, "%s", file[f1]); + die (EXIT_TROUBLE, errno, "%s", file[f]); } } @@ -361,7 +361,7 @@ main (int argc, char **argv) exit_status = cmp (); - for (f = 0; f < 2; f++) + for (int f = 0; f < 2; f++) if (close (file_desc[f]) != 0) die (EXIT_TROUBLE, errno, "%s", file[f]); if (exit_status != EXIT_SUCCESS && comparison_type < type_no_stdout) diff --git a/src/diff.c b/src/diff.c index a5ec7f4..d54782c 100644 --- a/src/diff.c +++ b/src/diff.c @@ -300,7 +300,7 @@ main (int argc, char **argv) presume_output_tty = false; int stdopen_errno = stdopen (); if (stdopen_errno != 0) - error (EXIT_TROUBLE, stdopen_errno, "standard file descriptors"); + error (EXIT_TROUBLE, stdopen_errno, _("standard file descriptors")); /* Decode the options. */ diff --git a/src/diff3.c b/src/diff3.c index c7b2840..36bf4a6 100644 --- a/src/diff3.c +++ b/src/diff3.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -272,6 +273,9 @@ main (int argc, char **argv) bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); c_stack_action (0); + int stdopen_errno = stdopen (); + if (stdopen_errno != 0) + error (EXIT_TROUBLE, stdopen_errno, _("standard file descriptors")); while ((c = getopt_long (argc, argv, "aeimvx3AEL:TX", longopts, 0)) != -1) { diff --git a/src/sdiff.c b/src/sdiff.c index 25ce3fe..bbbe16c 100644 --- a/src/sdiff.c +++ b/src/sdiff.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -455,6 +456,9 @@ main (int argc, char *argv[]) bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); c_stack_action (cleanup); + int stdopen_errno = stdopen (); + if (stdopen_errno != 0) + error (EXIT_TROUBLE, stdopen_errno, _("standard file descriptors")); prog = getenv ("EDITOR"); if (prog) -- 2.17.1