Skip to content

Commit af15eba

Browse files
authored
Merge pull request #18426 from egregius313/egregius313/go/mad/database/sqlx
Go: Add `database` source models for the `jmoiron/sqlx` package
2 parents 5cc34a1 + 8e4939e commit af15eba

File tree

13 files changed

+729
-1
lines changed

13 files changed

+729
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* `database` local source models have been added for the `github.com/jmoiron/sqlx` package.

go/ql/lib/ext/github.com.jmoiron.sqlx.model.yml

+68
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,57 @@
11
extensions:
2+
- addsTo:
3+
pack: codeql/go-all
4+
extensible: sourceModel
5+
data:
6+
- ["github.com/jmoiron/sqlx", "", True, "Get", "", "", "Argument[1]", "database", "manual"]
7+
- ["github.com/jmoiron/sqlx", "", True, "GetContext", "", "", "Argument[2]", "database", "manual"]
8+
- ["github.com/jmoiron/sqlx", "", True, "NamedQuery", "", "", "ReturnValue[0]", "database", "manual"]
9+
- ["github.com/jmoiron/sqlx", "", True, "NamedQueryContext", "", "", "ReturnValue[0]", "database", "manual"]
10+
- ["github.com/jmoiron/sqlx", "", True, "Select", "", "", "Argument[1]", "database", "manual"]
11+
- ["github.com/jmoiron/sqlx", "", True, "SelectContext", "", "", "Argument[2]", "database", "manual"]
12+
- ["github.com/jmoiron/sqlx", "Conn", True, "GetContext", "", "", "Argument[1]", "database", "manual"]
13+
- ["github.com/jmoiron/sqlx", "Conn", True, "QueryRowxContext", "", "", "ReturnValue", "database", "manual"]
14+
- ["github.com/jmoiron/sqlx", "Conn", True, "QueryxContext", "", "", "ReturnValue[0]", "database", "manual"]
15+
- ["github.com/jmoiron/sqlx", "Conn", True, "SelectContext", "", "", "Argument[1]", "database", "manual"]
16+
- ["github.com/jmoiron/sqlx", "DB", True, "Get", "", "", "Argument[0]", "database", "manual"]
17+
- ["github.com/jmoiron/sqlx", "DB", True, "GetContext", "", "", "Argument[1]", "database", "manual"]
18+
- ["github.com/jmoiron/sqlx", "DB", True, "NamedQuery", "", "", "ReturnValue[0]", "database", "manual"]
19+
- ["github.com/jmoiron/sqlx", "DB", True, "NamedQueryContext", "", "", "ReturnValue[0]", "database", "manual"]
20+
- ["github.com/jmoiron/sqlx", "DB", True, "QueryRowx", "", "", "ReturnValue[0]", "database", "manual"]
21+
- ["github.com/jmoiron/sqlx", "DB", True, "QueryRowxContext", "", "", "ReturnValue[0]", "database", "manual"]
22+
- ["github.com/jmoiron/sqlx", "DB", True, "Queryx", "", "", "ReturnValue[0]", "database", "manual"]
23+
- ["github.com/jmoiron/sqlx", "DB", True, "QueryxContext", "", "", "ReturnValue[0]", "database", "manual"]
24+
- ["github.com/jmoiron/sqlx", "DB", True, "Select", "", "", "Argument[0]", "database", "manual"]
25+
- ["github.com/jmoiron/sqlx", "DB", True, "SelectContext", "", "", "Argument[1]", "database", "manual"]
26+
- ["github.com/jmoiron/sqlx", "NamedStmt", True, "Get", "", "", "Argument[0]", "database", "manual"]
27+
- ["github.com/jmoiron/sqlx", "NamedStmt", True, "GetContext", "", "", "Argument[1]", "database", "manual"]
28+
- ["github.com/jmoiron/sqlx", "NamedStmt", True, "QueryRow", "", "", "ReturnValue[0]", "database", "manual"]
29+
- ["github.com/jmoiron/sqlx", "NamedStmt", True, "QueryRowContext", "", "", "ReturnValue[0]", "database", "manual"]
30+
- ["github.com/jmoiron/sqlx", "NamedStmt", True, "Query", "", "", "ReturnValue[0]", "database", "manual"]
31+
- ["github.com/jmoiron/sqlx", "NamedStmt", True, "QueryContext", "", "", "ReturnValue[0]", "database", "manual"]
32+
- ["github.com/jmoiron/sqlx", "NamedStmt", True, "QueryRowx", "", "", "ReturnValue[0]", "database", "manual"]
33+
- ["github.com/jmoiron/sqlx", "NamedStmt", True, "QueryRowxContext", "", "", "ReturnValue[0]", "database", "manual"]
34+
- ["github.com/jmoiron/sqlx", "NamedStmt", True, "Queryx", "", "", "ReturnValue[0]", "database", "manual"]
35+
- ["github.com/jmoiron/sqlx", "NamedStmt", True, "QueryxContext", "", "", "ReturnValue[0]", "database", "manual"]
36+
- ["github.com/jmoiron/sqlx", "NamedStmt", True, "Select", "", "", "Argument[0]", "database", "manual"]
37+
- ["github.com/jmoiron/sqlx", "NamedStmt", True, "SelectContext", "", "", "Argument[1]", "database", "manual"]
38+
- ["github.com/jmoiron/sqlx", "Stmt", True, "Get", "", "", "Argument[0]", "database", "manual"]
39+
- ["github.com/jmoiron/sqlx", "Stmt", True, "GetContext", "", "", "Argument[1]", "database", "manual"]
40+
- ["github.com/jmoiron/sqlx", "Stmt", True, "QueryRowx", "", "", "ReturnValue[0]", "database", "manual"]
41+
- ["github.com/jmoiron/sqlx", "Stmt", True, "QueryRowxContext", "", "", "ReturnValue[0]", "database", "manual"]
42+
- ["github.com/jmoiron/sqlx", "Stmt", True, "Queryx", "", "", "ReturnValue[0]", "database", "manual"]
43+
- ["github.com/jmoiron/sqlx", "Stmt", True, "QueryxContext", "", "", "ReturnValue[0]", "database", "manual"]
44+
- ["github.com/jmoiron/sqlx", "Stmt", True, "Select", "", "", "Argument[0]", "database", "manual"]
45+
- ["github.com/jmoiron/sqlx", "Stmt", True, "SelectContext", "", "", "Argument[1]", "database", "manual"]
46+
- ["github.com/jmoiron/sqlx", "Tx", True, "Get", "", "", "Argument[0]", "database", "manual"]
47+
- ["github.com/jmoiron/sqlx", "Tx", True, "GetContext", "", "", "Argument[1]", "database", "manual"]
48+
- ["github.com/jmoiron/sqlx", "Tx", True, "NamedQuery", "", "", "ReturnValue[0]", "database", "manual"]
49+
- ["github.com/jmoiron/sqlx", "Tx", True, "QueryRowx", "", "", "ReturnValue[0]", "database", "manual"]
50+
- ["github.com/jmoiron/sqlx", "Tx", True, "QueryRowxContext", "", "", "ReturnValue[0]", "database", "manual"]
51+
- ["github.com/jmoiron/sqlx", "Tx", True, "Queryx", "", "", "ReturnValue[0]", "database", "manual"]
52+
- ["github.com/jmoiron/sqlx", "Tx", True, "QueryxContext", "", "", "ReturnValue[0]", "database", "manual"]
53+
- ["github.com/jmoiron/sqlx", "Tx", True, "Select", "", "", "Argument[0]", "database", "manual"]
54+
- ["github.com/jmoiron/sqlx", "Tx", True, "SelectContext", "", "", "Argument[1]", "database", "manual"]
255
- addsTo:
356
pack: codeql/go-all
457
extensible: sinkModel
@@ -15,3 +68,18 @@ extensions:
1568
- ["github.com/jmoiron/sqlx", "Tx", True, "NamedQuery", "", "", "Argument[0]", "sql-injection", "manual"]
1669
- ["github.com/jmoiron/sqlx", "Tx", True, "Queryx", "", "", "Argument[0]", "sql-injection", "manual"]
1770
- ["github.com/jmoiron/sqlx", "Tx", True, "Select", "", "", "Argument[1]", "sql-injection", "manual"]
71+
- addsTo:
72+
pack: codeql/go-all
73+
extensible: summaryModel
74+
data:
75+
- ["github.com/jmoiron/sqlx", "", True, "MapScan", "", "", "Argument[0]", "Argument[1]", "taint", "manual"]
76+
- ["github.com/jmoiron/sqlx", "", True, "SliceScan", "", "", "Argument[0]", "ReturnValue[0]", "taint", "manual"]
77+
- ["github.com/jmoiron/sqlx", "", True, "StructScan", "", "", "Argument[0]", "Argument[1]", "taint", "manual"]
78+
- ["github.com/jmoiron/sqlx", "ColScanner", True, "Scan", "", "", "Argument[receiver]", "Argument[0]", "taint", "manual"]
79+
- ["github.com/jmoiron/sqlx", "Row", True, "MapScan", "", "", "Argument[receiver]", "Argument[0]", "taint", "manual"]
80+
- ["github.com/jmoiron/sqlx", "Row", True, "Scan", "", "", "Argument[receiver]", "Argument[0]", "taint", "manual"]
81+
- ["github.com/jmoiron/sqlx", "Row", True, "SliceScan", "", "", "Argument[receiver]", "ReturnValue[0]", "taint", "manual"]
82+
- ["github.com/jmoiron/sqlx", "Row", True, "StructScan", "", "", "Argument[receiver]", "Argument[0]", "taint", "manual"]
83+
- ["github.com/jmoiron/sqlx", "Rows", True, "MapScan", "", "", "Argument[receiver]", "Argument[0]", "taint", "manual"]
84+
- ["github.com/jmoiron/sqlx", "Rows", True, "SliceScan", "", "", "Argument[receiver]", "ReturnValue[0]", "taint", "manual"]
85+
- ["github.com/jmoiron/sqlx", "Rows", True, "StructScan", "", "", "Argument[receiver]", "Argument[0]", "taint", "manual"]

go/ql/test/library-tests/semmle/go/dataflow/flowsources/local/database/go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ go 1.22.5
44

55
require (
66
gorm.io/gorm v1.23.0
7+
github.com/jmoiron/sqlx v1.4.0
78
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
package test
2+
3+
import (
4+
"context"
5+
6+
"github.com/jmoiron/sqlx"
7+
)
8+
9+
func test_sqlx(q sqlx.Ext) {
10+
var user User
11+
12+
err := sqlx.Get(q, &user, "SELECT * FROM users WHERE id = 1") // $ source
13+
ignore(err)
14+
15+
err = sqlx.Select(q, &user, "SELECT * FROM users WHERE id = 1") // $ source
16+
ignore(err)
17+
18+
rows, err := sqlx.NamedQuery(q, "SELECT * FROM users WHERE id = :id", map[string]any{"id": 1}) // $ source
19+
ignore(err)
20+
21+
var user2 User
22+
23+
rows.StructScan(&user2)
24+
25+
sink(user2) // $ hasTaintFlow="user2"
26+
}
27+
28+
func test_sqlx_ctx(ctx context.Context, q sqlx.ExtContext) {
29+
var user User
30+
31+
err := sqlx.GetContext(ctx, q, &user, "SELECT * FROM users WHERE id = 1") // $ source
32+
ignore(err)
33+
34+
err = sqlx.SelectContext(ctx, q, &user, "SELECT * FROM users WHERE id = 1") // $ source
35+
ignore(err)
36+
37+
rows, err := sqlx.NamedQueryContext(ctx, q, "SELECT * FROM users WHERE id = :id", map[string]any{"id": 1}) // $ source
38+
ignore(err)
39+
40+
var user2 User
41+
42+
rows.StructScan(&user2)
43+
44+
sink(user2) // $ hasTaintFlow="user2"
45+
}
46+
47+
func test_sqlx_Conn(conn *sqlx.Conn) {
48+
var user User
49+
conn.GetContext(nil, &user, "SELECT * FROM users WHERE id = 1") // $ source
50+
51+
var user2 User
52+
conn.SelectContext(nil, &user2, "SELECT * FROM users WHERE id = 1") // $ source
53+
54+
row := conn.QueryRowxContext(nil, "SELECT * FROM users WHERE id = 1") // $ source
55+
56+
userMap := make(map[string]interface{})
57+
row.MapScan(userMap)
58+
id := userMap["id"].(int)
59+
sink(id) // $ hasTaintFlow="id"
60+
61+
rows, err := conn.QueryxContext(nil, "SELECT * FROM users WHERE id = 1") // $ source
62+
ignore(err)
63+
64+
for rows.Next() {
65+
var id int
66+
var name string
67+
err = rows.Scan(&id, &name)
68+
69+
if err != nil {
70+
return
71+
}
72+
73+
sink(id, name) // $ hasTaintFlow="id" hasTaintFlow="name"
74+
}
75+
}
76+
77+
func test_sqlx_DB(db *sqlx.DB) {
78+
example, err := db.Query("SELECT * FROM users") // $ source
79+
ignore(example, err)
80+
81+
rows, err := db.Queryx("SELECT * FROM users") // $ source
82+
83+
if err != nil {
84+
return
85+
}
86+
87+
defer rows.Close()
88+
89+
for rows.Next() {
90+
var id int
91+
var name string
92+
err = rows.Scan(&id, &name)
93+
94+
if err != nil {
95+
return
96+
}
97+
98+
sink(id, name) // $ hasTaintFlow="id" hasTaintFlow="name"
99+
100+
valmap := make(map[string]interface{})
101+
rows.MapScan(valmap)
102+
103+
id = valmap["id"].(int)
104+
sink(id) // $ hasTaintFlow="id"
105+
106+
var user User
107+
rows.StructScan(&user)
108+
sink(user) // $ hasTaintFlow="user"
109+
}
110+
111+
row := db.QueryRowx("SELECT * FROM users WHERE id = 1") // $ source
112+
113+
userMap := make(map[string]interface{})
114+
row.MapScan(userMap)
115+
116+
id := userMap["id"].(int)
117+
sink(id) // $ hasTaintFlow="id"
118+
119+
var user User
120+
row.StructScan(&user)
121+
sink(user) // $ hasTaintFlow="user"
122+
123+
var user2 User
124+
db.Get(&user2, "SELECT * FROM users WHERE id = 1") // $ source
125+
126+
var user3 User
127+
db.GetContext(nil, &user3, "SELECT * FROM users WHERE id = 1") // $ source
128+
129+
var user4 User
130+
rows, err = db.NamedQueryContext(nil, "SELECT * FROM users WHERE id = :id", map[string]any{"id": 1}) // $ source
131+
ignore(err)
132+
rows.StructScan(&user4)
133+
sink(user4) // $ hasTaintFlow="user4"
134+
135+
var user5 User
136+
db.Select(&user5, "SELECT * FROM users WHERE id = 1") // $ source
137+
}
138+
139+
func test_sqlx_NamedStmt(stmt *sqlx.NamedStmt) {
140+
example, err := stmt.Query("SELECT * FROM users") // $ source
141+
ignore(example, err)
142+
143+
rows, err := stmt.Queryx("SELECT * FROM users") // $ source
144+
145+
if err != nil {
146+
return
147+
}
148+
149+
defer rows.Close()
150+
151+
for rows.Next() {
152+
var id int
153+
var name string
154+
err = rows.Scan(&id, &name)
155+
156+
if err != nil {
157+
return
158+
}
159+
160+
sink(id, name) // $ hasTaintFlow="id" hasTaintFlow="name"
161+
162+
valmap := make(map[string]interface{})
163+
rows.MapScan(valmap)
164+
165+
id = valmap["id"].(int)
166+
sink(id) // $ hasTaintFlow="id"
167+
168+
var user User
169+
rows.StructScan(&user)
170+
sink(user) // $ hasTaintFlow="user"
171+
}
172+
173+
row := stmt.QueryRowx("SELECT * FROM users WHERE id = 1") // $ source
174+
175+
userMap := make(map[string]interface{})
176+
row.MapScan(userMap)
177+
178+
id := userMap["id"].(int)
179+
sink(id) // $ hasTaintFlow="id"
180+
181+
var user User
182+
row.StructScan(&user)
183+
sink(user) // $ hasTaintFlow="user"
184+
185+
var user2 User
186+
stmt.Get(&user2, "SELECT * FROM users WHERE id = 1") // $ source
187+
188+
var user3 User
189+
stmt.GetContext(nil, &user3, "SELECT * FROM users WHERE id = 1") // $ source
190+
191+
var user4 User
192+
stmt.Select(&user4, "SELECT * FROM users WHERE id = 1") // $ source
193+
}
194+
195+
func test_sqlx_Stmt(stmt *sqlx.Stmt) {
196+
example, err := stmt.Query("SELECT * FROM users") // $ source
197+
ignore(example, err)
198+
199+
rows, err := stmt.Queryx("SELECT * FROM users") // $ source
200+
201+
if err != nil {
202+
return
203+
}
204+
205+
defer rows.Close()
206+
207+
for rows.Next() {
208+
var id int
209+
var name string
210+
err = rows.Scan(&id, &name)
211+
212+
if err != nil {
213+
return
214+
}
215+
216+
sink(id, name) // $ hasTaintFlow="id" hasTaintFlow="name"
217+
218+
valmap := make(map[string]interface{})
219+
rows.MapScan(valmap)
220+
221+
id = valmap["id"].(int)
222+
sink(id) // $ hasTaintFlow="id"
223+
224+
var user User
225+
rows.StructScan(&user)
226+
sink(user) // $ hasTaintFlow="user"
227+
}
228+
229+
row := stmt.QueryRowx("SELECT * FROM users WHERE id = 1") // $ source
230+
231+
userMap := make(map[string]interface{})
232+
row.MapScan(userMap)
233+
234+
id := userMap["id"].(int)
235+
sink(id) // $ hasTaintFlow="id"
236+
237+
var user User
238+
row.StructScan(&user)
239+
sink(user) // $ hasTaintFlow="user"
240+
241+
var user2 User
242+
stmt.Get(&user2, "SELECT * FROM users WHERE id = 1") // $ source
243+
244+
var user3 User
245+
stmt.GetContext(nil, &user3, "SELECT * FROM users WHERE id = 1") // $ source
246+
247+
var user4 User
248+
stmt.Select(&user4, "SELECT * FROM users WHERE id = 1") // $ source
249+
}
250+
251+
func test_sqlx_Tx(tx *sqlx.Tx) {
252+
example, err := tx.Query("SELECT * FROM users") // $ source
253+
ignore(example, err)
254+
255+
rows, err := tx.Queryx("SELECT * FROM users") // $ source
256+
257+
if err != nil {
258+
return
259+
}
260+
261+
defer rows.Close()
262+
263+
for rows.Next() {
264+
var id int
265+
var name string
266+
err = rows.Scan(&id, &name)
267+
268+
if err != nil {
269+
return
270+
}
271+
272+
sink(id, name) // $ hasTaintFlow="id" hasTaintFlow="name"
273+
274+
valmap := make(map[string]interface{})
275+
rows.MapScan(valmap)
276+
277+
id = valmap["id"].(int)
278+
sink(id) // $ hasTaintFlow="id"
279+
280+
var user User
281+
rows.StructScan(&user)
282+
sink(user) // $ hasTaintFlow="user"
283+
}
284+
285+
row := tx.QueryRowx("SELECT * FROM users WHERE id = 1") // $ source
286+
287+
userMap := make(map[string]interface{})
288+
row.MapScan(userMap)
289+
290+
id := userMap["id"].(int)
291+
sink(id) // $ hasTaintFlow="id"
292+
293+
var user User
294+
row.StructScan(&user)
295+
sink(user) // $ hasTaintFlow="user"
296+
297+
var user2 User
298+
tx.Get(&user2, "SELECT * FROM users WHERE id = 1") // $ source
299+
300+
var user3 User
301+
tx.GetContext(nil, &user3, "SELECT * FROM users WHERE id = 1") // $ source
302+
303+
var user4 User
304+
rows, err = tx.NamedQuery("SELECT * FROM users WHERE id = :id", map[string]any{"id": 1}) // $ source
305+
ignore(err)
306+
rows.StructScan(&user4)
307+
sink(user4) // $ hasTaintFlow="user4"
308+
309+
var user5 User
310+
tx.Select(&user5, "SELECT * FROM users WHERE id = 1") // $ source
311+
}

0 commit comments

Comments
 (0)