@@ -5,8 +5,11 @@ import (
55 "fmt"
66)
77
8- const EOS = - 1
9- const _UNKNOWN = - 2
8+ const (
9+ EOS = - 1
10+ _UNKNOWN = - 2
11+ maxRecursionLevel = 100000
12+ )
1013
1114/* Error {{{ */
1215
@@ -524,7 +527,11 @@ func compilePattern(p pattern, ps ...*iptr) []inst {
524527
525528// Simple recursive virtual machine based on the
526529// "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+ }
528535 var m * MatchData
529536 if len (ms ) == 0 {
530537 m = newMatchState ()
@@ -549,14 +556,14 @@ redo:
549556 pc = inst .Operand1
550557 goto redo
551558 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 {
553560 return true , nsp , m
554561 }
555562 pc = inst .Operand2
556563 goto redo
557564 case opSave :
558565 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 {
560567 return true , nsp , m
561568 }
562569 m .restoreCapture (inst .Operand1 , s )
@@ -620,7 +627,7 @@ func Find(p string, src []byte, offset, limit int) (matches []*MatchData, err er
620627 insts := compilePattern (pat )
621628 matches = []* MatchData {}
622629 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 )
624631 sp ++
625632 if ok {
626633 if sp < nsp {
0 commit comments