Commit bc44b818 authored by David Chase's avatar David Chase

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/9601Reviewed-by: default avatarRuss Cox <rsc@golang.org>
parent 7bebccb9
...@@ -343,12 +343,11 @@ const ( ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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 {
......
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