You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Windows: zstd -r follows directory junctions and symlinks, so -r --rm deletes files outside the given folder #4853
Describe the bug
On Windows, recursive mode ignores reparse points. UTIL_isLink() (programs/util.c) returns 0 on every
non-POSIX platform, and the Windows UTIL_prepareFileList() never checks FILE_ATTRIBUTE_REPARSE_POINT, so a
directory junction or directory symlink inside the tree is entered like an ordinary folder. Unlike the POSIX
build, --no-follow-style behaviour (followLinks = 0, the default for -r) has no effect.
Consequences:
zstd -r --rm folder compresses and deletes files that are not under folder at all.
A junction pointing at an ancestor recurses until the path length or the stack gives out.
To Reproduce (Windows 11, cmd; mklink /J needs no administrator rights)
> mkdir outside tree
> echo outside the tree> outside\secret.txt
> echo inside> tree\a.txt
> mklink /J tree\link outside
Junction created for tree\link <<===>> outside
> zstd -r --rm -q tree
> dir /s /b outside tree
...\outside\secret.txt.zst
...\tree\a.txt.zst
outside\secret.txt has been compressed and deleted, although only tree was named.
Expected behavior
As on POSIX with the default followLinks = 0: junctions and directory symlinks met during recursion are skipped
(with a message at a suitable display level).
Suggested fix
In the Windows UTIL_prepareFileList(), skip entries whose cFile.dwFileAttributes include FILE_ATTRIBUTE_REPARSE_POINT when followLinks is 0, and make UTIL_isLink() test that attribute
(GetFileAttributesA) on Windows. (-f sets followLinks = 1, as on POSIX; the reproduction above does not use -f.)
Desktop
OS: Windows 11 Pro (26200), x64
Version: v1.5.7; UTIL_isLink() unchanged on dev (2026-10-05). UTIL_prepareFileList() on dev differs only
by a free(path) leak fix
Compiler: MSVC 14.51 (Visual Studio 2026 Build Tools), Release
Build system: build/cmake, Visual Studio generator
Environment caveats
Found by code review, then reproduced as shown on Windows 11 only (x64), with zstd.exe built from the v1.5.7 source by MSVC 14.51 (Visual Studio 2026 Build Tools) through build/cmake, Win64 Release only. Not tested with MinGW, clang-cl or the official release binaries, nor on Win32.
tests/playTests.sh was not run (no POSIX shell environment here).
The functions cited were compared with dev (2026-10-05) by source and are unchanged, but dev itself was not built.
The analysis was AI-assisted (Claude); every behaviour reported above was reproduced as shown.
Thanks for the detailed report and the reproduction steps.
The issue is being fixed by #4905, which skips symbolic links and junctions during -r on Windows unless -f is used, as on POSIX.
You are welcome to test it to check if it fixes your issue correctly.
Thanks for the quick fix. I tested it on Windows against the reproduction from the report, and it works.
Setup: Windows 11 Pro (build 26300), MSVC 14.51 (Visual Studio 2026 Build Tools), x64 Release, built with build/cmake (legacy support off). Two builds: dev at 4b0e377, which includes 6bdc1d3, and v1.5.7 as the control (its programs/ is identical to the release).
Each case ran in a fresh directory: tree\inside.txt, outside\secret.txt and tree\link pointing to outside.
zstd -r -k -q tree with tree\loop a junction to tree itself
recursed until the path was too long (Cannot open directory 'tree\loop\loop\...'), exit 1
a.txt.zst written once, exit 0
Without -q, dev prints Warning : tree\link is a symbolic link, ignoring for a junction as well.
Not covered: a Win32 build, playTests.sh (including the test from #4860), and non-name-surrogate reparse points such as OneDrive placeholders or deduplicated files, which I did not have available.
Tested with the help of an AI assistant (Claude Code).
Activity
Cyan4973 commentedon Nov 8, 2026
Thanks for the detailed report and the reproduction steps.
The issue is being fixed by #4905, which skips symbolic links and junctions during
-ron Windows unless-fis used, as on POSIX.You are welcome to test it to check if it fixes your issue correctly.
programs: don't follow symbolic links and junctions in -r on Windows
ijbranch commentedon Nov 8, 2026
Thanks for the quick fix. I tested it on Windows against the reproduction from the report, and it works.
Setup: Windows 11 Pro (build 26300), MSVC 14.51 (Visual Studio 2026 Build Tools), x64 Release, built with
build/cmake(legacy support off). Two builds:devat 4b0e377, which includes 6bdc1d3, and v1.5.7 as the control (itsprograms/is identical to the release).Each case ran in a fresh directory:
tree\inside.txt,outside\secret.txtandtree\linkpointing tooutside.zstd -r --rm -q tree,tree\linka junction (mklink /J)outside\secret.txtcompressed and deletedoutside\secret.txtuntouched;tree\inside.txtcompressedtree\linka directory symlink (mklink /D)-f-fzstd -r -k -q treewithtree\loopa junction totreeitselfCannot open directory 'tree\loop\loop\...'), exit 1a.txt.zstwritten once, exit 0Without
-q,devprintsWarning : tree\link is a symbolic link, ignoringfor a junction as well.Not covered: a Win32 build,
playTests.sh(including the test from #4860), and non-name-surrogate reparse points such as OneDrive placeholders or deduplicated files, which I did not have available.Tested with the help of an AI assistant (Claude Code).