@@ -5,8 +5,11 @@ import (
5
5
"fmt"
6
6
)
7
7
8
- const EOS = - 1
9
- const _UNKNOWN = - 2
8
+ const (
9
+ EOS = - 1
10
+ _UNKNOWN = - 2
11
+ maxRecursionLevel = 100000
12
+ )
10
13
11
14
/* Error {{{ */
12
15
@@ -524,7 +527,11 @@ func compilePattern(p pattern, ps ...*iptr) []inst {
524
527
525
528
// Simple recursive virtual machine based on the
526
529
// "Regular Expression Matching: the Virtual Machine Approach" (https://swtch.com/~rsc/regexp/regexp2.html)
527
- func recursiveVM (src []byte , insts []inst , pc , sp int , ms ... * MatchData ) (bool , int , * MatchData ) {
530
+ func recursiveVM (src []byte , insts []inst , pc , sp , recLevel int , ms ... * MatchData ) (bool , int , * MatchData ) {
531
+ recLevel ++
532
+ if recLevel > maxRecursionLevel {
533
+ panic (newError (_UNKNOWN , "pattern/input too complex" ))
534
+ }
528
535
var m * MatchData
529
536
if len (ms ) == 0 {
530
537
m = newMatchState ()
@@ -549,14 +556,14 @@ redo:
549
556
pc = inst .Operand1
550
557
goto redo
551
558
case opSplit :
552
- if ok , nsp , _ := recursiveVM (src , insts , inst .Operand1 , sp , m ); ok {
559
+ if ok , nsp , _ := recursiveVM (src , insts , inst .Operand1 , sp , recLevel , m ); ok {
553
560
return true , nsp , m
554
561
}
555
562
pc = inst .Operand2
556
563
goto redo
557
564
case opSave :
558
565
s := m .setCapture (inst .Operand1 , sp )
559
- if ok , nsp , _ := recursiveVM (src , insts , pc + 1 , sp , m ); ok {
566
+ if ok , nsp , _ := recursiveVM (src , insts , pc + 1 , sp , recLevel , m ); ok {
560
567
return true , nsp , m
561
568
}
562
569
m .restoreCapture (inst .Operand1 , s )
@@ -620,7 +627,7 @@ func Find(p string, src []byte, offset, limit int) (matches []*MatchData, err er
620
627
insts := compilePattern (pat )
621
628
matches = []* MatchData {}
622
629
for sp := offset ; sp <= len (src ); {
623
- ok , nsp , ms := recursiveVM (src , insts , 0 , sp )
630
+ ok , nsp , ms := recursiveVM (src , insts , 0 , sp , 0 )
624
631
sp ++
625
632
if ok {
626
633
if sp < nsp {
0 commit comments