]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
comm: don't close standard input twice
authorCollin Funk <collin.funk1@gmail.com>
Wed, 22 Apr 2026 03:10:55 +0000 (20:10 -0700)
committerCollin Funk <collin.funk1@gmail.com>
Thu, 23 Apr 2026 02:12:44 +0000 (19:12 -0700)
* NEWS: Mention the bug fix.
* src/comm.c (usage): Remove mention that FILE1 and FILE2 cannot both be
standard input.
(compare_files): Only close standard input once.
* doc/coreutils.texi (comm invocation): Document the behavior of
'comm - -' which is not portable to all implementations.
* tests/comm/dash-dash.sh: New file.
* tests/misc/comm.pl: Move to tests/comm/comm.pl.
* tests/local.mk (all_tests): Add the new test. Rename the existing
test.

NEWS
doc/coreutils.texi
src/comm.c
tests/comm/comm.pl [moved from tests/misc/comm.pl with 100% similarity]
tests/comm/dash-dash.sh [new file with mode: 0755]
tests/local.mk

diff --git a/NEWS b/NEWS
index 038a1b520a1f0f058a231d85600c188b3afa269b..a827cf0d98d42915a9ab6c88e2191450a79c7423 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,12 @@ GNU coreutils NEWS                                    -*- outline -*-
 
 * Noteworthy changes in release ?.? (????-??-??) [?]
 
+** Bug fixes
+
+  'comm - -' no longer closes standard input twice.  Previously it would
+  mistakenly exit with a nonzero status.
+  [This bug was present in "the beginning".]
+
 
 * Noteworthy changes in release 9.11 (2026-04-20) [stable]
 
index 0f9d3e276a454b5ba7c7fca0a60cf9371655ca76..26d405b0b59575deb6d899d32ecf544598120b2d 100644 (file)
@@ -5502,6 +5502,12 @@ $ comm -12 file1 file2 | wc -l    # number of lines common to both files
 
 @end table
 
+POSIX leaves the behavior undefined when @var{file1} and @var{file2}
+both refer to standard input, i.e., when both are @samp{-}.  GNU
+@command{comm} reads the first line as if it came from @var{file1} and
+the second as if it were from @var{file2}, and continues alternating in
+this manner until the end of file is reached.
+
 @node ptx invocation
 @section @command{ptx}: Produce permuted indexes
 
index 8e671f40ddeaa800e5cb1fa0e5ef77890a09b983..b2ceca382f9c2e4002ca9c04d3bbd454bb611189 100644 (file)
@@ -112,7 +112,7 @@ Compare sorted files FILE1 and FILE2 line by line.\n\
 "), stdout);
       fputs (_("\
 \n\
-When FILE1 or FILE2 (not both) is -, read standard input.\n\
+When FILE1 or FILE2 is -, read standard input.\n\
 "), stdout);
       fputs (_("\
 \n\
@@ -388,7 +388,9 @@ compare_files (char **infiles)
           }
     }
 
-  for (int i = 0; i < 2; i++)
+  /* Avoid closing standard input twice when invoking 'comm - -'.  */
+  const int n_streams = 2 - (streams[0] == streams[1]);
+  for (int i = 0; i < n_streams; i++)
     if (fclose (streams[i]) != 0)
       error (EXIT_FAILURE, errno, "%s", quotef (infiles[i]));
 
similarity index 100%
rename from tests/misc/comm.pl
rename to tests/comm/comm.pl
diff --git a/tests/comm/dash-dash.sh b/tests/comm/dash-dash.sh
new file mode 100755 (executable)
index 0000000..9d7dc6a
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/sh
+# Test that 'comm - -' works.
+
+# Copyright (C) 2026 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ comm
+
+printf '1\n\t2\n\t\t3\n4\n\t5\n\t\t6\n7\n\t8\n\t\t9\n' >exp \
+  || framework_failure_
+
+# In coreutils 9.11 and earlier, running 'comm - -' would close
+# standard input twice, leading to an incorrect exit status.
+seq 9 | sed 'n;n;p' | timeout 10 comm - - >out 2>err || fail=1
+compare exp out || fail=1
+compare /dev/null err || fail=1
+
+Exit $fail
index 628e54436d5384914d092dc706c0f5f264a4bd01..fde3ea98925866de44be5b04ce6fa84ce16390c5 100644 (file)
@@ -324,7 +324,8 @@ all_tests =                                 \
   tests/cksum/cksum-base64.pl                  \
   tests/cksum/cksum-base64-untagged.sh         \
   tests/cksum/cksum-raw.sh                     \
-  tests/misc/comm.pl                           \
+  tests/comm/comm.pl                           \
+  tests/comm/dash-dash.sh                      \
   tests/csplit/csplit.sh                       \
   tests/csplit/csplit-1000.sh                  \
   tests/csplit/csplit-heap.sh                  \