New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/compile: escape analysis doesn't handle interface conversions correctly #29353

Open
mdempsky opened this Issue Dec 20, 2018 · 2 comments

Comments

Projects
None yet
3 participants
@mdempsky
Copy link
Member

mdempsky commented Dec 20, 2018

Running the program below prints something like

allocated 0xc00001c160
finalized 0xc00001c160
accessing 0xc00001c160

This is due to esc.go not recognizing that the conversion from []*T to interface{} involves a heap allocation, so x leaks to the heap. However, esc.go instead only records a flow from x to the return parameter.

This is handled correctly by my escape analysis rewrite, which I hope to submit next release cycle. But maybe someone wants to try fixing it in esc.go for this release.

package main

import "runtime"

type T [4]int

//go:noinline
func f(x []*T) interface{} {
	return x
}

func main() {
	c := make(chan int)
	p := new(T)
	println("allocated", p)
	runtime.SetFinalizer(p, func(q *T) { println("finalized", q); c <- 0 })
	var s [10]*T
	s[0] = p
	h := f(s[:])
	runtime.GC()
	<-c
	println("accessing", h.([]*T)[0])
}
@josharian

This comment has been minimized.

Copy link
Contributor

josharian commented Dec 20, 2018

I’m curious—did you find this by inspection? It might be a worthwhile exercise to set up go-fuzz to try to find other inputs for which esc.go and your rewrite disagree.

@mdempsky

This comment has been minimized.

Copy link
Member

mdempsky commented Dec 20, 2018

I think I first noticed it by inspection while trying to understand esc.go, but my WIP branch is setup to run both esc.go and esc2.go and output any discrepancies, and this is probably the most common.

There are a handful of others where esc.go isn't wrong, but esc2.go is better. For example, esc2.go fixes #7714.

I think rather than fuzzing differences between esc.go and esc2.go, I'd think a better way would be to have a compiler and/or runtime debug mode where we make sure heap objects don't point to the stack, and then fuzz for triggering that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment