diff --git a/contributors.yml b/contributors.yml index f7a29ecb06..add15b112e 100644 --- a/contributors.yml +++ b/contributors.yml @@ -293,6 +293,7 @@ - rtmann - rtzll - rubeonline +- rururux - ryanflorence - ryanhiebert - saengmotmi diff --git a/packages/react-router/__tests__/matchPath-test.tsx b/packages/react-router/__tests__/matchPath-test.tsx index 5d4a95b0aa..fab6bdf94e 100644 --- a/packages/react-router/__tests__/matchPath-test.tsx +++ b/packages/react-router/__tests__/matchPath-test.tsx @@ -355,6 +355,17 @@ describe("matchPath *", () => { pathnameBase: "/users/foo*", }); }); + + it("matches a URL with %0A (a newline character)", () => { + expect(matchPath("*", "/%0A")).toMatchObject({ + pathname: "/%0A", + pathnameBase: "/", + }) + expect(matchPath("*", "/new%0Aline")).toMatchObject({ + pathname: "/new%0Aline", + pathnameBase: "/", + }) + }) }); describe("matchPath warnings", () => { diff --git a/packages/react-router/__tests__/matchRoutes-test.tsx b/packages/react-router/__tests__/matchRoutes-test.tsx index 71c4e472ac..2b22713b0c 100644 --- a/packages/react-router/__tests__/matchRoutes-test.tsx +++ b/packages/react-router/__tests__/matchRoutes-test.tsx @@ -65,6 +65,11 @@ describe("matchRoutes", () => { expect(pickPaths(routes, "/hometypo")).toEqual(["*"]); }); + it("matches root * routes for URLs containing %0A (a newline character)", () => { + expect(pickPaths(routes, "/%0A")).toEqual(["*"]); + expect(pickPaths(routes, "/new%0Aline")).toEqual(["*"]); + }); + it("matches index routes with path correctly", () => { expect(pickPaths(routes, "/withpath")).toEqual(["/withpath"]); }); diff --git a/packages/react-router/lib/router/utils.ts b/packages/react-router/lib/router/utils.ts index cebea7406f..48e5d6b074 100644 --- a/packages/react-router/lib/router/utils.ts +++ b/packages/react-router/lib/router/utils.ts @@ -1255,6 +1255,9 @@ export function compilePath( return isOptional ? "/?([^\\/]+)?" : "/([^\\/]+)"; } ); + // If the URL contains %0A (a newline character), + // the regular expression will not match correctly unless the s (single line) flag is set. + let regexpFlags = ["s"]; if (path.endsWith("*")) { params.push({ paramName: "*" }); @@ -1278,7 +1281,9 @@ export function compilePath( // Nothing to match for "" or "/" } - let matcher = new RegExp(regexpSource, caseSensitive ? undefined : "i"); + if (!caseSensitive) regexpFlags.push("i"); + + let matcher = new RegExp(regexpSource, regexpFlags.join("")); return [matcher, params]; }