15
15
package rules
16
16
17
17
import (
18
+ "fmt"
18
19
"go/ast"
19
20
"regexp"
20
- "strings"
21
21
22
22
"github.com/securego/gosec/v2"
23
23
)
@@ -30,6 +30,51 @@ type sqlStatement struct {
30
30
patterns []* regexp.Regexp
31
31
}
32
32
33
+ var sqlCallIdents = map [string ]map [string ]int {
34
+ "*database/sql.DB" : {
35
+ "Exec" : 0 ,
36
+ "ExecContext" : 1 ,
37
+ "Query" : 0 ,
38
+ "QueryContext" : 1 ,
39
+ "QueryRow" : 0 ,
40
+ "QueryRowContext" : 1 ,
41
+ "Prepare" : 0 ,
42
+ "PrepareContext" : 1 ,
43
+ },
44
+ "*database/sql.Tx" : {
45
+ "Exec" : 0 ,
46
+ "ExecContext" : 1 ,
47
+ "Query" : 0 ,
48
+ "QueryContext" : 1 ,
49
+ "QueryRow" : 0 ,
50
+ "QueryRowContext" : 1 ,
51
+ "Prepare" : 0 ,
52
+ "PrepareContext" : 1 ,
53
+ },
54
+ }
55
+
56
+ // findQueryArg locates the argument taking raw SQL
57
+ func findQueryArg (call * ast.CallExpr , ctx * gosec.Context ) (ast.Expr , error ) {
58
+ typeName , fnName , err := gosec .GetCallInfo (call , ctx )
59
+ if err != nil {
60
+ return nil , err
61
+ }
62
+ i := - 1
63
+ if ni , ok := sqlCallIdents [typeName ]; ok {
64
+ if i , ok = ni [fnName ]; ! ok {
65
+ i = - 1
66
+ }
67
+ }
68
+ if i == - 1 {
69
+ return nil , fmt .Errorf ("SQL argument index not found for %s.%s" , typeName , fnName )
70
+ }
71
+ if i >= len (call .Args ) {
72
+ return nil , nil
73
+ }
74
+ query := call .Args [i ]
75
+ return query , nil
76
+ }
77
+
33
78
func (s * sqlStatement ) ID () string {
34
79
return s .MetaData .ID
35
80
}
@@ -69,16 +114,10 @@ func (s *sqlStrConcat) checkObject(n *ast.Ident, c *gosec.Context) bool {
69
114
70
115
// checkQuery verifies if the query parameters is a string concatenation
71
116
func (s * sqlStrConcat ) checkQuery (call * ast.CallExpr , ctx * gosec.Context ) (* gosec.Issue , error ) {
72
- _ , fnName , err := gosec . GetCallInfo (call , ctx )
117
+ query , err := findQueryArg (call , ctx )
73
118
if err != nil {
74
119
return nil , err
75
120
}
76
- var query ast.Node
77
- if strings .HasSuffix (fnName , "Context" ) {
78
- query = call .Args [1 ]
79
- } else {
80
- query = call .Args [0 ]
81
- }
82
121
83
122
if be , ok := query .(* ast.BinaryExpr ); ok {
84
123
operands := gosec .GetBinaryExprOperands (be )
@@ -137,8 +176,11 @@ func NewSQLStrConcat(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
137
176
},
138
177
}
139
178
140
- rule .AddAll ("*database/sql.DB" , "Query" , "QueryContext" , "QueryRow" , "QueryRowContext" , "Exec" , "ExecContext" , "Prepare" , "PrepareContext" )
141
- rule .AddAll ("*database/sql.Tx" , "Query" , "QueryContext" , "QueryRow" , "QueryRowContext" , "Exec" , "ExecContext" , "Prepare" , "PrepareContext" )
179
+ for s , si := range sqlCallIdents {
180
+ for i := range si {
181
+ rule .Add (s , i )
182
+ }
183
+ }
142
184
return rule , []ast.Node {(* ast .AssignStmt )(nil ), (* ast .ExprStmt )(nil )}
143
185
}
144
186
@@ -171,16 +213,10 @@ func (s *sqlStrFormat) constObject(e ast.Expr, c *gosec.Context) bool {
171
213
}
172
214
173
215
func (s * sqlStrFormat ) checkQuery (call * ast.CallExpr , ctx * gosec.Context ) (* gosec.Issue , error ) {
174
- _ , fnName , err := gosec . GetCallInfo (call , ctx )
216
+ query , err := findQueryArg (call , ctx )
175
217
if err != nil {
176
218
return nil , err
177
219
}
178
- var query ast.Node
179
- if strings .HasSuffix (fnName , "Context" ) {
180
- query = call .Args [1 ]
181
- } else {
182
- query = call .Args [0 ]
183
- }
184
220
185
221
if ident , ok := query .(* ast.Ident ); ok && ident .Obj != nil {
186
222
decl := ident .Obj .Decl
@@ -306,8 +342,11 @@ func NewSQLStrFormat(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
306
342
},
307
343
},
308
344
}
309
- rule .AddAll ("*database/sql.DB" , "Query" , "QueryContext" , "QueryRow" , "QueryRowContext" , "Exec" , "ExecContext" , "Prepare" , "PrepareContext" )
310
- rule .AddAll ("*database/sql.Tx" , "Query" , "QueryContext" , "QueryRow" , "QueryRowContext" , "Exec" , "ExecContext" , "Prepare" , "PrepareContext" )
345
+ for s , si := range sqlCallIdents {
346
+ for i := range si {
347
+ rule .Add (s , i )
348
+ }
349
+ }
311
350
rule .fmtCalls .AddAll ("fmt" , "Sprint" , "Sprintf" , "Sprintln" , "Fprintf" )
312
351
rule .noIssue .AddAll ("os" , "Stdout" , "Stderr" )
313
352
rule .noIssueQuoted .Add ("github.com/lib/pq" , "QuoteIdentifier" )
0 commit comments