Hey Bruno,

It seems we forgot about this behavior when moving to posix_spawn. In
the find_in_given_path function, there are the following lines:

    if (path == NULL)
      /* If PATH is not set, the default search path is implementation 
dependent.
         In practice, it is treated like an empty PATH.  */
      path = "";

That isn't true on GNU/Linux, FreeBSD, and Solaris at least, where an
unset PATH searches the default path specified by
pathconf (_CS_PATH, ...) and an empty PATH searches the current working
directory. Perhaps the default to _CS_PATH I put here is better placed
in the Gnulib function? It has been in POSIX for a long time [1].

[1] https://pubs.opengroup.org/onlinepubs/9799919799/functions/confstr.html

-- 8< --

* src/sort.c (get_resolved_compress_program): When PATH is not defined
in the environment, look up the compress program in "/bin:/usr/bin" or
the default search path specified by confstr (_CS_PATH, ...), if
supported.
* tests/sort/sort-compress.sh: Add a test case.
* NEWS: Mention the bug fix.

Discovered by Anthropic's OSS Scanner, as bug ANT-2026-1R7RAVAG.
---
 NEWS                        |  7 +++++++
 src/sort.c                  | 27 ++++++++++++++++++++++++++-
 tests/sort/sort-compress.sh | 16 +++++++++++++++-
 3 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/NEWS b/NEWS
index 7071d6878..cf4566029 100644
--- a/NEWS
+++ b/NEWS
@@ -124,6 +124,13 @@ GNU coreutils NEWS                                    -*- 
outline -*-
   resolves to a path beginning with the symbolic link itself.
   [bug introduced in coreutils-9.0]
 
+  'sort --compress-program=PROG' no longer treats an unset PATH environment
+  variable as equivalent to a PATH environment variable defined to an empty
+  string.  On typical platforms, that would result in PROG being executed from
+  the current working directory, if it existed, when PATH was not defined in 
the
+  environment.
+  [bug introduced in coreutils-9.9]
+
   'stty' again rejects empty speed arguments.
   Previously such arguments were accepted as value 0.
   [bug introduced in coreutils-9.8]
diff --git a/src/sort.c b/src/sort.c
index 962588c34..47862e95c 100644
--- a/src/sort.c
+++ b/src/sort.c
@@ -1114,9 +1114,34 @@ get_resolved_compress_program (void)
 
   if (resolved_compress_program_cache == NULL)
     {
+      char const *path = getenv ("PATH");
+      char *default_path = NULL;
+
+      /* The find_in_given_path function treats an unset PATH as the same
+         as an empty PATH.  On typical platforms, that means executing a
+         program from the current working directory.  Instead, we want
+         the behavior of execlp, which will default to
+         confstr (_CS_PATH, ...).  */
+      if (! path)
+        {
+          path = "/bin:/usr/bin";
+
+#ifdef _CS_PATH
+          size_t const len = confstr (_CS_PATH, NULL, 0);
+
+          if (len)
+            {
+              default_path = malloc (len);
+              if (default_path && confstr (_CS_PATH, default_path, len) == len)
+                path = default_path;
+            }
+#endif
+        }
+
       resolved_compress_program_cache =
-        find_in_given_path (compress_program, getenv ("PATH"), NULL, false);
+        find_in_given_path (compress_program, path, NULL, false);
       /* If resolved_compress_program_cache == NULL, errno is set here.  */
+      free (default_path);
     }
 
   return resolved_compress_program_cache;
diff --git a/tests/sort/sort-compress.sh b/tests/sort/sort-compress.sh
index 12802ca02..04a2778be 100755
--- a/tests/sort/sort-compress.sh
+++ b/tests/sort/sort-compress.sh
@@ -49,7 +49,21 @@ chmod +x gzip
 PATH=.:$PATH sort -S 1k --compress-program=gzip in > out || fail=1
 compare exp out || fail=1
 test -f ok || fail=1
-rm -f ok
+rm -f ok out
+
+# Test that an unset PATH is not treated the same as an empty
+# PATH, i.e., PATH=''.  On GNU/Linux, an unset PATH searches
+# the default path, but an empty PATH searches the current working
+# directory.  Since the behavior may differ on other platforms, we
+# check it using 'env' first.  In coreutils-9.9 to coreutils-9.12,
+# an unset PATH was turned into an empty PATH.
+env -u PATH gzip </dev/null >/dev/null 2>&1
+if test $? -eq 0  && ! test -f ok; then
+  sort=$(cmd_exe sort) || framework_failure_
+  env -u PATH $sort -S 1k --compress-program=gzip in >out || fail=1
+  compare exp out || fail=1
+  test -f ok && fail=1
+fi
 
 # This is to make sure it works with no compression.
 PATH=.:$PATH sort -S 1k in > out || fail=1
-- 
2.56.0


Reply via email to