Skip to content

lib/encoder: fix decoding a trailing character after an escaped quote - #10036

Merged
ncw merged 1 commit into
rclone:masterfrom
kevin9327:fix-encoder-quote-before-trailing
Oct 13, 2026
Merged

ncw merged 1 commit into
rclone:masterfrom
kevin9327:fix-encoder-quote-before-trailing

Conversation

@kevin9327

Copy link
Copy Markdown
Contributor

What does this change do?

MultiEncoder.Decode gets a trailing replaced character wrong when the original name has a literal ‛ (U+201B, QuoteRune) just before it. Any of RightSpace, RightPeriod or RightCrLfHtVt is affected:

EncodeRightSpace: "a‛ " -> Encode -> "a‛‛␠" -> Decode -> "a‛␠"   (want "a‛ ")
EncodeRightPeriod: "a‛." -> Encode -> "a‛‛." -> Decode -> "a‛."  (want "a‛.")

Encode is correct: it escapes the literal quote as ‛‛ and replaces the trailing space with ␠. On the way back, the suffix code in Decode only checks whether the rune before ␠/./␉… is a QuoteRune. If it is, Decode treats the symbol as a quoted literal. That check doesn't account for the quote being the second half of an escaped ‛‛. So a file named a‛ on a remote whose encoding includes RightSpace (OneDrive, Windows local, etc.) is decoded as a‛␠.

The fix counts the run of QuoteRunes before the trailing symbol. Only an odd count means the last quote applies to the symbol. The prefix side scans from the start and doesn't have this problem.

I found this with a randomized Decode(Encode(s)) == s check over random masks and names. With this change, the only round-trip failures left in that check are a separate EncodeDot case (".." / ".." encode to "..", which decodes to ".."). I've left that out of this PR so the change stays minimal.

Linked issue

None. This is a small, self-contained decoding fix.

Checklist

  • This change is trivial OR it has been discussed and agreed in the linked issue. (small obvious bug fix)
  • I have read the contribution guidelines.
  • (If I used AI tools to help write this code) I have read and understood the AI-assisted contributions guidance, and I have tested and take ownership of this change myself.
  • I have added tests for all changes in this PR if appropriate.
  • I have added documentation for the changes if appropriate. (n/a)
  • All commit messages are in house style.
  • (Backend changes only) test_all passes for this backend and if submitting a new backend can provide a test account for the integration tester - see CONTRIBUTING.md. (n/a)
  • This Pull Request is ready for review.

TestEncodeQuoteBeforeRightEdge fails on master for 4 of its 5 cases (the decode errors above) and passes with the fix. go test ./lib/... ./backend/local/... and golangci-lint run ./lib/encoder/ pass.

@ncw ncw 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.

Thank you for this, and for the clear write-up - looks great :-)

If you'd like to look at the EncodeDot case you mentioned (".." and ".." colliding), a separate PR would be welcome. That one is a genuine encoding collision rather than a decode bug, so it may need a bit of discussion first about what the right encoding should be.

@ncw
ncw merged commit f91c9d2 into rclone:master Oct 13, 2026
9 checks passed
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.

2 participants