]> Cypherpunks repositories - gostls13.git/commitdiff
regexp: fix slice bounds out of range panics
authorDidier Spezia <didier.06@gmail.com>
Fri, 28 Aug 2015 17:36:35 +0000 (17:36 +0000)
committerRuss Cox <rsc@golang.org>
Fri, 23 Oct 2015 03:30:25 +0000 (03:30 +0000)
Regular expressions involving a (x){0} term are
simplified by removing this term from the
expression, just before the expression is compiled.

The number of subexpressions is evaluated before
the simplification. The number of capture instructions
in the compiled expressions is not necessarily in line
with the number of subexpressions.

When the ReplaceAll(String) methods are used, a number
of capture slots (nmatch) is evaluated as 2*(s+1)
(s being the number of subexpressions).

In some case, it can be higher than the number of capture
instructions evaluated at compile time, resulting in a
panic when the internal slices of regexp.machine
are resized to this value.

Fixed by capping the number of capture slots to the number
of capture instructions.

I must say I do not really see the benefits of setting
nmatch lower than re.prog.NumCap using this 2*(s+1) formula,
so perhaps this can be further simplified.

Fixes #11178
Fixes #11176

Change-Id: I21415e8ef2dd5f2721218e9a679f7f6bfb76ae9b
Reviewed-on: https://go-review.googlesource.com/14013
Reviewed-by: Russ Cox <rsc@golang.org>
src/regexp/all_test.go
src/regexp/regexp.go

index d78ae6a4cdedc85dc9a46b10d89cc9dfaa066e2f..9448f606247f70d8d4500e45a4c26f3c62ae7a4d 100644 (file)
@@ -201,6 +201,12 @@ var replaceTests = []ReplaceTest{
        // Substitution when subexpression isn't found
        {"(x)?", "$1", "123", "123"},
        {"abc", "$1", "123", "123"},
+
+       // Substitutions involving a (x){0}
+       {"(a)(b){0}(c)", ".$1|$3.", "xacxacx", "x.a|c.x.a|c.x"},
+       {"(a)(((b))){0}c", ".$1.", "xacxacx", "x.a.x.a.x"},
+       {"((a(b){0}){3}){5}(h)", "y caramb$2", "say aaaaaaaaaaaaaaaah", "say ay caramba"},
+       {"((a(b){0}){3}){5}h", "y caramb$2", "say aaaaaaaaaaaaaaaah", "say ay caramba"},
 }
 
 var replaceLiteralTests = []ReplaceTest{
index 4e4b41242a3749662835ef1874244d475d67b021..85c070eaeb8caf68bf36699a1e8a6496c3bd7130 100644 (file)
@@ -482,6 +482,10 @@ func (re *Regexp) replaceAll(bsrc []byte, src string, nmatch int, repl func(dst
        } else {
                endPos = len(src)
        }
+       if nmatch > re.prog.NumCap {
+               nmatch = re.prog.NumCap
+       }
+
        for searchPos <= endPos {
                a := re.doExecute(nil, bsrc, src, searchPos, nmatch)
                if len(a) == 0 {