]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: in cse, allow for new ssa values
authorPhilip Hofer <phofer@umich.edu>
Tue, 15 Nov 2016 01:05:46 +0000 (17:05 -0800)
committerCherry Zhang <cherryyz@google.com>
Fri, 18 Nov 2016 16:31:27 +0000 (16:31 +0000)
The table of rewrites in ssa/cse is not sized appropriately for
ssa IDs that are created during copying of selects into new blocks.

Fixes #17918

Change-Id: I65fe86c6aab5efa679aa473aadc4ee6ea882cd41
Reviewed-on: https://go-review.googlesource.com/33240
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: David Chase <drchase@google.com>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/compile/internal/ssa/cse.go
test/fixedbugs/issue17918.go [new file with mode: 0644]

index 94104333259ec04c25d3e262a506c740beadaf87..4e07c89b888cd55e0a4ba2f26958d81abd3491b7 100644 (file)
@@ -188,7 +188,10 @@ func cse(f *Func) {
        for _, b := range f.Blocks {
        out:
                for _, v := range b.Values {
-                       if rewrite[v.ID] != nil {
+                       // New values are created when selectors are copied to
+                       // a new block. We can safely ignore those new values,
+                       // since they have already been copied (issue 17918).
+                       if int(v.ID) >= len(rewrite) || rewrite[v.ID] != nil {
                                continue
                        }
                        if v.Op != OpSelect0 && v.Op != OpSelect1 {
diff --git a/test/fixedbugs/issue17918.go b/test/fixedbugs/issue17918.go
new file mode 100644 (file)
index 0000000..88ede6f
--- /dev/null
@@ -0,0 +1,41 @@
+// compile
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 17918: slice out-of-bounds in ssa/cse
+
+package dead
+
+import (
+       "fmt"
+       "time"
+)
+
+var (
+       units = []struct {
+               divisor time.Duration
+               unit    rune
+       }{
+               {1000000, 's'},
+               {60, 'm'},
+               {60, 'h'},
+               {24, 'd'},
+               {7, 'w'},
+       }
+)
+
+func foobar(d time.Duration) string {
+       d /= time.Microsecond
+       unit := 'u'
+
+       for _, f := range units {
+               if d%f.divisor != 0 {
+                       break
+               }
+               d /= f.divisor
+               unit = f.unit
+       }
+       return fmt.Sprintf("%d%c", d, unit)
+}