Skip to content

Commit e4e5992

Browse files
aclementsadg
authored andcommitted
[release-branch.go1.5] cmd/compile: fix uninitialized memory in compare of interface value
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 <[email protected]> Reviewed-on: https://go-review.googlesource.com/14242 Reviewed-by: Austin Clements <[email protected]>
1 parent 13d03fa commit e4e5992

File tree

4 files changed

+28
-0
lines changed

4 files changed

+28
-0
lines changed

src/cmd/compile/internal/gc/walk.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3219,6 +3219,11 @@ func walkcompare(np **Node, init **NodeList) {
32193219

32203220
if l != nil {
32213221
x := temp(r.Type)
3222+
if haspointers(r.Type) {
3223+
a := Nod(OAS, x, nil)
3224+
typecheck(&a, Etop)
3225+
*init = list(*init, a)
3226+
}
32223227
ok := temp(Types[TBOOL])
32233228

32243229
// l.(type(r))

src/runtime/export_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,3 +154,4 @@ func BenchSetType(n int, x interface{}) {
154154
const PtrSize = ptrSize
155155

156156
var TestingAssertE2I2GC = &testingAssertE2I2GC
157+
var TestingAssertE2T2GC = &testingAssertE2T2GC

src/runtime/gc_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,3 +469,20 @@ func testAssertVar(x interface{}) error {
469469
}
470470
return nil
471471
}
472+
473+
func TestAssertE2T2Liveness(t *testing.T) {
474+
*runtime.TestingAssertE2T2GC = true
475+
defer func() {
476+
*runtime.TestingAssertE2T2GC = false
477+
}()
478+
479+
poisonStack()
480+
testIfaceEqual(io.EOF)
481+
}
482+
483+
func testIfaceEqual(x interface{}) {
484+
if x == "abc" {
485+
// Prevent inlining
486+
panic("")
487+
}
488+
}

src/runtime/iface.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,13 @@ func assertE2T(t *_type, e interface{}, r unsafe.Pointer) {
229229
}
230230
}
231231

232+
var testingAssertE2T2GC bool
233+
232234
// The compiler ensures that r is non-nil.
233235
func assertE2T2(t *_type, e interface{}, r unsafe.Pointer) bool {
236+
if testingAssertE2T2GC {
237+
GC()
238+
}
234239
ep := (*eface)(unsafe.Pointer(&e))
235240
if ep._type != t {
236241
memclr(r, uintptr(t.size))

0 commit comments

Comments
 (0)