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

Skip to content

Commit 3857331

Browse files
committed
avoid .getReturn().getAUse().(DataFlow::InvokeNode) in the SQL model
1 parent deae925 commit 3857331

3 files changed

Lines changed: 58 additions & 30 deletions

File tree

javascript/ql/src/semmle/javascript/frameworks/SQL.qll

Lines changed: 46 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,17 @@ private module MySql {
3131
/** Gets the package name `mysql` or `mysql2`. */
3232
API::Node mysql() { result = API::moduleImport(["mysql", "mysql2"]) }
3333

34+
/** Gets a reference to `mysql.createConnection`. */
35+
API::Node createConnectionCallee() { result = mysql().getMember("createConnection") }
36+
3437
/** Gets a call to `mysql.createConnection`. */
35-
API::Node createConnection() { result = mysql().getMember("createConnection").getReturn() }
38+
API::Node createConnection() { result = createConnectionCallee().getReturn() }
39+
40+
/** Gets a reference to `mysql.createPool`. */
41+
API::Node createPoolCallee() { result = mysql().getMember("createPool") }
3642

3743
/** Gets a call to `mysql.createPool`. */
38-
API::Node createPool() { result = mysql().getMember("createPool").getReturn() }
44+
API::Node createPool() { result = createPoolCallee().getReturn() }
3945

4046
/** Gets a data flow node that contains a freshly created MySQL connection instance. */
4147
API::Node connection() {
@@ -48,7 +54,7 @@ private module MySql {
4854
private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode {
4955
QueryCall() {
5056
exists(API::Node recv | recv = createPool() or recv = connection() |
51-
this = recv.getMember("query").getReturn().getAUse()
57+
this = recv.getMember("query").getASourceUse().getACall()
5258
)
5359
}
5460

@@ -66,8 +72,8 @@ private module MySql {
6672
this =
6773
[mysql(), createPool(), connection()]
6874
.getMember(["escape", "escapeId"])
69-
.getReturn()
70-
.getAUse()
75+
.getASourceUse()
76+
.getACall()
7177
.asExpr() and
7278
input = this.getArgument(0) and
7379
output = this
@@ -79,9 +85,9 @@ private module MySql {
7985
string kind;
8086

8187
Credentials() {
82-
exists(API::Node call, string prop |
83-
call in [createConnection(), createPool()] and
84-
call.getAUse().asExpr().(CallExpr).hasOptionArgument(0, prop, this) and
88+
exists(API::Node callee, string prop |
89+
callee in [createConnectionCallee(), createPoolCallee()] and
90+
this = callee.getParameter(0).getMember(prop).getARhs().asExpr() and
8591
(
8692
prop = "user" and kind = "user name"
8793
or
@@ -98,8 +104,11 @@ private module MySql {
98104
* Provides classes modelling the `pg` package.
99105
*/
100106
private module Postgres {
107+
/** Gets an expression of the form `require('pg').Client`. */
108+
API::Node newClientCallee() { result = API::moduleImport("pg").getMember("Client") }
109+
101110
/** Gets an expression of the form `new require('pg').Client()`. */
102-
API::Node newClient() { result = API::moduleImport("pg").getMember("Client").getInstance() }
111+
API::Node newClient() { result = newClientCallee().getInstance() }
103112

104113
/** Gets a data flow node that holds a freshly created Postgres client instance. */
105114
API::Node client() {
@@ -109,18 +118,21 @@ private module Postgres {
109118
result = newPool().getMember("connect").getParameter(0).getParameter(1)
110119
}
111120

112-
/** Gets an expression that constructs a new connection pool. */
113-
API::Node newPool() {
121+
/** Gets a constructor that when invoked constructs a new connection pool. */
122+
API::Node newPoolCallee() {
114123
// new require('pg').Pool()
115-
result = API::moduleImport("pg").getMember("Pool").getInstance()
124+
result = API::moduleImport("pg").getMember("Pool")
116125
or
117126
// new require('pg-pool')
118-
result = API::moduleImport("pg-pool").getInstance()
127+
result = API::moduleImport("pg-pool")
119128
}
120129

130+
/** Gets an expression that constructs a new connection pool. */
131+
API::Node newPool() { result = newPoolCallee().getInstance() }
132+
121133
/** A call to the Postgres `query` method. */
122134
private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode {
123-
QueryCall() { this = [client(), newPool()].getMember("query").getReturn().getAUse() }
135+
QueryCall() { this = [client(), newPool()].getMember("query").getASourceUse().getACall() }
124136

125137
override DataFlow::Node getAQueryArgument() { result = getArgument(0) }
126138
}
@@ -135,9 +147,9 @@ private module Postgres {
135147
string kind;
136148

137149
Credentials() {
138-
exists(DataFlow::InvokeNode call, string prop |
139-
call = [client(), newPool()].getAUse() and
140-
this = call.getOptionArgument(0, prop).asExpr() and
150+
exists(string prop |
151+
this =
152+
[newClientCallee(), newPoolCallee()].getParameter(0).getMember(prop).getARhs().asExpr() and
141153
(
142154
prop = "user" and kind = "user name"
143155
or
@@ -178,7 +190,7 @@ private module Sqlite {
178190
meth = "prepare" or
179191
meth = "run"
180192
|
181-
this = newDb().getMember(meth).getReturn().getAUse()
193+
this = newDb().getMember(meth).getASourceUse().getACall()
182194
)
183195
}
184196

@@ -222,7 +234,7 @@ private module MsSql {
222234

223235
/** A call to a MsSql query method. */
224236
private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode {
225-
QueryCall() { this = request().getMember(["query", "batch"]).getReturn().getAUse() }
237+
QueryCall() { this = request().getMember(["query", "batch"]).getASourceUse().getACall() }
226238

227239
override DataFlow::Node getAQueryArgument() { result = getArgument(0) }
228240
}
@@ -250,13 +262,13 @@ private module MsSql {
250262
string kind;
251263

252264
Credentials() {
253-
exists(DataFlow::InvokeNode call, string prop |
265+
exists(API::Node callee, string prop |
254266
(
255-
call = mssql().getMember("connect").getReturn().getAUse()
267+
callee = mssql().getMember("connect")
256268
or
257-
call = mssql().getMember("ConnectionPool").getInstance().getAUse()
269+
callee = mssql().getMember("ConnectionPool")
258270
) and
259-
this = call.getOptionArgument(0, prop).asExpr() and
271+
this = callee.getParameter(0).getMember(prop).getARhs().asExpr() and
260272
(
261273
prop = "user" and kind = "user name"
262274
or
@@ -281,7 +293,7 @@ private module Sequelize {
281293

282294
/** A call to `Sequelize.query`. */
283295
private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode {
284-
QueryCall() { this = newSequelize().getMember("query").getReturn().getAUse() }
296+
QueryCall() { this = newSequelize().getMember("query").getASourceUse().getACall() }
285297

286298
override DataFlow::Node getAQueryArgument() { result = getArgument(0) }
287299
}
@@ -300,7 +312,7 @@ private module Sequelize {
300312

301313
Credentials() {
302314
exists(NewExpr ne, string prop |
303-
ne = newSequelize().getAUse().asExpr() and
315+
ne = sequelize().getASourceUse().getAnInstantiation().asExpr() and
304316
(
305317
this = ne.getArgument(1) and prop = "username"
306318
or
@@ -379,7 +391,10 @@ private module Spanner {
379391
class DatabaseRunCall extends SqlExecution {
380392
DatabaseRunCall() {
381393
this =
382-
database().getMember(["run", "runPartitionedUpdate", "runStream"]).getReturn().getAUse()
394+
database()
395+
.getMember(["run", "runPartitionedUpdate", "runStream"])
396+
.getASourceUse()
397+
.getACall()
383398
}
384399
}
385400

@@ -388,7 +403,7 @@ private module Spanner {
388403
*/
389404
class TransactionRunCall extends SqlExecution {
390405
TransactionRunCall() {
391-
this = transaction().getMember(["run", "runStream", "runUpdate"]).getReturn().getAUse()
406+
this = transaction().getMember(["run", "runStream", "runUpdate"]).getASourceUse().getACall()
392407
}
393408
}
394409

@@ -398,7 +413,10 @@ private module Spanner {
398413
class ExecuteSqlCall extends SqlExecution {
399414
ExecuteSqlCall() {
400415
this =
401-
v1SpannerClient().getMember(["executeSql", "executeStreamingSql"]).getReturn().getAUse()
416+
v1SpannerClient()
417+
.getMember(["executeSql", "executeStreamingSql"])
418+
.getASourceUse()
419+
.getACall()
402420
}
403421

404422
override DataFlow::Node getAQueryArgument() {

javascript/ql/test/library-tests/frameworks/SQL/SqlString.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
| mssql2.js:5:15:5:34 | 'select 1 as number' |
44
| mssql2.js:13:15:13:66 | 'create ... table' |
55
| mssql2.js:22:24:22:43 | 'select 1 as number' |
6+
| mssql2.js:29:30:29:81 | 'create ... table' |
67
| mysql1.js:13:18:13:43 | 'SELECT ... lution' |
78
| mysql1.js:18:18:22:1 | {\\n s ... vid']\\n} |
89
| mysql1a.js:17:18:17:43 | 'SELECT ... lution' |

javascript/ql/test/library-tests/frameworks/SQL/mssql2.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Adapted from https://github.com/tediousjs/node-mssql#readme
22
const sql = require('mssql')
3-
3+
44
const request = new sql.Request()
55
request.query('select 1 as number', (err, result) => {
66
// ... error checks
@@ -19,7 +19,16 @@ class C {
1919
this.req = req;
2020
}
2121
send() {
22-
this.req.query('select 1 as number', (err, result) => {})
22+
this.req.query('select 1 as number', (err, result) => { })
2323
}
2424
}
2525
new C(new sql.Request());
26+
27+
var obj = {
28+
foo: function () {
29+
return request.batch('create procedure #temporary as select * from table', (err, result) => {
30+
// ... error checks
31+
})
32+
}
33+
}
34+
obj.foo("foo", "bar", "baz"); // A API-graphs gotcha.

0 commit comments

Comments
 (0)