diff --git a/go/analysis/passes/sigchanyzer/sigchanyzer.go b/go/analysis/passes/sigchanyzer/sigchanyzer.go index 3d89061d176..b00aa7e1440 100644 --- a/go/analysis/passes/sigchanyzer/sigchanyzer.go +++ b/go/analysis/passes/sigchanyzer/sigchanyzer.go @@ -49,6 +49,11 @@ func run(pass *analysis.Pass) (interface{}, error) { chanDecl = decl } case *ast.CallExpr: + // Only signal.Notify(make(chan os.Signal), os.Interrupt) is safe, + // conservatively treate others as not safe, see golang/go#45043 + if isBuiltinMake(pass.TypesInfo, arg) { + return + } chanDecl = arg } if chanDecl == nil || len(chanDecl.Args) != 1 { @@ -127,3 +132,16 @@ func findDecl(arg *ast.Ident) ast.Node { } return nil } + +func isBuiltinMake(info *types.Info, call *ast.CallExpr) bool { + typVal := info.Types[call.Fun] + if !typVal.IsBuiltin() { + return false + } + switch fun := call.Fun.(type) { + case *ast.Ident: + return info.ObjectOf(fun).Name() == "make" + default: + return false + } +} diff --git a/go/analysis/passes/sigchanyzer/testdata/src/a/a.go b/go/analysis/passes/sigchanyzer/testdata/src/a/a.go index 277bf2054c0..34dee88c3a0 100644 --- a/go/analysis/passes/sigchanyzer/testdata/src/a/a.go +++ b/go/analysis/passes/sigchanyzer/testdata/src/a/a.go @@ -36,3 +36,19 @@ func j() { f := signal.Notify f(c, os.Interrupt) // want "misuse of unbuffered os.Signal channel as argument to signal.Notify" } + +func k() { + signal.Notify(make(chan os.Signal), os.Interrupt) // ok +} + +func l() { + signal.Notify(make(chan os.Signal, 1), os.Interrupt) // ok +} + +func m() { + signal.Notify(make(chan ao.Signal, 1), os.Interrupt) // ok +} + +func n() { + signal.Notify(make(chan ao.Signal), os.Interrupt) // ok +} diff --git a/go/analysis/passes/sigchanyzer/testdata/src/a/a.go.golden b/go/analysis/passes/sigchanyzer/testdata/src/a/a.go.golden index e3702d72f72..1158ff5fd37 100644 --- a/go/analysis/passes/sigchanyzer/testdata/src/a/a.go.golden +++ b/go/analysis/passes/sigchanyzer/testdata/src/a/a.go.golden @@ -36,3 +36,19 @@ func j() { f := signal.Notify f(c, os.Interrupt) // want "misuse of unbuffered os.Signal channel as argument to signal.Notify" } + +func k() { + signal.Notify(make(chan os.Signal), os.Interrupt) // ok +} + +func l() { + signal.Notify(make(chan os.Signal, 1), os.Interrupt) // ok +} + +func m() { + signal.Notify(make(chan ao.Signal, 1), os.Interrupt) // ok +} + +func n() { + signal.Notify(make(chan ao.Signal), os.Interrupt) // ok +}