Skip to content

Escape reserved Windows device names in output file names#3776

Merged
siegfriedpammer merged 1 commit into
masterfrom
escape-reserved-device-names
Jun 12, 2026
Merged

Escape reserved Windows device names in output file names#3776
siegfriedpammer merged 1 commit into
masterfrom
escape-reserved-device-names

Conversation

@siegfriedpammer

Copy link
Copy Markdown
Member

Fixes #3775.

CleanUpName only checked IsReservedFileSystemName after re-appending the file extension, where it never matches, so a type named Con produced Con.cs both in whole-project export and in the save dialog's default file name -- Windows resolves that to the \\.\CON device and the save fails with an IOException. Reserved directory segments (resource paths, namespace directories) slipped through the same way.

  • CleanUpName now checks each segment as its whitelist loop closes it (separateAtDots dot, path separator, end of input): if the segment's base name (the part before the first dot) is a reserved device name, an underscore is inserted before the dot (con.txt -> con_.txt), since Windows device-name parsing ignores everything after the first dot.
  • The save dialogs' default file names (SaveCodeHelper, AssemblyTreeNode) now go through WholeProjectDecompiler.CleanUpFileName, matching the WPF version, instead of ad-hoc invalid-char loops.
  • Tests: cross-platform expectations in ICSharpCode.Decompiler.Tests (all 22 reserved names x file/directory/path-segment variants) and ILSpy.Tests; ILSpy.Tests.Windows additionally round-trips the sanitized names through a real Windows filesystem. The Windows fixture deliberately does not assert that the raw names fail to be created, because Windows 11 allows reserved names with extensions.

Verified on Linux: full decompiler and UI test suites green. The ILSpy.Tests.Windows fixture still needs a run on a Windows machine.

🤖 Generated with Claude Code

Windows maps CON, PRN, AUX, NUL, COM1-9 and LPT1-9 to devices -- on many
builds even with an extension appended, so a type named Con made both
whole-project export and the save dialog fail with IOException '\\.\Con'.
CleanUpName only checked for reserved names after re-appending the file
extension, where they never match, and the save-dialog default-name
helpers did not check them at all. The escape appends the underscore to
the base name (con_.txt, not con.txt_) because device-name parsing
ignores everything after the first dot, and is applied per path segment
so reserved directory names produced by namespaces are covered too. The
ILSpy.Tests.Windows fixture verifies on a real Windows filesystem that
the escaped names are creatable.

Assisted-by: Claude:claude-fable-5:Claude Code
@siegfriedpammer
siegfriedpammer merged commit 83879c4 into master Jun 12, 2026
9 checks passed
@siegfriedpammer
siegfriedpammer deleted the escape-reserved-device-names branch June 12, 2026 16:58
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.

Con.cs

1 participant