Browse Source

Fallback to regexp2 if repeat count is too large. Fixes #681

Dmitry Panov 1 month ago
parent
commit
af2ceb9156
2 changed files with 24 additions and 7 deletions
  1. 16 7
      builtin_regexp.go
  2. 8 0
      regexp_test.go

+ 16 - 7
builtin_regexp.go

@@ -1,8 +1,10 @@
 package goja
 package goja
 
 
 import (
 import (
+	"errors"
 	"fmt"
 	"fmt"
 	"regexp"
 	"regexp"
+	"regexp/syntax"
 	"strings"
 	"strings"
 	"unicode/utf16"
 	"unicode/utf16"
 	"unicode/utf8"
 	"unicode/utf8"
@@ -242,8 +244,8 @@ func compileRegexp(patternStr, flags string) (p *regexpPattern, err error) {
 		patternStr = convertRegexpToUtf16(patternStr)
 		patternStr = convertRegexpToUtf16(patternStr)
 	}
 	}
 
 
-	re2Str, err1 := parser.TransformRegExp(patternStr, dotAll, unicode)
-	if err1 == nil {
+	re2Str, err := parser.TransformRegExp(patternStr, dotAll, unicode)
+	if err == nil {
 		re2flags := ""
 		re2flags := ""
 		if multiline {
 		if multiline {
 			re2flags += "m"
 			re2flags += "m"
@@ -260,15 +262,22 @@ func compileRegexp(patternStr, flags string) (p *regexpPattern, err error) {
 
 
 		pattern, err1 := regexp.Compile(re2Str)
 		pattern, err1 := regexp.Compile(re2Str)
 		if err1 != nil {
 		if err1 != nil {
-			err = fmt.Errorf("Invalid regular expression (re2): %s (%v)", re2Str, err1)
-			return
+			var syntaxError *syntax.Error
+			if !errors.As(err1, &syntaxError) || syntaxError.Code != syntax.ErrInvalidRepeatSize {
+				err = fmt.Errorf("Invalid regular expression (re2): %s (%v)", re2Str, err1)
+				return
+			}
+		} else {
+			wrapper = (*regexpWrapper)(pattern)
 		}
 		}
-		wrapper = (*regexpWrapper)(pattern)
 	} else {
 	} else {
-		if _, incompat := err1.(parser.RegexpErrorIncompatible); !incompat {
-			err = err1
+		var incompat parser.RegexpErrorIncompatible
+		if !errors.As(err, &incompat) {
 			return
 			return
 		}
 		}
+	}
+
+	if wrapper == nil {
 		wrapper2, err = compileRegexp2(patternStr, multiline, dotAll, ignoreCase, unicode)
 		wrapper2, err = compileRegexp2(patternStr, multiline, dotAll, ignoreCase, unicode)
 		if err != nil {
 		if err != nil {
 			err = fmt.Errorf("Invalid regular expression (regexp2): %s (%v)", patternStr, err)
 			err = fmt.Errorf("Invalid regular expression (regexp2): %s (%v)", patternStr, err)

+ 8 - 0
regexp_test.go

@@ -779,6 +779,14 @@ func TestRegExpLastIndex(t *testing.T) {
 	testScriptWithTestLib(SCRIPT, _undefined, t)
 	testScriptWithTestLib(SCRIPT, _undefined, t)
 }
 }
 
 
+func TestRegExpRepeatCount(t *testing.T) {
+	const SCRIPT = `
+	const re = /^0x[0-9a-fA-F]{0,4096}$/;
+	re.test("0xABCD");
+	`
+	testScript(SCRIPT, valueTrue, t)
+}
+
 func BenchmarkRegexpSplitWithBackRef(b *testing.B) {
 func BenchmarkRegexpSplitWithBackRef(b *testing.B) {
 	const SCRIPT = `
 	const SCRIPT = `
 	"aaaaaaaaaaaaaaaaaaaaaaaaa++bbbbbbbbbbbbbbbbbbbbbb+-ccccccccccccccccccccccc".split(/([+-])\1/)
 	"aaaaaaaaaaaaaaaaaaaaaaaaa++bbbbbbbbbbbbbbbbbbbbbb+-ccccccccccccccccccccccc".split(/([+-])\1/)