Skip to content

fix(sftp): folder upload skips a symlink back to an ancestor (#543) - #567

Merged
kipavy merged 1 commit into
devfrom
fix/symlink-loop-543
Oct 7, 2026
Merged

kipavy merged 1 commit into
devfrom
fix/symlink-loop-543

Conversation

@kipavy

@kipavy kipavy commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Fixes #543.

LocalFs::list follows symlinks, so a link back to an ancestor (sub/up -> ..) made walk copy the tree once per level. It stopped only when the kernel's 40-hop limit hit ELOOP, about 40 copies deep.

Change

  • Endpoint::real_dir: a directory's canonical path. LocalFs returns canonicalize; remote endpoints return None, because their listings never follow links.
  • visit carries each directory's ancestor chain of canonical paths and leaves out a child directory that resolves to one of them. It returns those paths.
  • walk reports them on sftp-skipped-{tid}, as the tar path already does (local_tar::Walk uses the same ancestor check).
  • Symlinks to files and to unrelated directories are still followed.
  • large_by_walk ignores the returned list. A looped entry is no longer counted; before, its ELOOP made the tree count as large.

Tests

  • New a_link_back_to_an_ancestor_is_skipped_and_other_links_followed. Before the fix it failed with sub/up/sub/up/… dirs about 80 components deep. After: dirs sub, sub/empty, sub/ext, a followed file link, and only sub/up reported as skipped.
  • cargo test --lib -- resume:: passes: 66 passed, 1 ignored.
  • cargo fmt --check and cargo clippy --workspace --all-targets -D warnings are clean.

LocalFs listings follow symlinks, so a link like `sub/up -> ..` made
`walk` copy the tree once per level until the kernel's 40-hop limit
stopped it with ELOOP.

`visit` now tracks the canonical path of each directory's ancestors
and leaves out a directory that resolves to one of them; `walk`
reports it on `sftp-skipped-{tid}`, as the tar path already does.
Symlinks to files and to unrelated directories are still followed.
Remote endpoints never follow links, so `real_dir` is None there and
nothing changes for them.
@kipavy
kipavy merged commit 1d3cefb into dev Oct 7, 2026
4 checks passed
@kipavy
kipavy deleted the fix/symlink-loop-543 branch October 7, 2026 12:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant