You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Persistence keys COM¹–COM³, LPT¹–LPT³, COM0 and LPT0 aren't escaped, so on Windows they resolve to device names instead of files #146
PersistenceProviderUtilities.ReservedDeviceNames (Essentials/PersistenceProviderUtilities.cs:22-27) lists CON, PRN, AUX, NUL, COM1-COM9 and LPT1-LPT9, and IsReservedDeviceName (:291-297) checks against that list.
COM¹, COM², COM³, LPT¹, LPT² and LPT³, because Windows treats the ISO-8859-1 superscript digits ¹ ² ³ as digits in device names;
COM0 and LPT0.
None of these is in the list.
Failure scenario
GetSafeFileName("COM¹") returns COM¹ unchanged: none of its characters are reserved or control characters, and the stem isn't in ReservedDeviceNames.
FileSystemPersistenceProvider.StoreAsync("COM¹", obj) (and the DataHome, ConfigHome and Temp providers) therefore writes to <base>/COM¹.json.
On Windows that path resolves to the serial-port device, not a file. The store then fails, blocks, or writes to the device, and a later retrieve can't read the data back.
Keys are free-form strings from callers, so any app that persists user-named items can hit this. The existing test (Essentials.Tests/PersistenceNamingTests.cs:60) only covers the ASCII names.
Suggested fix
Add COM0, LPT0, COM¹, COM², COM³, LPT¹, LPT² and LPT³ to ReservedDeviceNames. Names in that set already get their first character escaped, and GetKeyFromFileName reverses the escape, so nothing else should need to change.
Acceptance criteria
For each new name, GetSafeFileName returns an escaped stem.
GetKeyFromFileName(GetSafeFileName(name)) == name for each new name.
The data rows in PersistenceNamingTests are extended to cover these names.
Priority: Medium. On Windows, a caller-supplied key of COM0, LPT0 or COM¹–LPT³ makes the file-backed providers write to a device instead of a file, so the store fails or the data can't be read back. The keys involved are unusual, but they are free-form caller input, and the fix is a few list entries.
Area / suggested assignee:PersistenceProviderUtilities.ReservedDeviceNames and PersistenceNamingTests. Owner: @matt-edmondson
Activity
matt-edmondson commentedon Oct 18, 2026
Triage
COM0,LPT0orCOM¹–LPT³makes the file-backed providers write to a device instead of a file, so the store fails or the data can't be read back. The keys involved are unusual, but they are free-form caller input, and the fix is a few list entries.PersistenceProviderUtilities.ReservedDeviceNamesandPersistenceNamingTests. Owner: @matt-edmondsonReservedDeviceNamesand extend thePersistenceNamingTestsdata rows with escape and round-trip assertions.Generated by Claude Code