From 592e461b3b429aa8866d1c3e55bafadac9777b21 Mon Sep 17 00:00:00 2001 From: Jay Howard Date: Sun, 6 Sep 2026 20:36:43 -0500 Subject: [PATCH] programs: strip trailing '\r' from --filelist entries `--filelist` stopped accepting Windows CRLF line endings in 165e52ce ("first implementation supporting Process Substitution", #4349). That rewrite reads the list into a buffer opened in binary mode and splits it on '\n' alone. Previously the list was opened in text mode, where the Windows CRT translated CRLF to LF before the parser saw it, so stripping '\n' was enough. In binary mode the CR survives into every path: zstd: can't stat a.txt : No such file or directory -- ignored The '\r' is invisible in that message, which makes it awkward to diagnose. Drop a trailing '\r' when the line pointers are built, and add a playTests case that fails without the fix. --- programs/util.c | 7 +++++++ tests/playTests.sh | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/programs/util.c b/programs/util.c index 652530b1223..1f61520b857 100644 --- a/programs/util.c +++ b/programs/util.c @@ -730,6 +730,13 @@ static const char** UTIL_createLinePointers(char* buffer, size_t numLines, size_ len++; } + /* Drop a trailing '\r' so lists written with Windows-native CRLF + * endings (e.g. `dir /b > list.txt`) resolve. The file is opened in + * binary mode, so the C runtime does not strip it for us. */ + if (len > 0 && buffer[pos + len - 1] == '\r') { + buffer[pos + len - 1] = '\0'; + } + /* Move past this string and its null terminator */ pos += len; if (pos < bufferSize) pos++; /* Skip the null terminator if we're not at buffer end */ diff --git a/tests/playTests.sh b/tests/playTests.sh index d8ea0c3dad3..f00539d2b06 100755 --- a/tests/playTests.sh +++ b/tests/playTests.sh @@ -800,6 +800,13 @@ zstd -f --filelist=tmp_symLink test -f tmp2.zst test -f tmp1.zst +println "test : file list with Windows CRLF line endings, --filelist=FILE" +rm -f *.zst +printf 'tmp1\r\ntmp2\r\n' > tmp_crlfList +zstd -f --filelist=tmp_crlfList +test -f tmp1.zst +test -f tmp2.zst + println "test : compress multiple files reading them from multiple files, --filelist=FILE" rm -f *.zst println "Hello world!, file3" > tmp3