mirror of
https://github.com/golang/go
synced 2024-11-18 16:04:44 -07:00
regexp: set b.cap[0] and b.cap[1] only when captures requested
Fixes #10319 Change-Id: I96015b0e1dff30a72de11fea3837638b5c672891 Reviewed-on: https://go-review.googlesource.com/8501 Reviewed-by: Russ Cox <rsc@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
92189a2be2
commit
485f348979
@ -489,6 +489,17 @@ func TestOnePassCutoff(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the same machine can be used with the standard matcher
|
||||
// and then the backtracker when there are no captures.
|
||||
func TestSwitchBacktrack(t *testing.T) {
|
||||
re := MustCompile(`a|b`)
|
||||
long := make([]byte, maxBacktrackVector+1)
|
||||
|
||||
// The following sequence of Match calls used to panic. See issue #10319.
|
||||
re.Match(long) // triggers standard matcher
|
||||
re.Match(long[:1]) // triggers backtracker
|
||||
}
|
||||
|
||||
func BenchmarkLiteral(b *testing.B) {
|
||||
x := strings.Repeat("x", 50) + "y"
|
||||
b.StopTimer()
|
||||
|
@ -36,7 +36,6 @@ type bitState struct {
|
||||
|
||||
end int
|
||||
cap []int
|
||||
reqcap bool // whether any captures are requested
|
||||
input input
|
||||
jobs []job
|
||||
visited []uint32
|
||||
@ -72,12 +71,10 @@ func shouldBacktrack(prog *syntax.Prog) bool {
|
||||
}
|
||||
|
||||
// reset resets the state of the backtracker.
|
||||
// end is the end position in the input. ncap and reqcap are the number
|
||||
// of the machine's capture registers and the number of user-requested
|
||||
// captures respectively.
|
||||
func (b *bitState) reset(end int, ncap int, reqcap int) {
|
||||
// end is the end position in the input.
|
||||
// ncap is the number of captures.
|
||||
func (b *bitState) reset(end int, ncap int) {
|
||||
b.end = end
|
||||
b.reqcap = reqcap > 0
|
||||
|
||||
if cap(b.jobs) == 0 {
|
||||
b.jobs = make([]job, 0, 256)
|
||||
@ -95,8 +92,10 @@ func (b *bitState) reset(end int, ncap int, reqcap int) {
|
||||
}
|
||||
}
|
||||
|
||||
if len(b.cap) < ncap {
|
||||
if cap(b.cap) < ncap {
|
||||
b.cap = make([]int, ncap)
|
||||
} else {
|
||||
b.cap = b.cap[:ncap]
|
||||
}
|
||||
for i := range b.cap {
|
||||
b.cap[i] = -1
|
||||
@ -271,7 +270,7 @@ func (m *machine) tryBacktrack(b *bitState, i input, pc uint32, pos int) bool {
|
||||
case syntax.InstMatch:
|
||||
// We found a match. If the caller doesn't care
|
||||
// where the match is, no point going further.
|
||||
if !b.reqcap {
|
||||
if len(b.cap) == 0 {
|
||||
m.matched = true
|
||||
return m.matched
|
||||
}
|
||||
@ -279,7 +278,9 @@ func (m *machine) tryBacktrack(b *bitState, i input, pc uint32, pos int) bool {
|
||||
// Record best match so far.
|
||||
// Only need to check end point, because this entire
|
||||
// call is only considering one start position.
|
||||
b.cap[1] = pos
|
||||
if len(b.cap) > 1 {
|
||||
b.cap[1] = pos
|
||||
}
|
||||
if !m.matched || (longest && pos > 0 && pos > m.matchcap[1]) {
|
||||
copy(m.matchcap, b.cap)
|
||||
}
|
||||
@ -305,7 +306,7 @@ func (m *machine) tryBacktrack(b *bitState, i input, pc uint32, pos int) bool {
|
||||
}
|
||||
|
||||
// backtrack runs a backtracking search of prog on the input starting at pos.
|
||||
func (m *machine) backtrack(i input, pos int, end int, reqcap int) bool {
|
||||
func (m *machine) backtrack(i input, pos int, end int, ncap int) bool {
|
||||
if !i.canCheckPrefix() {
|
||||
panic("backtrack called for a RuneReader")
|
||||
}
|
||||
@ -320,15 +321,18 @@ func (m *machine) backtrack(i input, pos int, end int, reqcap int) bool {
|
||||
}
|
||||
|
||||
b := m.b
|
||||
b.reset(end, len(m.matchcap), reqcap)
|
||||
b.reset(end, ncap)
|
||||
|
||||
m.matchcap = m.matchcap[:ncap]
|
||||
for i := range m.matchcap {
|
||||
m.matchcap[i] = -1
|
||||
}
|
||||
|
||||
// Anchored search must start at the beginning of the input
|
||||
if startCond&syntax.EmptyBeginText != 0 {
|
||||
b.cap[0] = pos
|
||||
if len(b.cap) > 0 {
|
||||
b.cap[0] = pos
|
||||
}
|
||||
return m.tryBacktrack(b, i, uint32(m.p.Start), pos)
|
||||
}
|
||||
|
||||
@ -349,7 +353,9 @@ func (m *machine) backtrack(i input, pos int, end int, reqcap int) bool {
|
||||
pos += advance
|
||||
}
|
||||
|
||||
b.cap[0] = pos
|
||||
if len(b.cap) > 0 {
|
||||
b.cap[0] = pos
|
||||
}
|
||||
if m.tryBacktrack(b, i, uint32(m.p.Start), pos) {
|
||||
// Match must be leftmost; done.
|
||||
return true
|
||||
|
Loading…
Reference in New Issue
Block a user