Skip to content

Fix GetCanonicalPathAsync resolving full path instead of parent - #1864

Merged
Rob-Hague merged 2 commits into
sshnet:developfrom
GitMonkey007:fix/getcanonicalpath
Nov 14, 2026
Merged

Rob-Hague merged 2 commits into
sshnet:developfrom
GitMonkey007:fix/getcanonicalpath

Conversation

@GitMonkey007

@GitMonkey007 GitMonkey007 commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #1863

First time contributing to this project, relatively trivial, but still a bug I think worth fixing. Discovered this issue when looking at MoveTo vs RenameAsync; I've made the relevant change and tried to adhere to the standards/contributing docs; let me know if I've missed something.

The fix itself just moves the problematic implementation details into shared methods (because they previously differ); I've added some tests again trying to adhere to the style in the project.

AI not used to write the change.

@Rob-Hague

Copy link
Copy Markdown
Collaborator

Thanks, I have tried to avoid understanding this part of the code in the past but the sync/async paths are clearly inconsistent, seems it was an accident in 508fc87. I've taken the liberty of combining the whole thing into a shared method. I thought about adding an integration test but it seems like it is quite hard to hit this depending on the server behaviour of SSH_FXP_REALPATH, but if you have a straightforward case then we can add it.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

A regression test is still needed for the parent-path fallback in both GetCanonicalPath and GetCanonicalPathAsync to guard against the original full-path retry bug.

1 open issue
What changed in this PR

This PR addresses #1863 by aligning SSH.NET’s synchronous and asynchronous SFTP path canonicalization so failed full-path lookups fall back to resolving the parent directory.

Changes:

  • Share canonicalization logic between sync and async methods.
  • Correct the async fallback to resolve the parent and append the final path component.
  • Avoid allocating a string for ordinal character searches in the compatibility helper.
File Description
src/​Renci.SshNet/​Sftp/​SftpSession.cs Unifies canonicalization logic and corrects the async parent-path fallback.
src/​Renci.SshNet/​Abstractions/​StringExtensions.cs Optimizes ordinal character searches using IndexOf(char).

Review effort: Balanced

Comment thread src/Renci.SshNet/Sftp/SftpSession.cs Resolved
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.

Inconsistent behaviour between the synchronous and asynchronous versions of GetCanonicalPath

3 participants