Skip to content

Commit 2ac5bb5

Browse files
committed
Limit recursion in regex parser (#757)
Cherry-picks some more changes from swift/main. * Limit recursion in regex parser * Also check for custom char class nesting
1 parent c75631d commit 2ac5bb5

File tree

2 files changed

+20
-0
lines changed

2 files changed

+20
-0
lines changed

Sources/_RegexParser/Regex/Parse/Parse.swift

+13
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,19 @@ extension Parser {
523523
mutating func parseCustomCharacterClass(
524524
_ start: Source.Located<CustomCC.Start>
525525
) -> CustomCC {
526+
// Excessively nested recursion is a common DOS attack, so limit
527+
// our recursion.
528+
context.parseDepth += 1
529+
defer { context.parseDepth -= 1 }
530+
guard context.parseDepth < context.maxParseDepth else {
531+
self.errorAtCurrentPosition(.nestingTooDeep)
532+
533+
// This is not generally recoverable and further errors will be
534+
// incorrect
535+
diags.suppressFurtherDiagnostics = true
536+
return .init(start, [], start.location)
537+
}
538+
526539
let alreadyInCCC = context.isInCustomCharacterClass
527540
context.isInCustomCharacterClass = true
528541
defer { context.isInCustomCharacterClass = alreadyInCCC }

Tests/RegexTests/ParseTests.swift

+7
Original file line numberDiff line numberDiff line change
@@ -3335,6 +3335,13 @@ extension RegexTests {
33353335
+ "a"
33363336
+ String(repeating: ")*", count: 500),
33373337
.nestingTooDeep)
3338+
3339+
diagnosticTest(
3340+
String(repeating: "[", count: 500)
3341+
+ "a"
3342+
+ String(repeating: "]*", count: 500),
3343+
.nestingTooDeep)
3344+
33383345
}
33393346

33403347
func testDelimiterLexingErrors() {

0 commit comments

Comments
 (0)