]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
stat: honor QUOTING_STYLE in default file name quoting
authorPádraig Brady <P@draigBrady.com>
Wed, 3 Jun 2026 15:04:09 +0000 (16:04 +0100)
committerPádraig Brady <P@draigBrady.com>
Thu, 4 Jun 2026 12:14:27 +0000 (13:14 +0100)
This is safer to output to terminal with malicious file names,
with multiple lines or control characters etc.

* src/stat.c: Quote the file name in the default output format
in the default quoting style, or as selected with QUOTING_STYLE.
Reported by Michał Majchrowicz and Marcin Wyczechowski.

src/stat.c
tests/stat/stat-fmt.sh

index e682bc6b9022a874ce30de21674ced017277b460..a159d13581333486c916c62ecdba063042ea42a8 100644 (file)
@@ -1050,6 +1050,11 @@ neg_to_zero (struct timespec ts)
 static void
 getenv_quoting_style (void)
 {
+  static bool got_quoting_style;
+  if (got_quoting_style)
+    return;
+  got_quoting_style = true;
+
   char const *q_style = getenv ("QUOTING_STYLE");
   if (q_style)
     {
@@ -1515,6 +1520,7 @@ print_stat (char *pformat, size_t prefix_len, char mod, char m,
       out_string (pformat, prefix_len, filename);
       break;
     case 'N':
+      getenv_quoting_style ();
       out_string (pformat, prefix_len, quoteN (filename));
       if (S_ISLNK (statbuf->st_mode))
         {
@@ -1970,18 +1976,6 @@ main (int argc, char *argv[])
 
   if (format)
     {
-      bool need_quoting_style = false;
-      for (char const *p = format; (p = strchr (p, '%'));
-           p += (p[1] == '%') + 1)
-        {
-          if (p[1] == 'N')
-            {
-              need_quoting_style = true;
-              break;
-            }
-        }
-      if (need_quoting_style)
-        getenv_quoting_style ();
       format2 = format;
     }
   else
index 11cc09bc93da9e69e1506b7961fe2b7ca2022f02..3645165829d5a3f026b36ff219fc9b936c8259f1 100755 (executable)
@@ -53,6 +53,13 @@ cat <<\EOF >exp
 EOF
 compare exp out || fail=1
 
+# ensure control characters in file names are escaped by default
+stat "$fname" | grep 'File: ' > out || fail=1
+cat <<\EOF >exp
+  File: 'a'$'\n\n''b'$'\n''c'
+EOF
+compare exp out || fail=1
+
 # Check the behavior with invalid values of QUOTING_STYLE.
 for style in '' 'abcdef'; do
   QUOTING_STYLE="$style" stat -c%%%N \' > out 2> err || fail=1