]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: fix uninitialized memory in compare of interface value
authorAustin Clements <austin@google.com>
Mon, 24 Aug 2015 17:35:49 +0000 (13:35 -0400)
committerRuss Cox <rsc@golang.org>
Tue, 25 Aug 2015 14:37:08 +0000 (14:37 +0000)
A comparison of the form l == r where l is an interface and r is
concrete performs a type assertion on l to convert it to r's type.
However, the compiler fails to zero the temporary where the result of
the type assertion is written, so if the type is a pointer type and a
stack scan occurs while in the type assertion, it may see an invalid
pointer on the stack.

Fix this by zeroing the temporary. This is equivalent to the fix for
type switches from c4092ac.

Fixes #12253.

Change-Id: Iaf205d456b856c056b317b4e888ce892f0c555b9
Reviewed-on: https://go-review.googlesource.com/13872
Reviewed-by: Russ Cox <rsc@golang.org>
src/cmd/compile/internal/gc/walk.go
src/runtime/export_test.go
src/runtime/gc_test.go
src/runtime/iface.go

index ce73018b8b01a08d0eb075d78fbc11e4cd7846b1..af3e1ccbe4e5424191aec5e6fe888bb9bb2e5384 100644 (file)
@@ -3219,6 +3219,11 @@ func walkcompare(np **Node, init **NodeList) {
 
        if l != nil {
                x := temp(r.Type)
+               if haspointers(r.Type) {
+                       a := Nod(OAS, x, nil)
+                       typecheck(&a, Etop)
+                       *init = list(*init, a)
+               }
                ok := temp(Types[TBOOL])
 
                // l.(type(r))
index 16d54765b7e967ea61c981aa1c3fdc5a4eacd2a4..f14dc30a7f1027c38b13d87fd8662a920841b398 100644 (file)
@@ -154,3 +154,4 @@ func BenchSetType(n int, x interface{}) {
 const PtrSize = ptrSize
 
 var TestingAssertE2I2GC = &testingAssertE2I2GC
+var TestingAssertE2T2GC = &testingAssertE2T2GC
index 636e5248c8b1d117d9b0378dfa423d1d6c08a02c..6c9b314c65e0dbc58f301737c2072e0f0d1d77b1 100644 (file)
@@ -469,3 +469,20 @@ func testAssertVar(x interface{}) error {
        }
        return nil
 }
+
+func TestAssertE2T2Liveness(t *testing.T) {
+       *runtime.TestingAssertE2T2GC = true
+       defer func() {
+               *runtime.TestingAssertE2T2GC = false
+       }()
+
+       poisonStack()
+       testIfaceEqual(io.EOF)
+}
+
+func testIfaceEqual(x interface{}) {
+       if x == "abc" {
+               // Prevent inlining
+               panic("")
+       }
+}
index abd7068ed1afcb9f4e7f57b7b5d72df5d34d3fff..332b7d50ab33aa110ff5dd0686524f741f827206 100644 (file)
@@ -229,8 +229,13 @@ func assertE2T(t *_type, e interface{}, r unsafe.Pointer) {
        }
 }
 
+var testingAssertE2T2GC bool
+
 // The compiler ensures that r is non-nil.
 func assertE2T2(t *_type, e interface{}, r unsafe.Pointer) bool {
+       if testingAssertE2T2GC {
+               GC()
+       }
        ep := (*eface)(unsafe.Pointer(&e))
        if ep._type != t {
                memclr(r, uintptr(t.size))