Skip to content

Commit

Permalink
regexp: fix LiteralPrefix for certain onepass progs
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
cespare authored and rsc committed Nov 25, 2015
1 parent 937172b commit d1eedfe
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 2 deletions.
15 changes: 14 additions & 1 deletion src/regexp/all_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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()
Expand Down
7 changes: 6 additions & 1 deletion src/regexp/onepass.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit d1eedfe

Please sign in to comment.