Created
July 18, 2015 15:40
-
-
Save joeduffy/0cf84adbe6ada42a6fc6 to your computer and use it in GitHub Desktop.
Breaking Go memory safety by violating concurrency safety (#2: interfaces).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// teariface.go | |
// A simple demonstration of breaking Go memory safety by violating concurrency | |
// safety. We alias an interface variable which is of course multiple words; | |
// the net result is the itable pointer and target object pointer end up | |
// mismatched, triggering undefined behavior (wrong results, AVs, etc). | |
package main | |
import ( | |
"fmt" | |
"runtime" | |
) | |
type I interface { | |
F() string | |
M() string | |
} | |
type A struct { | |
nm string | |
} | |
func (a *A) F() string { return a.nm } | |
func (a *A) M() string { return "A" } | |
func MakeA() *A { return &A{nm: "A"} } | |
type B struct { | |
nm string | |
} | |
func (b *B) F() string { return b.nm } | |
func (b *B) M() string { return "B" } | |
func MakeB() *B { return &B{nm: "B"} } | |
type C struct { | |
// No field! | |
} | |
func (c *C) F() string { return "C" } | |
func (c *C) M() string { return "C" } | |
func MakeC() *C { return &C{} } | |
func main() { | |
// Make sure we've got some parallelism. | |
runtime.GOMAXPROCS(32) | |
a := MakeA() | |
b := MakeB() | |
c := MakeC() | |
var shared I | |
shared = a // Initially an A. | |
// Kick off some goroutines that just continuosly read the shared obj. | |
for i := 0; i < 16; i++ { | |
go func() { | |
for { | |
local := shared // Make a local copy (logically one read). | |
if local.F() != local.M() { | |
// All Fs should == Ms. | |
fmt.Printf("torn face: '%v' != '%v'\n", | |
local.F(), local.M()) | |
} | |
} | |
}() | |
} | |
// Finally, continuously swap in our A, B, and C typed pointers. | |
for { | |
shared = b | |
shared = c | |
shared = a | |
shared = c | |
shared = b | |
shared = a | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment