Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d49da96

Browse files
adonovangopherbot
authored andcommitted
go/analysis/internal/checker: fix panic due to nil Pass
This CL documents that that internal.Pass backdoor accessor function (renamed to ActionPass for clarity) may return nil if the action was never executed, and adds defensive checks. Also, remove go1.22 transitional iterator. Thanks to cuishang for reporting and investigating. Fixes golang/go#75358 Change-Id: I59a8ce5bfb6e3a25ba129c35f321930d6786f611 Reviewed-on: https://go-review.googlesource.com/c/tools/+/702375 Reviewed-by: Robert Findley <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Auto-Submit: Alan Donovan <[email protected]>
1 parent 9da4f7b commit d49da96

File tree

6 files changed

+23
-44
lines changed

6 files changed

+23
-44
lines changed

go/analysis/analysistest/analysistest.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ func Run(t Testing, dir string, a *analysis.Analyzer, patterns ...string) []*Res
425425

426426
// Construct the legacy result.
427427
results = append(results, &Result{
428-
Pass: internal.Pass(act),
428+
Pass: internal.ActionPass(act), // may be nil
429429
Diagnostics: act.Diagnostics,
430430
Facts: facts,
431431
Result: act.Result,
@@ -448,12 +448,12 @@ func Run(t Testing, dir string, a *analysis.Analyzer, patterns ...string) []*Res
448448
type Result struct {
449449
Action *checker.Action
450450

451-
// legacy fields
451+
// legacy fields (do not use)
452452
Facts map[types.Object][]analysis.Fact // nil key => package fact
453-
Pass *analysis.Pass
454-
Diagnostics []analysis.Diagnostic // see Action.Diagnostics
455-
Result any // see Action.Result
456-
Err error // see Action.Err
453+
Pass *analysis.Pass // nil => action not executed
454+
Diagnostics []analysis.Diagnostic // see Action.Diagnostics
455+
Result any // see Action.Result
456+
Err error // see Action.Err
457457
}
458458

459459
// loadPackages uses go/packages to load a specified packages (from source, with

go/analysis/checker/checker.go

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import (
3434
"fmt"
3535
"go/types"
3636
"io"
37+
"iter"
3738
"log"
3839
"os"
3940
"reflect"
@@ -94,14 +95,7 @@ type Graph struct {
9495
// for act := range graph.All() {
9596
// ...
9697
// }
97-
//
98-
// Clients using go1.22 should iterate using the code below and may
99-
// not assume anything else about the result:
100-
//
101-
// graph.All()(func (act *Action) bool {
102-
// ...
103-
// })
104-
func (g *Graph) All() actionSeq {
98+
func (g *Graph) All() iter.Seq[*Action] {
10599
return func(yield func(*Action) bool) {
106100
forEach(g.Roots, func(act *Action) error {
107101
if !yield(act) {
@@ -231,8 +225,9 @@ func Analyze(analyzers []*analysis.Analyzer, pkgs []*packages.Package, opts *Opt
231225

232226
func init() {
233227
// Allow analysistest to access Action.pass,
234-
// for its legacy Result data type.
235-
internal.Pass = func(x any) *analysis.Pass { return x.(*Action).pass }
228+
// for the legacy analysistest.Result data type,
229+
// and for internal/checker.ApplyFixes to access pass.ReadFile.
230+
internal.ActionPass = func(x any) *analysis.Pass { return x.(*Action).pass }
236231
}
237232

238233
type objectFactKey struct {

go/analysis/checker/iter_go122.go

Lines changed: 0 additions & 10 deletions
This file was deleted.

go/analysis/checker/iter_go123.go

Lines changed: 0 additions & 11 deletions
This file was deleted.

go/analysis/internal/checker/checker.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -193,11 +193,13 @@ func Run(args []string, analyzers []*analysis.Analyzer) (exitcode int) {
193193
if analysisflags.Fix {
194194
fixActions := make([]analysisflags.FixAction, len(graph.Roots))
195195
for i, act := range graph.Roots {
196-
fixActions[i] = analysisflags.FixAction{
197-
Name: act.String(),
198-
FileSet: act.Package.Fset,
199-
ReadFileFunc: internal.Pass(act).ReadFile,
200-
Diagnostics: act.Diagnostics,
196+
if pass := internal.ActionPass(act); pass != nil {
197+
fixActions[i] = analysisflags.FixAction{
198+
Name: act.String(),
199+
FileSet: act.Package.Fset,
200+
ReadFileFunc: pass.ReadFile,
201+
Diagnostics: act.Diagnostics,
202+
}
201203
}
202204
}
203205
if err := analysisflags.ApplyFixes(fixActions, dbg('v')); err != nil {

go/analysis/internal/internal.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,8 @@ import "golang.org/x/tools/go/analysis"
88

99
// This function is set by the checker package to provide
1010
// backdoor access to the private Pass field
11-
// of the checker.Action type, for use by analysistest.
12-
var Pass func(any) *analysis.Pass
11+
// of the *checker.Action type, for use by analysistest.
12+
//
13+
// It may return nil, for example if the action was not
14+
// executed because of a failed dependent.
15+
var ActionPass func(action any) *analysis.Pass

0 commit comments

Comments
 (0)