@@ -55,32 +55,50 @@ func (r *noErrorCheck) Match(n ast.Node, ctx *gosec.Context) (*gosec.Issue, erro
55
55
switch stmt := n .(type ) {
56
56
case * ast.AssignStmt :
57
57
for _ , expr := range stmt .Rhs {
58
- if callExpr , ok := expr .(* ast.CallExpr ); ok {
59
- pos := returnsError (callExpr , ctx )
60
- if pos < 0 || pos >= len (stmt .Lhs ) {
61
- return nil , nil
62
- }
63
- id , ok := stmt .Lhs [pos ].(* ast.Ident )
64
- if ! ok {
65
- // don't think this should ever happen
66
- return gosec .NewIssue (ctx , n , r .ID (), "PANIC!" , r .Severity , r .Confidence ), nil
67
- } else if ok && id .Name == "_" {
68
- // error is just ignored!
69
- return gosec .NewIssue (ctx , n , r .ID (), r .What , r .Severity , r .Confidence ), nil
70
- }
58
+ callExpr , ok := expr .(* ast.CallExpr )
59
+ if ! ok {
60
+ continue
61
+ }
71
62
72
- // TODO: next line should check `id.Name != nil`,
73
- // and the BlockStmt that follows should have a ReturnStmt
74
- // that includes the id.Name
63
+ if allowedToNotReturnErr .ContainsCallExpr (callExpr , ctx ) != nil {
64
+ continue
65
+ }
66
+
67
+ pos := returnsError (callExpr , ctx )
68
+ if pos < 0 || pos >= len (stmt .Lhs ) {
69
+ return nil , nil
70
+ }
71
+ id , ok := stmt .Lhs [pos ].(* ast.Ident )
72
+ if ! ok {
73
+ // don't think this should ever happen
74
+ return gosec .NewIssue (ctx , n , r .ID (), "PANIC!" , r .Severity , r .Confidence ), nil
75
+ } else if ok && id .Name == "_" {
76
+ // error is just ignored!
77
+ return gosec .NewIssue (ctx , n , r .ID (), r .What , r .Severity , r .Confidence ), nil
75
78
}
79
+
80
+ // TODO: next line should check `id.Name != nil`,
81
+ // and the BlockStmt that follows should have a ReturnStmt
82
+ // that includes the id.Name
76
83
}
77
84
}
78
85
return nil , nil
79
86
}
80
87
88
+ var allowedToNotReturnErr gosec.CallList
89
+
90
+ func init () {
91
+ allowedToNotReturnErr = gosec .NewCallList ()
92
+ allowedToNotReturnErr .AddAll ("bytes.Buffer" , "Write" , "WriteByte" , "WriteRune" , "WriteString" )
93
+ allowedToNotReturnErr .AddAll ("fmt" , "Print" , "Printf" , "Println" , "Fprint" , "Fprintf" , "Fprintln" )
94
+ allowedToNotReturnErr .AddAll ("strings.Builder" , "Write" , "WriteByte" , "WriteRune" , "WriteString" )
95
+ allowedToNotReturnErr .Add ("io.PipeWriter" , "CloseWithError" )
96
+ allowedToNotReturnErr .Add ("hash.Hash" , "Write" )
97
+ allowedToNotReturnErr .AddAll ("github.com/spf13/pflag.FlagSet" , "GetBool" , "GetString" , "GetUint32" , "GetBool" , "GetInt64" , "GetUint64" )
98
+ }
99
+
81
100
// NewErrorNotPropagated detects if a returned error is not propagated up the stack.
82
101
func NewErrorNotPropagated (id string , conf gosec.Config ) (gosec.Rule , []ast.Node ) {
83
-
84
102
return & noErrorCheck {
85
103
MetaData : gosec.MetaData {
86
104
ID : id ,
0 commit comments