Commit c5414457 authored by Keith Randall's avatar Keith Randall Committed by Keith Randall

cmd/compile: pad zero-sized stack variables

If someone takes a pointer to a zero-sized stack variable, it can
be incorrectly interpreted as a pointer to the next object in the
stack frame. To avoid this, add some padding after zero-sized variables.

We only need to pad if the next variable in memory (which is the
previous variable in the order in which we allocate variables to the
stack frame) has pointers. If the next variable has no pointers, it
won't hurt to have a pointer to it.

Because we allocate all pointer-containing variables before all
non-pointer-containing variables, we should only have to pad once per
frame.

Fixes #24993

Change-Id: Ife561cdfdf964fdbf69af03ae6ba97d004e6193c
Reviewed-on: https://go-review.googlesource.com/c/155698
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent debca779
...@@ -153,6 +153,7 @@ func (s *ssafn) AllocFrame(f *ssa.Func) { ...@@ -153,6 +153,7 @@ func (s *ssafn) AllocFrame(f *ssa.Func) {
sort.Sort(byStackVar(fn.Dcl)) sort.Sort(byStackVar(fn.Dcl))
// Reassign stack offsets of the locals that are used. // Reassign stack offsets of the locals that are used.
lastHasPtr := false
for i, n := range fn.Dcl { for i, n := range fn.Dcl {
if n.Op != ONAME || n.Class() != PAUTO { if n.Op != ONAME || n.Class() != PAUTO {
continue continue
...@@ -167,10 +168,20 @@ func (s *ssafn) AllocFrame(f *ssa.Func) { ...@@ -167,10 +168,20 @@ func (s *ssafn) AllocFrame(f *ssa.Func) {
if w >= thearch.MAXWIDTH || w < 0 { if w >= thearch.MAXWIDTH || w < 0 {
Fatalf("bad width") Fatalf("bad width")
} }
if w == 0 && lastHasPtr {
// Pad between a pointer-containing object and a zero-sized object.
// This prevents a pointer to the zero-sized object from being interpreted
// as a pointer to the pointer-containing object (and causing it
// to be scanned when it shouldn't be). See issue 24993.
w = 1
}
s.stksize += w s.stksize += w
s.stksize = Rnd(s.stksize, int64(n.Type.Align)) s.stksize = Rnd(s.stksize, int64(n.Type.Align))
if types.Haspointers(n.Type) { if types.Haspointers(n.Type) {
s.stkptrsize = s.stksize s.stkptrsize = s.stksize
lastHasPtr = true
} else {
lastHasPtr = false
} }
if thearch.LinkArch.InFamily(sys.MIPS, sys.MIPS64, sys.ARM, sys.ARM64, sys.PPC64, sys.S390X) { if thearch.LinkArch.InFamily(sys.MIPS, sys.MIPS64, sys.ARM, sys.ARM64, sys.PPC64, sys.S390X) {
s.stksize = Rnd(s.stksize, int64(Widthptr)) s.stksize = Rnd(s.stksize, int64(Widthptr))
......
// asmcheck
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Make sure a pointer variable and a zero-sized variable
// aren't allocated to the same stack slot.
// See issue 24993.
package codegen
func zeroSize() {
c := make(chan struct{})
// amd64:`MOVQ\t\$0, ""\.s\+32\(SP\)`
var s *int
g(&s) // force s to be a stack object
// amd64:`LEAQ\t""\..*\+31\(SP\)`
c <- struct{}{}
}
//go:noinline
func g(p **int) {
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment