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 | 18 ++++++------------
tests/stat/stat-fmt.sh | 7 +++++++
2 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/src/stat.c b/src/stat.c
index e682bc6b9..a159d1358 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -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
diff --git a/tests/stat/stat-fmt.sh b/tests/stat/stat-fmt.sh
index 11cc09bc9..364516582 100755
--- a/tests/stat/stat-fmt.sh
+++ b/tests/stat/stat-fmt.sh
@@ -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
--
2.54.0