From bc44b818a6c3ce69e2cb7a4b942d42c41e764af1 Mon Sep 17 00:00:00 2001 From: David Chase Date: Fri, 1 May 2015 11:16:35 -0400 Subject: [PATCH] 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 --- src/cmd/internal/gc/esc.go | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/cmd/internal/gc/esc.go b/src/cmd/internal/gc/esc.go index 044bb3d31d..c816feaa7f 100644 --- a/src/cmd/internal/gc/esc.go +++ b/src/cmd/internal/gc/esc.go @@ -343,12 +343,11 @@ const ( // escMax returns the maximum of an existing escape value // (and its additional parameter flow flags) and a new escape type. func escMax(e, etype uint16) uint16 { - if e&EscMask == EscHeap { + if e&EscMask >= EscScope { // normalize - if e != EscHeap { - Fatal("Escape information had tag bits combined with 'EscHeap' ") + if e&^EscMask != 0 { + Fatal("Escape information had unexpected return encoding bits (w/ EscScope, EscHeap, EscNever), e&EscMask=%v", e&EscMask) } - return EscHeap } if e&EscMask > etype { return e @@ -1563,7 +1562,7 @@ func escwalk(e *EscState, level Level, dst *Node, src *Node) { // Input parameter flowing to output parameter? 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: // 1. 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 // Note minor confusion around escape from pointer-to-struct vs escape from struct 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 { src.Esc = escMax(EscContentEscapes|src.Esc, EscNone) if Debug['m'] != 0 { @@ -1598,7 +1597,7 @@ func escwalk(e *EscState, level Level, dst *Node, src *Node) { switch src.Op { 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 { src.Esc = escMax(EscContentEscapes|src.Esc, EscNone) if Debug['m'] != 0 {