From ac2946029ad3806349fa00546449da9f59320e89 Mon Sep 17 00:00:00 2001 From: Tim King Date: Mon, 22 May 2023 13:46:35 -0700 Subject: [PATCH] go/ssa: fix bug in writeSignature on external functions Fixes a panic in writeSignature when fn.Params is non-empty while the function has a receiver. fn.Params is nil for non-Go source functions (synthetic or from object files). Change-Id: Iae3f7ce53fca05d1b154349c3b091aee015afa0b Reviewed-on: https://go-review.googlesource.com/c/tools/+/497155 Run-TryBot: Tim King Reviewed-by: Alan Donovan gopls-CI: kokoro TryBot-Result: Gopher Robot --- go/ssa/func.go | 10 +++++----- go/ssa/sanity.go | 3 +++ go/ssa/ssa.go | 4 ++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/go/ssa/func.go b/go/ssa/func.go index 60cf53f6003..38c3e31baff 100644 --- a/go/ssa/func.go +++ b/go/ssa/func.go @@ -516,15 +516,15 @@ func (f *Function) relMethod(from *types.Package, recv types.Type) string { } // writeSignature writes to buf the signature sig in declaration syntax. -func writeSignature(buf *bytes.Buffer, from *types.Package, name string, sig *types.Signature, params []*Parameter) { +func writeSignature(buf *bytes.Buffer, from *types.Package, name string, sig *types.Signature) { buf.WriteString("func ") if recv := sig.Recv(); recv != nil { buf.WriteString("(") - if n := params[0].Name(); n != "" { - buf.WriteString(n) + if name := recv.Name(); name != "" { + buf.WriteString(name) buf.WriteString(" ") } - types.WriteType(buf, params[0].Type(), types.RelativeTo(from)) + types.WriteType(buf, recv.Type(), types.RelativeTo(from)) buf.WriteString(") ") } buf.WriteString(name) @@ -599,7 +599,7 @@ func WriteFunction(buf *bytes.Buffer, f *Function) { fmt.Fprintf(buf, "# % 3d:\t%s %s\n", i, l.Name(), relType(mustDeref(l.Type()), from)) } } - writeSignature(buf, from, f.Name(), f.Signature, f.Params) + writeSignature(buf, from, f.Name(), f.Signature) buf.WriteString(":\n") if f.Blocks == nil { diff --git a/go/ssa/sanity.go b/go/ssa/sanity.go index 88ad374ded0..886be053251 100644 --- a/go/ssa/sanity.go +++ b/go/ssa/sanity.go @@ -8,6 +8,7 @@ package ssa // Currently it checks CFG invariants but little at the instruction level. import ( + "bytes" "fmt" "go/types" "io" @@ -412,8 +413,10 @@ func (s *sanity) checkFunction(fn *Function) bool { s.errorf("nil Prog") } + var buf bytes.Buffer _ = fn.String() // must not crash _ = fn.RelString(fn.relPkg()) // must not crash + WriteFunction(&buf, fn) // must not crash // All functions have a package, except delegates (which are // shared across packages, or duplicated as weak symbols in a diff --git a/go/ssa/ssa.go b/go/ssa/ssa.go index 313146d3351..bd42f2e0a90 100644 --- a/go/ssa/ssa.go +++ b/go/ssa/ssa.go @@ -258,8 +258,8 @@ type Node interface { // or method. // // If Blocks is nil, this indicates an external function for which no -// Go source code is available. In this case, FreeVars and Locals -// are nil too. Clients performing whole-program analysis must +// Go source code is available. In this case, FreeVars, Locals, and +// Params are nil too. Clients performing whole-program analysis must // handle external functions specially. // // Blocks contains the function's control-flow graph (CFG).