Commit 15cb7ed3 authored by Rob Pike's avatar Rob Pike

regexp: fix prefix bug.

After a prefix match, the old code advanced the length of the
prefix.  This is incorrect since the full match might begin
in the middle of the prefix. (Consider "aaaab+" matching
"aaaaaab").

Fixes #1373

R=rsc
CC=golang-dev
https://golang.org/cl/3795044
parent c0d0d4ef
...@@ -78,6 +78,7 @@ var findTests = []FindTest{ ...@@ -78,6 +78,7 @@ var findTests = []FindTest{
{`axxb$`, "axxcb", nil}, {`axxb$`, "axxcb", nil},
{`data`, "daXY data", build(1, 5, 9)}, {`data`, "daXY data", build(1, 5, 9)},
{`da(.)a$`, "daXY data", build(1, 5, 9, 7, 8)}, {`da(.)a$`, "daXY data", build(1, 5, 9, 7, 8)},
{`zx+`, "zzx", build(1, 1, 3)},
// can backslash-escape any punctuation // can backslash-escape any punctuation
{`\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\{\|\}\~`, {`\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\{\|\}\~`,
......
...@@ -758,7 +758,6 @@ func (re *Regexp) doExecute(str string, bytestr []byte, pos int) []int { ...@@ -758,7 +758,6 @@ func (re *Regexp) doExecute(str string, bytestr []byte, pos int) []int {
return nil return nil
} }
// fast check for initial plain substring // fast check for initial plain substring
prefixed := false // has this iteration begun by skipping a prefix?
if re.prefix != "" { if re.prefix != "" {
advance := 0 advance := 0
if anchored { if anchored {
...@@ -781,8 +780,7 @@ func (re *Regexp) doExecute(str string, bytestr []byte, pos int) []int { ...@@ -781,8 +780,7 @@ func (re *Regexp) doExecute(str string, bytestr []byte, pos int) []int {
if advance == -1 { if advance == -1 {
return nil return nil
} }
pos += advance + len(re.prefix) pos += advance
prefixed = true
} }
arena := &matchArena{nil, 2 * (re.nbra + 1)} arena := &matchArena{nil, 2 * (re.nbra + 1)}
for pos <= end { for pos <= end {
...@@ -790,12 +788,7 @@ func (re *Regexp) doExecute(str string, bytestr []byte, pos int) []int { ...@@ -790,12 +788,7 @@ func (re *Regexp) doExecute(str string, bytestr []byte, pos int) []int {
// prime the pump if we haven't seen a match yet // prime the pump if we haven't seen a match yet
match := arena.noMatch() match := arena.noMatch()
match.m[0] = pos match.m[0] = pos
if prefixed { s[out] = arena.addState(s[out], re.start.next, false, match, pos, end)
s[out] = arena.addState(s[out], re.prefixStart, true, match, pos, end)
prefixed = false // next iteration should start at beginning of machine.
} else {
s[out] = arena.addState(s[out], re.start.next, false, match, pos, end)
}
arena.free(match) // if addState saved it, ref was incremented arena.free(match) // if addState saved it, ref was incremented
} }
in, out = out, in // old out state is new in state in, out = out, in // old out state is new in state
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment