]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: avoid memmove -> SSA move rewrite when size is negative
authorKeith Randall <khr@golang.org>
Tue, 24 Dec 2019 02:16:22 +0000 (18:16 -0800)
committerKeith Randall <khr@golang.org>
Mon, 24 Feb 2020 20:23:14 +0000 (20:23 +0000)
We should panic in this situation. Rewriting to a SSA op just leads
to a compiler panic.

Fixes #36259

Change-Id: I6e0bccbed7dd0fdac7ebae76b98a211947947386
Reviewed-on: https://go-review.googlesource.com/c/go/+/212405
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
src/cmd/compile/internal/ssa/gen/generic.rules
src/cmd/compile/internal/ssa/rewritegeneric.go
test/fixedbugs/issue36259.go [new file with mode: 0644]

index 529669ec6a419b9915577a9d7642fc294598776f..1382cdc25900b78c14dce4016499576182c8b8f2 100644 (file)
 
 // Inline small or disjoint runtime.memmove calls with constant length.
 (StaticCall {sym} s1:(Store _ (Const(64|32) [sz]) s2:(Store  _ src s3:(Store {t} _ dst mem))))
+       && sz >= 0
        && isSameSym(sym,"runtime.memmove")
        && t.(*types.Type).IsPtr() // avoids TUINTPTR, see issue 30061
        && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1
index 9d88652d4a56c2b8e9a4648b20018d10b4e702fb..a4a2506d8efc00429526ed5fe02b4e07dad0351c 100644 (file)
@@ -19680,7 +19680,7 @@ func rewriteValuegeneric_OpStaticCall(v *Value) bool {
        b := v.Block
        config := b.Func.Config
        // match: (StaticCall {sym} s1:(Store _ (Const64 [sz]) s2:(Store _ src s3:(Store {t} _ dst mem))))
-       // cond: isSameSym(sym,"runtime.memmove") && t.(*types.Type).IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst,src,sz,config) && clobber(s1) && clobber(s2) && clobber(s3)
+       // cond: sz >= 0 && isSameSym(sym,"runtime.memmove") && t.(*types.Type).IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst,src,sz,config) && clobber(s1) && clobber(s2) && clobber(s3)
        // result: (Move {t.(*types.Type).Elem()} [sz] dst src mem)
        for {
                sym := v.Aux
@@ -19707,7 +19707,7 @@ func rewriteValuegeneric_OpStaticCall(v *Value) bool {
                t := s3.Aux
                mem := s3.Args[2]
                dst := s3.Args[1]
-               if !(isSameSym(sym, "runtime.memmove") && t.(*types.Type).IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, sz, config) && clobber(s1) && clobber(s2) && clobber(s3)) {
+               if !(sz >= 0 && isSameSym(sym, "runtime.memmove") && t.(*types.Type).IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, sz, config) && clobber(s1) && clobber(s2) && clobber(s3)) {
                        break
                }
                v.reset(OpMove)
@@ -19719,7 +19719,7 @@ func rewriteValuegeneric_OpStaticCall(v *Value) bool {
                return true
        }
        // match: (StaticCall {sym} s1:(Store _ (Const32 [sz]) s2:(Store _ src s3:(Store {t} _ dst mem))))
-       // cond: isSameSym(sym,"runtime.memmove") && t.(*types.Type).IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst,src,sz,config) && clobber(s1) && clobber(s2) && clobber(s3)
+       // cond: sz >= 0 && isSameSym(sym,"runtime.memmove") && t.(*types.Type).IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst,src,sz,config) && clobber(s1) && clobber(s2) && clobber(s3)
        // result: (Move {t.(*types.Type).Elem()} [sz] dst src mem)
        for {
                sym := v.Aux
@@ -19746,7 +19746,7 @@ func rewriteValuegeneric_OpStaticCall(v *Value) bool {
                t := s3.Aux
                mem := s3.Args[2]
                dst := s3.Args[1]
-               if !(isSameSym(sym, "runtime.memmove") && t.(*types.Type).IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, sz, config) && clobber(s1) && clobber(s2) && clobber(s3)) {
+               if !(sz >= 0 && isSameSym(sym, "runtime.memmove") && t.(*types.Type).IsPtr() && s1.Uses == 1 && s2.Uses == 1 && s3.Uses == 1 && isInlinableMemmove(dst, src, sz, config) && clobber(s1) && clobber(s2) && clobber(s3)) {
                        break
                }
                v.reset(OpMove)
diff --git a/test/fixedbugs/issue36259.go b/test/fixedbugs/issue36259.go
new file mode 100644 (file)
index 0000000..246eb35
--- /dev/null
@@ -0,0 +1,28 @@
+// compile
+
+// Copyright 2019 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.
+
+package main
+
+func rotate(s []int, m int) {
+    l := len(s)
+    m = m % l
+    buf := make([]int, m)
+
+    copy(buf, s)
+    copy(s, s[m:])
+    copy(s[l-m:], buf)
+}
+
+func main() {
+    a0 := [...]int{1,2,3,4,5}
+    println(a0[0])
+
+    rotate(a0[:], 1)
+    println(a0[0])
+
+    rotate(a0[:], -3)
+    println(a0[0])
+}