diff --git a/lib/util/url.ts b/lib/util/url.ts index f13966eb..2c63a522 100644 --- a/lib/util/url.ts +++ b/lib/util/url.ts @@ -16,7 +16,7 @@ const urlEncodePatterns = [ ] as [RegExp, string][]; // RegExp patterns to URL-decode special characters for local filesystem paths -const urlDecodePatterns = [/%23/g, "#", /%24/g, "$", /%26/g, "&", /%2C/g, ",", /%40/g, "@"]; +const urlDecodePatterns = [/%23/g, "#", /%24/g, "$", /%26/g, "&", /%2C/g, ",", /%3F/g, "?", /%40/g, "@"]; const unsafeDomainSuffixes = [".localhost", ".local", ".internal", ".intranet", ".corp", ".home", ".lan"]; diff --git a/test/specs/util/url.spec.ts b/test/specs/util/url.spec.ts index 9563c059..65475c2d 100644 --- a/test/specs/util/url.spec.ts +++ b/test/specs/util/url.spec.ts @@ -152,3 +152,19 @@ describe("Handle Linux file paths", () => { expect($url.toFileSystemPath("FILE:///a/random/Path/file.json")).to.equal("/a/random/Path/file.json"); }); }); + +describe("Round-trip special characters in filesystem paths", () => { + it("should round-trip a literal question mark", () => { + const original = "/a/random/Path/defs?1.json"; + const encoded = $url.fromFileSystemPath(original); + expect(encoded).to.equal("/a/random/Path/defs%3F1.json"); + expect($url.toFileSystemPath(encoded)).to.equal(original); + }); + + it("should round-trip a literal hash", () => { + const original = "/a/random/Path/defs#1.json"; + const encoded = $url.fromFileSystemPath(original); + expect(encoded).to.equal("/a/random/Path/defs%231.json"); + expect($url.toFileSystemPath(encoded)).to.equal(original); + }); +});