Instantly share code, notes, and snippets.

@methane /badptr_amd64.go Secret
Created Dec 27, 2018

Embed
What would you like to do?
package main
import (
"fmt"
"runtime"
"sync"
"unsafe"
)
var stopC = make(chan struct{})
// stress starts GC repeatedly to enable write barrier.
func stress() {
for {
select {
case <-stopC:
return
default:
runtime.GC()
}
}
}
var wg sync.WaitGroup
var throttle = make(chan struct{}, 1)
//go:noinline
func noPointerArgs(a, b, c, d uint64) {
<-throttle
wg.Done()
}
func main() {
// make large heap to make write barrier longer
x := make(map[string]string)
for i := 0; i < 10000; i++ {
x[fmt.Sprintf("k%v", i)] = fmt.Sprintf("v%v", i)
}
// enable write barrier.
go stress()
// build integer looks like bad pointer. amd64 specific.
y := uint64(uintptr(unsafe.Pointer(&x)))
fmt.Printf("%x -> ", y)
y |= 0x3000000
fmt.Printf("%x\n", y)
// run go func()
wg.Add(10000000)
for i := 0; i < 10000000; i++ {
throttle <- struct{}{}
go noPointerArgs(y, y, y, y)
}
wg.Wait()
close(stopC)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment