Skip to content

Fix relative symlink handling in write_atomic - #17362

Merged
weihanglo merged 2 commits into
rust-lang:masterfrom
cuishuang:master
Sep 5, 2026
Merged

weihanglo merged 2 commits into
rust-lang:masterfrom
cuishuang:master

Conversation

@cuishuang

Copy link
Copy Markdown
Contributor

What does this PR try to resolve?

Fixes #17361.

cargo_util::paths::write_atomic follows symlinks before performing an atomic write. However, fs::read_link returns a relative target exactly as stored in the symlink.

The returned target was previously used directly, causing subsequent filesystem operations to interpret it relative to Cargo's process working directory. This could make the write fail or overwrite an unrelated file.

This change resolves the target against the symlink's parent directory:

resolved_path = path.parent().unwrap().join(target);

Path::join preserves absolute targets, so the existing behavior for absolute symlinks is unchanged.

How to test and review this PR?

A new unit test creates a symlink with a relative target in a directory different from the process working directory. The test verifies that:

  • the actual target receives the updated contents;
  • the symlink remains a symlink;
  • the stored relative target remains unchanged.

I ran:

cargo +1.97.1 test -p cargo-util
cargo fmt --all -- --check
image

All 12 unit tests and the cargo-util doc-test passed.

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 14, 2026
@rustbot

rustbot commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

r? @weihanglo

rustbot has assigned @weihanglo.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: @epage, @weihanglo
  • @epage, @weihanglo expanded to epage, weihanglo
  • Random selection from epage, weihanglo

@cuishuang

Copy link
Copy Markdown
Contributor Author

@weihanglo Would you mind taking a look at this write_atomic symlink fix when you have a chance?

read_link() returns relative targets as stored, but write_atomic was resolving them relative to Cargo's process working directory instead of the symlink's parent. The fix resolves the target against the parent while preserving absolute-target behavior, with a focused regression test.

Thanks!

Comment thread crates/cargo-util/src/paths.rs
Add a regression test that records the current failure when a symlink target is relative to its parent directory.

Signed-off-by: cuishuang <imcusg@gmail.com>
Interpret a relative symlink target relative to the directory containing the symlink before creating the temporary file.

Signed-off-by: cuishuang <imcusg@gmail.com>

@weihanglo weihanglo left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

BTW, I found that if you have a chained of symlinks this will still fail, though this is good enough as an incremental improvment!

View changes since this review

@weihanglo
weihanglo added this pull request to the merge queue Sep 5, 2026
Merged via the queue into rust-lang:master with commit 8d4bb1e Sep 5, 2026
28 checks passed
@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Sep 5, 2026
@cuishuang

Copy link
Copy Markdown
Contributor Author

Thanks!

BTW, I found that if you have a chained of symlinks this will still fail, though this is good enough as an incremental improvment!

View changes since this review

Thanks for pointing this out. I opened a follow-up issue for chained symlink resolution: #17443

I also have a preliminary implementation there. There are still a few design details to discuss, especially symlink loops and dangling targets. #17444

When you have time, feedback or a review would be very helpful. 😄

rust-bors Bot pushed a commit to rust-lang/rust that referenced this pull request Sep 12, 2026
Update cargo submodule

6 commits in 3c0b534756e166d12eb9fd2e1abfe5b42ac6101e..7941be6fb416b4cd9666aef7b858dfea25587a8c
2026-09-04 17:03:10 +0000 to 2026-09-11 20:47:37 +0000
- fix(install): use packaged lockfile by default (rust-lang/cargo#17388)
- test: add more comprehensive workspace feature unification tests (rust-lang/cargo#17466)
- chore(deps): update crossbeam-epoch to 0.9.21 (rust-lang/cargo#17427)
- Fixed stale comment about fingerprint checking method (rust-lang/cargo#17450)
- docs(lints): how to configure Cargo lints (rust-lang/cargo#17441)
- Fix relative symlink handling in write_atomic (rust-lang/cargo#17362)

r? ghost
@rustbot rustbot added this to the 1.100.0 milestone Sep 12, 2026
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.

write_atomic interprets relative symlink targets against the process working directory

3 participants