Repository navigation
Escape an unpaired surrogate in a persistence key's file name [patch] - #206
Open
matt-edmondson wants to merge 2 commits into
Open
matt-edmondson wants to merge 2 commits into
matt-edmondson wants to merge 2 commits into
Conversation
GetSafeFileName passed lone surrogates through, and on Unix .NET writes a path as UTF-8, replacing them with U+FFFD. "user\uD800", "user\uDBFF" and "user�" all named one file, overwrote each other, and GetAllKeysAsync listed none of them. An unpaired surrogate is now written as %uXXXX, which GetKeyFromFileName decodes, and truncation never cuts inside one. Paired surrogates (emoji) keep their names. Fixes #202 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017vfJW1od4g4sgqv5pyHNsc
Addresses SonarCloud S3776 (GetSafeFileName's cognitive complexity) and S127 (loop index advanced inside the for body) raised on the %uXXXX change. Both loops are now while loops over a helper that returns how many characters it consumed; the encoding and its bounds checks are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017vfJW1od4g4sgqv5pyHNsc
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Fixes #202
What was wrong
PersistenceProviderUtilities.GetSafeFileNamepassed lone surrogates through unchanged. On Unix, .NET writes a path as UTF-8 and replaces an unpaired surrogate with U+FFFD. So"user\uD800","user\uDBFF"and a literal"user�"all named the same file and overwrote each other, andGetAllKeysAsyncreturned none of the original keys. This happens in practice when a key is user text cut through the middle of an emoji.Change
%uXXXX. The existing%XXform can't hold0xD800, anduisn't a hex digit, so the two forms can't be confused. A literal%is still%25.GetKeyFromFileNamedecodes%uXXXX. It returns null for a malformed form or for one that doesn't name a surrogate, the same way it handles a bad%XX.Truncate's "never split an escape" guard covers the six-character form as well.PersistenceProviderUtilitiesentry describes both escape forms.This doesn't touch #77 (keys that differ only in case). The
%uform works with either fix proposed there.Tests
SafeFileName_Escapes_Unpaired_Surrogates_And_Keeps_Pairs: lone high, lone low, a reversed pair and U+FFFD keys all get distinct names that survive UTF-8 and decode back to the original key. An emoji key is unchanged.SafeFileName_Never_Truncates_Inside_A_Surrogate_Escape: across 25 paddings, a truncated name never ends partway through a%uXXXX.Keys_Differing_Only_In_An_Unpaired_Surrogate_Keep_Separate_Records: onNativeFileSystemProvider,"a\uD800","a\uDBFF"and"a�"keep separate values, andGetAllKeysAsyncreturns all three.Generated by Claude Code