]> Cypherpunks repositories - gostls13.git/commitdiff
regexp: fix LiteralPrefix for certain onepass progs
authorCaleb Spare <cespare@gmail.com>
Thu, 22 Oct 2015 06:03:54 +0000 (23:03 -0700)
committerRuss Cox <rsc@golang.org>
Wed, 25 Nov 2015 17:28:33 +0000 (17:28 +0000)
The prefix computation for onepass was incorrectly returning
complete=true when it encountered a beginning-of-text empty width match
(^) in the middle of an expression.

Fix by returning complete only when the prefix is followed by $ and then
an accepting state.

Fixes #11175.

Change-Id: Ie9c4cf5f76c1d2c904a6fb2f016cedb265c19fde
Reviewed-on: https://go-review.googlesource.com/16200
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
src/regexp/all_test.go
src/regexp/onepass.go

index ebe31d7fbb1932c7dd9731b5a251a2827b1ff8b4..88391ff47decd531c4266dc756689f8265246de9 100644 (file)
@@ -359,6 +359,19 @@ var metaTests = []MetaTest{
        {`!@#$%^&*()_+-=[{]}\|,<.>/?~`, `!@#\$%\^&\*\(\)_\+-=\[\{\]\}\\\|,<\.>/\?~`, `!@#`, false},
 }
 
+var literalPrefixTests = []MetaTest{
+       // See golang.org/issue/11175.
+       // output is unused.
+       {`^0^0$`, ``, `0`, false},
+       {`^0^`, ``, ``, false},
+       {`^0$`, ``, `0`, true},
+       {`$0^`, ``, ``, false},
+       {`$0$`, ``, ``, false},
+       {`^^0$$`, ``, ``, false},
+       {`^$^$`, ``, ``, false},
+       {`$$0^^`, ``, ``, false},
+}
+
 func TestQuoteMeta(t *testing.T) {
        for _, tc := range metaTests {
                // Verify that QuoteMeta returns the expected string.
@@ -390,7 +403,7 @@ func TestQuoteMeta(t *testing.T) {
 }
 
 func TestLiteralPrefix(t *testing.T) {
-       for _, tc := range metaTests {
+       for _, tc := range append(metaTests, literalPrefixTests...) {
                // Literal method needs to scan the pattern.
                re := MustCompile(tc.pattern)
                str, complete := re.LiteralPrefix()
index e6f42856387bc1ffc8efe9bd6ea714bc45dfa127..2bd81e32335598001fd9ec614fbe630fe851ba7c 100644 (file)
@@ -59,7 +59,12 @@ func onePassPrefix(p *syntax.Prog) (prefix string, complete bool, pc uint32) {
                buf.WriteRune(i.Rune[0])
                pc, i = i.Out, &p.Inst[i.Out]
        }
-       return buf.String(), i.Op == syntax.InstEmptyWidth && (syntax.EmptyOp(i.Arg))&syntax.EmptyBeginText != 0, pc
+       if i.Op == syntax.InstEmptyWidth &&
+               syntax.EmptyOp(i.Arg)&syntax.EmptyEndText != 0 &&
+               p.Inst[i.Out].Op == syntax.InstMatch {
+               complete = true
+       }
+       return buf.String(), complete, pc
 }
 
 // OnePassNext selects the next actionable state of the prog, based on the input character.