From f515c1bac708c46f3bb4811439fc75bd013300c9 Mon Sep 17 00:00:00 2001 From: "Andrew W. Phillips" Date: Tue, 29 Aug 2023 20:55:59 +1000 Subject: [PATCH] cmd/go/internal/work: avoid panic for a repeated //go:debug setting The creation of a bytes.Buffer in one code path is missing causing a nil pointer dereference. Changed (as rec. by Bryan Mills) to use fmt.Appendf() on []byte instead of fmt.Fprintf on *bytes.Buffer - simpler and avoids duplicated code (but requires Go 1.19 or later). Added test to verify the change (as rec. by Michael Matloob) at src\cmd\go\testdata\script\build_repeated_godebug_issue62346.txt Fixes #62346 Change-Id: Ic3267d878a6f7ebedb1cde64e6206de404176b10 Reviewed-on: https://go-review.googlesource.com/c/go/+/523836 Reviewed-by: Michael Matloob LUCI-TryBot-Result: Go LUCI Reviewed-by: Dmitri Shuralyov Auto-Submit: Michael Matloob --- src/cmd/go/internal/work/exec.go | 13 +++++-------- .../script/build_repeated_godebug_issue62346.txt | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 src/cmd/go/testdata/script/build_repeated_godebug_issue62346.txt diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index 90c61a9c30..8dd9802f4f 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -989,21 +989,18 @@ OverlayLoop: } func (b *Builder) checkDirectives(a *Action) error { - var msg *bytes.Buffer + var msg []byte p := a.Package var seen map[string]token.Position for _, d := range p.Internal.Build.Directives { if strings.HasPrefix(d.Text, "//go:debug") { key, _, err := load.ParseGoDebug(d.Text) if err != nil && err != load.ErrNotGoDebug { - if msg == nil { - msg = new(bytes.Buffer) - } - fmt.Fprintf(msg, "%s: invalid //go:debug: %v\n", d.Pos, err) + msg = fmt.Appendf(msg, "%s: invalid //go:debug: %v\n", d.Pos, err) continue } if pos, ok := seen[key]; ok { - fmt.Fprintf(msg, "%s: repeated //go:debug for %v\n\t%s: previous //go:debug\n", d.Pos, key, pos) + msg = fmt.Appendf(msg, "%s: repeated //go:debug for %v\n\t%s: previous //go:debug\n", d.Pos, key, pos) continue } if seen == nil { @@ -1012,12 +1009,12 @@ func (b *Builder) checkDirectives(a *Action) error { seen[key] = d.Pos } } - if msg != nil { + if len(msg) > 0 { // We pass a non-nil error to reportCmd to trigger the failure reporting // path, but the content of the error doesn't matter because msg is // non-empty. err := errors.New("invalid directive") - return b.Shell(a).reportCmd("", "", msg.Bytes(), err) + return b.Shell(a).reportCmd("", "", msg, err) } return nil } diff --git a/src/cmd/go/testdata/script/build_repeated_godebug_issue62346.txt b/src/cmd/go/testdata/script/build_repeated_godebug_issue62346.txt new file mode 100644 index 0000000000..23534dde58 --- /dev/null +++ b/src/cmd/go/testdata/script/build_repeated_godebug_issue62346.txt @@ -0,0 +1,14 @@ +[short] skip # runs go build +! go build file.go +! stderr 'panic:' +! stderr 'runtime error' +stderr 'file.go:2:1: repeated //go:debug for panicnil' + +-- file.go -- +//go:debug panicnil=1 +//go:debug panicnil=1 + +package main + +func main() { +} -- 2.48.1