Skip to content

Commit

Permalink
Add backtrack protection to 6.x (#324)
Browse files Browse the repository at this point in the history
  • Loading branch information
blakeembrey authored Sep 12, 2024
1 parent 28a5b27 commit f1253b4
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 55 deletions.
102 changes: 102 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"@types/node": "^20.4.9",
"@types/semver": "^7.3.1",
"@vitest/coverage-v8": "^1.4.0",
"recheck": "^4.4.5",
"semver": "^7.3.5",
"size-limit": "^11.1.2",
"typescript": "^5.1.6"
Expand All @@ -46,7 +47,7 @@
"size-limit": [
{
"path": "dist.es2015/index.js",
"limit": "2 kB"
"limit": "2.1 kB"
}
],
"ts-scripts": {
Expand Down
21 changes: 21 additions & 0 deletions redos.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { checkSync } from "recheck";
import { pathToRegexp } from "./src/index.js";

let safe = 0;
let fail = 0;

const tests = ["/:x{/foobar/:y}?-:z"];

for (const path of tests) {
const regexp = pathToRegexp(path);
const result = checkSync(regexp.source, regexp.flags);
if (result.status === "safe") {
safe++;
console.log("Safe:", path, String(regexp));
} else {
fail++;
console.log("Fail:", path, String(regexp));
}
}

console.log("Safe:", safe, "Fail:", fail);
79 changes: 32 additions & 47 deletions src/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1353,7 +1353,7 @@ const TESTS: Test[] = [
prefix: ".",
suffix: "",
modifier: "+",
pattern: "[^\\/#\\?]+?",
pattern: "(?:(?!\\.)[^\\/#\\?])+?",
},
],
[
Expand Down Expand Up @@ -1397,7 +1397,7 @@ const TESTS: Test[] = [
prefix: ".",
suffix: "",
modifier: "",
pattern: "[^\\/#\\?]+?",
pattern: "(?:(?!\\.)[^\\/#\\?])+?",
},
".",
],
Expand Down Expand Up @@ -1430,13 +1430,13 @@ const TESTS: Test[] = [
prefix: ".",
suffix: "",
modifier: "",
pattern: "[^\\/#\\?]+?",
pattern: "(?:(?!\\.)[^\\/#\\?])+?",
},
],
[
["/route.html", ["/route.html", "route", "html"]],
["/route", null],
["/route.html.json", ["/route.html.json", "route", "html.json"]],
["/route.html.json", ["/route.html.json", "route.html", "json"]],
],
[
[{}, null],
Expand All @@ -1459,13 +1459,13 @@ const TESTS: Test[] = [
prefix: ".",
suffix: "",
modifier: "?",
pattern: "[^\\/#\\?]+?",
pattern: "(?:(?!\\.)[^\\/#\\?])+?",
},
],
[
["/route", ["/route", "route", undefined]],
["/route.json", ["/route.json", "route", "json"]],
["/route.json.html", ["/route.json.html", "route", "json.html"]],
["/route.json.html", ["/route.json.html", "route.json", "html"]],
],
[
[{ test: "route" }, "/route"],
Expand All @@ -1491,13 +1491,13 @@ const TESTS: Test[] = [
prefix: ".",
suffix: "",
modifier: "?",
pattern: "[^\\/#\\?]+?",
pattern: "(?:(?!\\.)[^\\/#\\?])+?",
},
],
[
["/route", ["/route", "route", undefined]],
["/route.json", ["/route.json", "route", "json"]],
["/route.json.html", ["/route.json.html", "route", "json.html"]],
["/route.json.html", ["/route.json.html", "route.json", "html"]],
],
[
[{ test: "route" }, "/route"],
Expand Down Expand Up @@ -2084,7 +2084,7 @@ const TESTS: Test[] = [
prefix: "",
suffix: "",
modifier: "?",
pattern: "[^\\/#\\?]+?",
pattern: "(?:(?!\\()[^\\/#\\?])+?",
},
")",
],
Expand Down Expand Up @@ -2290,7 +2290,7 @@ const TESTS: Test[] = [
prefix: ".",
suffix: "",
modifier: "",
pattern: "[^\\/#\\?]+?",
pattern: "(?:(?!\\.)[^\\/#\\?])+?",
},
],
[
Expand Down Expand Up @@ -2356,14 +2356,14 @@ const TESTS: Test[] = [
[
{
name: "foo",
pattern: "[^\\/#\\?]+?",
pattern: "(?:(?!\\$)[^\\/#\\?])+?",
prefix: "$",
suffix: "",
modifier: "",
},
{
name: "bar",
pattern: "[^\\/#\\?]+?",
pattern: "(?:(?!\\$)[^\\/#\\?])+?",
prefix: "$",
suffix: "",
modifier: "?",
Expand Down Expand Up @@ -2392,14 +2392,14 @@ const TESTS: Test[] = [
},
{
name: "attr2",
pattern: "[^\\/#\\?]+?",
pattern: "(?:(?!-)[^\\/#\\?])+?",
prefix: "-",
suffix: "",
modifier: "?",
},
{
name: "attr3",
pattern: "[^\\/#\\?]+?",
pattern: "(?:(?!-)[^\\/#\\?])+?",
prefix: "-",
suffix: "",
modifier: "?",
Expand Down Expand Up @@ -2597,39 +2597,6 @@ const TESTS: Test[] = [
[{ foo: "#" }, null],
],
],
/**
* https://github.com/pillarjs/path-to-regexp/issues/260
*/
[
":name*",
undefined,
[
{
name: "name",
prefix: "",
suffix: "",
modifier: "*",
pattern: "[^\\/#\\?]+?",
},
],
[["foobar", ["foobar", "foobar"]]],
[[{ name: "foobar" }, "foobar"]],
],
[
":name+",
undefined,
[
{
name: "name",
prefix: "",
suffix: "",
modifier: "+",
pattern: "[^\\/#\\?]+?",
},
],
[["foobar", ["foobar", "foobar"]]],
[[{ name: "foobar" }, "foobar"]],
],
];

/**
Expand Down Expand Up @@ -2799,6 +2766,24 @@ describe("path-to-regexp", () => {
pathToRegexp.pathToRegexp("/foo?");
}).toThrow(new TypeError("Unexpected MODIFIER at 4, expected END"));
});

it("should throw on parameters without text between them", () => {
expect(() => {
pathToRegexp.pathToRegexp("/:x:y");
}).toThrow(
new TypeError(
`Must have text between two parameters, missing text after "x"`,
),
);
});

it("should throw on unrepeatable params", () => {
expect(() => {
pathToRegexp.pathToRegexp("/foo:x*");
}).toThrow(
new TypeError(`Can not repeat "x" without a prefix and suffix`),
);
});
});

describe("tokens", () => {
Expand Down
Loading

0 comments on commit f1253b4

Please sign in to comment.