Skip to content

Commit

Permalink
cmd/compile: fix uninitialized memory in compare of interface value
Browse files Browse the repository at this point in the history
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 golang#12253.

Change-Id: Iaf205d456b856c056b317b4e888ce892f0c555b9
Reviewed-on: https://go-review.googlesource.com/13872
Reviewed-by: Russ Cox <[email protected]>
  • Loading branch information
aclements authored and rsc committed Aug 25, 2015
1 parent 686d44d commit 05a3b1f
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/cmd/compile/internal/gc/walk.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
1 change: 1 addition & 0 deletions src/runtime/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,4 @@ func BenchSetType(n int, x interface{}) {
const PtrSize = ptrSize

var TestingAssertE2I2GC = &testingAssertE2I2GC
var TestingAssertE2T2GC = &testingAssertE2T2GC
17 changes: 17 additions & 0 deletions src/runtime/gc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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("")
}
}
5 changes: 5 additions & 0 deletions src/runtime/iface.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down

0 comments on commit 05a3b1f

Please sign in to comment.