From: Pádraig Brady
Date: Sat, 1 Jul 2023 16:01:18 +0000 (+0100) Subject: cksum: escape filenames with a leading '\' in --check status X-Git-Tag: v9.4~81 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=86614ba1c2854d3209086db3788124f6cd07a9ff;p=thirdparty%2Fcoreutils.git cksum: escape filenames with a leading '\' in --check status * src/digest.c (digest_check): Also escape in the case that the file name contains '\'. * tests/cksum/md5sum-bsd.sh: Add a test case. * doc/coreutils.texi (md5um invocation): Clarify escaping operation. * NEWS: Mention the bug fix. Fixes https://bugs.gnu.org/64392 --- diff --git a/NEWS b/NEWS index a3ce05e632..35ae02a8eb 100644 --- a/NEWS +++ b/NEWS @@ -19,6 +19,11 @@ GNU coreutils NEWS -*- outline -*- cksum again diagnoses read errors in its default CRC32 mode. [bug introduced in coreutils-9.0] + 'cksum --check' now ensures filenames with a leading backslash character + are escaped appropriately in the status output. + This also applies to the standalone checksumming utilities. + [bug introduced in coreutils-8.25] + dd again supports more than two multipliers for numbers. Previously numbers of the form '1024x1024x32' gave "invalid number" errors. [bug introduced in coreutils-9.1] diff --git a/doc/coreutils.texi b/doc/coreutils.texi index d6918e8ad5..c3673fd3f1 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -4162,6 +4162,8 @@ Without @option{--zero}, if @var{file} contains a backslash, newline, or carriage return, the line is started with a backslash, and each problematic character in the file name is escaped with a backslash, making the output unambiguous even in the presence of arbitrary file names. +Since the backslash character itself is escaped, any other backslash +escape sequences are reserved for future use. If @var{file} is omitted or specified as @samp{-}, standard input is read. @@ -4258,8 +4260,8 @@ indicating there was a failure. @cindex BSD output Output BSD style checksums, which indicate the checksum algorithm used. As a GNU extension, if @option{--zero} is not used, file names with problematic -characters are escaped as described above, with the same escaping indicator of -@samp{\} at the start of the line, being used. +characters are escaped as described above, using the same escaping indicator of +@samp{\} at the start of the line, as used with the other output format. The @option{--tag} option implies binary mode, and is disallowed with @option{--text} mode as supporting that would unnecessarily complicate the output format, while providing little benefit. diff --git a/src/digest.c b/src/digest.c index 4c9c477dd4..5490f96a49 100644 --- a/src/digest.c +++ b/src/digest.c @@ -560,6 +560,16 @@ or equivalent standalone program.\ exit (status); } +/* Given a string S, return TRUE if it contains problematic characters + that need escaping. Note we escape '\' itself to provide some forward + compat to introduce escaping of other characters. */ + +static bool +problematic_chars (char const *s) +{ + return strchr (s, '\\') || strchr (s, '\n') || strchr (s, '\r'); +} + #define ISWHITE(c) ((c) == ' ' || (c) == '\t') /* Given a file name, S of length S_LEN, that is not NUL-terminated, @@ -1029,12 +1039,9 @@ output_file (char const *file, int binary_file, void const *digest, unsigned char const *bin_buffer = digest; - /* Output a leading backslash if the file name contains problematic chars. - Note we escape '\' itself to provide some forward compat to introduce - escaping of other characters. */ - bool needs_escape = delim == '\n' && (strchr (file, '\\') - || strchr (file, '\n') - || strchr (file, '\r')); + /* Output a leading backslash if the file name contains problematic chars. */ + bool needs_escape = delim == '\n' && problematic_chars (file); + if (needs_escape) putchar ('\\'); @@ -1206,9 +1213,7 @@ digest_check (char const *checkfile_name) { bool ok; bool missing; - /* Only escape in the edge case producing multiple lines, - to ease automatic processing of status output. */ - bool needs_escape = ! status_only && strchr (filename, '\n'); + bool needs_escape = ! status_only && problematic_chars (filename); properly_formatted_lines = true; diff --git a/tests/cksum/md5sum-bsd.sh b/tests/cksum/md5sum-bsd.sh index 5fe9b2fc93..1581b8ac88 100755 --- a/tests/cksum/md5sum-bsd.sh +++ b/tests/cksum/md5sum-bsd.sh @@ -74,13 +74,17 @@ md5sum --strict -c check.md5 || fail=1 # with the GNU extension of escaped newlines nl=' ' -tab=' ' +t=' ' rm check.md5 -for i in 'a\b' 'a\' "a${nl}b" "a${tab}b"; do +for i in 'a\b' 'a\' '\a' "a${nl}b" "a${t}b"; do : > "$i" md5sum --tag "$i" >> check.md5 || fail=1 done -md5sum --strict -c check.md5 || fail=1 +md5sum --strict -c check.md5 > out || fail=1 +printf '%s: OK\n' '\a\\b' '\a\\' '\\\a' '\a\nb' "a${t}b" > exp || + framework_failure_ +compare exp out || fail=1 + # Ensure BSD traditional format with GNU extension escapes # is in the expected format