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>
diff --git a/src/regexp/backtrack.go b/src/regexp/backtrack.go
index a387fa6..fd95604 100644
--- a/src/regexp/backtrack.go
+++ b/src/regexp/backtrack.go
@@ -36,7 +36,6 @@
 
 	end     int
 	cap     []int
-	reqcap  bool // whether any captures are requested
 	input   input
 	jobs    []job
 	visited []uint32
@@ -72,12 +71,10 @@
 }
 
 // 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 @@
 		}
 	}
 
-	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 @@
 		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 @@
 			// 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 @@
 }
 
 // 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 @@
 	}
 
 	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 @@
 			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