Skip to content

Commit 694b378

Browse files
authored
Merge pull request #33 from dop251/fix-ecmascript-num-escape
Fix handling of numeric backslash escape sequences in ECMAScript mode
2 parents 3ab0363 + c7f14a0 commit 694b378

File tree

2 files changed

+67
-4
lines changed

2 files changed

+67
-4
lines changed

regexp_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,58 @@ func TestECMAOctal(t *testing.T) {
740740

741741
}
742742

743+
func TestECMAInvalidEscape(t *testing.T) {
744+
re := MustCompile(`\x0`, ECMAScript)
745+
if m, err := re.MatchString("x0"); err != nil {
746+
t.Fatal(err)
747+
} else if !m {
748+
t.Fatal("Expected match")
749+
}
750+
751+
re = MustCompile(`\x0z`, ECMAScript)
752+
if m, err := re.MatchString("x0z"); err != nil {
753+
t.Fatal(err)
754+
} else if !m {
755+
t.Fatal("Expected match")
756+
}
757+
}
758+
759+
func TestECMAInvalidEscapeCharClass(t *testing.T) {
760+
re := MustCompile(`[\x0]`, ECMAScript)
761+
if m, err := re.MatchString("x"); err != nil {
762+
t.Fatal(err)
763+
} else if !m {
764+
t.Fatal("Expected match")
765+
}
766+
767+
if m, err := re.MatchString("0"); err != nil {
768+
t.Fatal(err)
769+
} else if !m {
770+
t.Fatal("Expected match")
771+
}
772+
773+
if m, err := re.MatchString("z"); err != nil {
774+
t.Fatal(err)
775+
} else if m {
776+
t.Fatal("Expected no match")
777+
}
778+
}
779+
780+
func TestECMAScriptXCurlyBraceEscape(t *testing.T) {
781+
re := MustCompile(`\x{20}`, ECMAScript)
782+
if m, err := re.MatchString(" "); err != nil {
783+
t.Fatal(err)
784+
} else if m {
785+
t.Fatal("Expected no match")
786+
}
787+
788+
if m, err := re.MatchString("xxxxxxxxxxxxxxxxxxxx"); err != nil {
789+
t.Fatal(err)
790+
} else if !m {
791+
t.Fatal("Expected match")
792+
}
793+
}
794+
743795
func TestNegateRange(t *testing.T) {
744796
re := MustCompile(`[\D]`, 0)
745797
if m, err := re.MatchString("A"); err != nil {

syntax/parser.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1648,7 +1648,7 @@ func (p *parser) scanOptions() {
16481648
}
16491649

16501650
// Scans \ code for escape codes that map to single unicode chars.
1651-
func (p *parser) scanCharEscape() (rune, error) {
1651+
func (p *parser) scanCharEscape() (r rune, err error) {
16521652

16531653
ch := p.moveRightGetChar()
16541654

@@ -1657,16 +1657,22 @@ func (p *parser) scanCharEscape() (rune, error) {
16571657
return p.scanOctal(), nil
16581658
}
16591659

1660+
pos := p.textpos()
1661+
16601662
switch ch {
16611663
case 'x':
16621664
// support for \x{HEX} syntax from Perl and PCRE
16631665
if p.charsRight() > 0 && p.rightChar(0) == '{' {
1666+
if p.useOptionE() {
1667+
return ch, nil
1668+
}
16641669
p.moveRight(1)
16651670
return p.scanHexUntilBrace()
1671+
} else {
1672+
r, err = p.scanHex(2)
16661673
}
1667-
return p.scanHex(2)
16681674
case 'u':
1669-
return p.scanHex(4)
1675+
r, err = p.scanHex(4)
16701676
case 'a':
16711677
return '\u0007', nil
16721678
case 'b':
@@ -1684,13 +1690,18 @@ func (p *parser) scanCharEscape() (rune, error) {
16841690
case 'v':
16851691
return '\u000B', nil
16861692
case 'c':
1687-
return p.scanControl()
1693+
r, err = p.scanControl()
16881694
default:
16891695
if !p.useOptionE() && IsWordChar(ch) {
16901696
return 0, p.getErr(ErrUnrecognizedEscape, string(ch))
16911697
}
16921698
return ch, nil
16931699
}
1700+
if err != nil && p.useOptionE() {
1701+
p.textto(pos)
1702+
return ch, nil
1703+
}
1704+
return
16941705
}
16951706

16961707
// Grabs and converts an ascii control character

0 commit comments

Comments
 (0)