1
0
mirror of https://github.com/golang/go synced 2024-11-18 17:14:45 -07:00

cmd/internal/gc: Toughen escape analysis against some bugs.

Ensures that parameter flow bits are not set for tags EscScope, EscHeap, EscNever;
crash the compiler earl to expose faulty logic, rather than flake out silently downstream.

Change-Id: I1428129980ae047d02975f033d56cbbd04f49579
Reviewed-on: https://go-review.googlesource.com/9601
Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
David Chase 2015-05-01 11:16:35 -04:00
parent 7bebccb972
commit bc44b818a6

View File

@ -343,12 +343,11 @@ const (
// escMax returns the maximum of an existing escape value // escMax returns the maximum of an existing escape value
// (and its additional parameter flow flags) and a new escape type. // (and its additional parameter flow flags) and a new escape type.
func escMax(e, etype uint16) uint16 { func escMax(e, etype uint16) uint16 {
if e&EscMask == EscHeap { if e&EscMask >= EscScope {
// normalize // normalize
if e != EscHeap { if e&^EscMask != 0 {
Fatal("Escape information had tag bits combined with 'EscHeap' ") Fatal("Escape information had unexpected return encoding bits (w/ EscScope, EscHeap, EscNever), e&EscMask=%v", e&EscMask)
} }
return EscHeap
} }
if e&EscMask > etype { if e&EscMask > etype {
return e return e
@ -1563,7 +1562,7 @@ func escwalk(e *EscState, level Level, dst *Node, src *Node) {
// Input parameter flowing to output parameter? // Input parameter flowing to output parameter?
var leaks bool var leaks bool
if funcOutputAndInput(dst, src) && src.Esc&EscMask != EscScope && src.Esc != EscHeap && dst.Esc != EscHeap { if funcOutputAndInput(dst, src) && src.Esc&EscMask < EscScope && dst.Esc != EscHeap {
// This case handles: // This case handles:
// 1. return in // 1. return in
// 2. return &in // 2. return &in
@ -1586,7 +1585,7 @@ func escwalk(e *EscState, level Level, dst *Node, src *Node) {
// If parameter content escapes to heap, set EscContentEscapes // If parameter content escapes to heap, set EscContentEscapes
// Note minor confusion around escape from pointer-to-struct vs escape from struct // Note minor confusion around escape from pointer-to-struct vs escape from struct
if dst.Esc == EscHeap && if dst.Esc == EscHeap &&
src.Op == ONAME && src.Class == PPARAM && src.Esc != EscHeap && src.Op == ONAME && src.Class == PPARAM && src.Esc&EscMask < EscScope &&
level.int() > 0 { level.int() > 0 {
src.Esc = escMax(EscContentEscapes|src.Esc, EscNone) src.Esc = escMax(EscContentEscapes|src.Esc, EscNone)
if Debug['m'] != 0 { if Debug['m'] != 0 {
@ -1598,7 +1597,7 @@ func escwalk(e *EscState, level Level, dst *Node, src *Node) {
switch src.Op { switch src.Op {
case ONAME: case ONAME:
if src.Class == PPARAM && (leaks || dst.Escloopdepth < 0) && src.Esc != EscHeap { if src.Class == PPARAM && (leaks || dst.Escloopdepth < 0) && src.Esc&EscMask < EscScope {
if level.guaranteedDereference() > 0 { if level.guaranteedDereference() > 0 {
src.Esc = escMax(EscContentEscapes|src.Esc, EscNone) src.Esc = escMax(EscContentEscapes|src.Esc, EscNone)
if Debug['m'] != 0 { if Debug['m'] != 0 {