Skip to content

Commit 9300c93

Browse files
committed
fix: improve regex pattern to avoid backtracking
1 parent 6837fe7 commit 9300c93

File tree

3 files changed

+15
-12
lines changed

3 files changed

+15
-12
lines changed

_abnf.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
atomic,
23
either,
34
maybe,
45
namedCapture,
@@ -8,23 +9,23 @@ import {
89
import { optimize } from "https://esm.sh/regexp-tree";
910

1011
const tchar = /[!#$%&'*+.^_`|~\dA-Za-z-]/;
11-
const token = suffix("+", tchar);
12+
const token = atomic(suffix("+", tchar));
1213
const authScheme = namedCapture("authScheme", token);
1314
const SP = / /;
1415
const ALPHA = /[A-Za-z]/;
1516
const DIGIT = /\d/;
1617
const token68 = sequence(
17-
suffix("+", either(ALPHA, DIGIT, /[-._~+/]/)),
18-
suffix("*", "="),
18+
atomic(suffix("+", either(ALPHA, DIGIT, /[-._~+/]/))),
19+
atomic(suffix("*", "=")),
1920
);
2021

2122
const challenge = sequence(
2223
authScheme,
2324
maybe(
24-
suffix("+", SP),
25+
atomic(suffix("+", SP)),
2526
either(
2627
namedCapture("token68", token68),
27-
namedCapture("authParam", /.*/),
28+
namedCapture("authParam", atomic(/.*/)),
2829
),
2930
),
3031
);
@@ -33,7 +34,9 @@ const OWS = /[ \t]*/;
3334
const BWS = OWS;
3435

3536
const element = sequence(
36-
maybe(/.*?/, suffix("*", OWS, ",", OWS, maybe(/.*?/))),
37+
atomic(
38+
maybe(atomic(/.*?/), atomic(suffix("*", OWS, ",", OWS, maybe(/.*?/)))),
39+
),
3740
);
3841

3942
const DQUOTE = /"/;
@@ -45,7 +48,7 @@ const quotedPair = sequence("\\", either(HTAB, SP, VCHAR, obsText));
4548

4649
const quotedString = sequence(
4750
DQUOTE,
48-
suffix("*", either(qdtext, quotedPair)),
51+
atomic(suffix("*", either(qdtext, quotedPair))),
4952
DQUOTE,
5053
);
5154

parse.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import type { Authorization, AuthParams } from "./types.ts";
88

99
/** Generate from _abnf.ts. */
1010
const reAuthorization =
11-
/^(?<authScheme>[\w!#$%&'*+.^`|~-]+)(?: +(?:(?<token68>(?:[A-Za-z]|\d|[+./_~-])+=*)|(?<authParam>.*)))?$/;
11+
/^(?<authScheme>(?=([\w!#$%&'*+.^`|~-]+))\2)(?:(?=( +))\3(?:(?<token68>(?=((?:[A-Za-z]|\d|[+./_~-])+))\5(?=(=*))\6)|(?<authParam>(?=(.*))\8)))?$/;
1212

1313
/** Parse string into {@link Authorization}.
1414
*
@@ -60,7 +60,7 @@ type ParsedGroups = {
6060

6161
/** Generate from _abnf.ts. */
6262
const reAuthParam =
63-
/^(?<key>[\w!#$%&'*+.^`|~-]+)[\t ]*=[\t ]*(?:(?<token>[\w!#$%&'*+.^`|~-]+)|(?<quotedString>"(?:\t| |!|[ \x23-\x5B\x5D-\x7E]|[\x80-\xFF]|\\(?:\t| |[\x21-\x7E]|[\x80-\xFF]))*"))$/;
63+
/^(?<key>(?=([\w!#$%&'*+.^`|~-]+))\2)[\t ]*=[\t ]*(?:(?<token>(?=([\w!#$%&'*+.^`|~-]+))\4)|(?<quotedString>"(?=((?:\t| |!|[ \x23-\x5B\x5D-\x7E]|[\x80-\xFF]|\\(?:\t| |[\x21-\x7E]|[\x80-\xFF]))*))\6"))$/;
6464

6565
type AuthParamGroups =
6666
& { key: string }

stringify.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export function stringifyAuthorization(input: AuthorizationLike): string {
4747
return [input.authScheme, data].filter(Boolean).join(" ");
4848
}
4949

50-
const reToken = /^[\w!#$%&'*+.^`|~-]+$/;
50+
const reToken = /^(?=([\w!#$%&'*+.^`|~-]+))\1$/;
5151

5252
export function assertToken(
5353
input: string,
@@ -61,7 +61,7 @@ export function isToken(input: string): boolean {
6161
return reToken.test(input);
6262
}
6363

64-
const reToken68 = /^[A-Za-z\d+./_~-]+=*$/;
64+
const reToken68 = /^(?=((?:[A-Za-z]|\d|[+./_~-])+))\1(?=(=*))\2$/;
6565

6666
export function isToken68(input: string): boolean {
6767
return reToken68.test(input);
@@ -76,7 +76,7 @@ export function assertToken68(
7676
}
7777

7878
const reQuotedString =
79-
/^"(?:\t| |!|[ \x23-\x5B\x5D-\x7E]|[\x80-\xFF]|\\(?:\t| |[\x21-\x7E]|[\x80-\xFF]))*"$/;
79+
/^"(?=((?:\t| |!|[ \x23-\x5B\x5D-\x7E]|[\x80-\xFF]|\\(?:\t| |[\x21-\x7E]|[\x80-\xFF]))*))\1"$/;
8080

8181
export function isQuotedString(input: string): boolean {
8282
return reQuotedString.test(input);

0 commit comments

Comments
 (0)