mirror of
https://github.com/golang/go
synced 2024-11-26 16:46:58 -07:00
[dev.typeparams] runtime: don't keep stack uintptr across potential stack move
Currently, deferproc stores the caller SP as a uintptr in a local variable across a call to newdefer, but newdefer could grow the stack and invalidate this saved SP, causing deferproc to store a stale SP in the defer record. This would lead to us later failing to match that defer to its calling frame, and we wouldn't run the defer at the right time (or possibly at all). It turns out this isn't crashing horribly right now only because the compiler happens to only materialize the result of getcallersp when this variable is used, *after* the call to newdefer. But this is clearly on thin ice, so this CL moves the getcallersp() to the place where we actually need the result. Change-Id: Iae8ab226e03e4482f16acfb965885f0bd83a13b0 Reviewed-on: https://go-review.googlesource.com/c/go/+/337649 Trust: Austin Clements <austin@google.com> Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
parent
37d2219960
commit
cb14e673ec
@ -234,9 +234,6 @@ func deferproc(fn *funcval) { // TODO: Make deferproc just take a func().
|
|||||||
throw("defer on system stack")
|
throw("defer on system stack")
|
||||||
}
|
}
|
||||||
|
|
||||||
sp := getcallersp()
|
|
||||||
callerpc := getcallerpc()
|
|
||||||
|
|
||||||
d := newdefer()
|
d := newdefer()
|
||||||
if d._panic != nil {
|
if d._panic != nil {
|
||||||
throw("deferproc: d.panic != nil after newdefer")
|
throw("deferproc: d.panic != nil after newdefer")
|
||||||
@ -244,8 +241,11 @@ func deferproc(fn *funcval) { // TODO: Make deferproc just take a func().
|
|||||||
d.link = gp._defer
|
d.link = gp._defer
|
||||||
gp._defer = d
|
gp._defer = d
|
||||||
d.fn = fn
|
d.fn = fn
|
||||||
d.pc = callerpc
|
d.pc = getcallerpc()
|
||||||
d.sp = sp
|
// We must not be preempted between calling getcallersp and
|
||||||
|
// storing it to d.sp because getcallersp's result is a
|
||||||
|
// uintptr stack pointer.
|
||||||
|
d.sp = getcallersp()
|
||||||
|
|
||||||
// deferproc returns 0 normally.
|
// deferproc returns 0 normally.
|
||||||
// a deferred func that stops a panic
|
// a deferred func that stops a panic
|
||||||
|
Loading…
Reference in New Issue
Block a user