Skip to content

Commit 84cd02c

Browse files
committed
JS: Type track pg model
1 parent f7771f1 commit 84cd02c

File tree

4 files changed

+54
-30
lines changed

4 files changed

+54
-30
lines changed

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

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -123,47 +123,64 @@ private module MySql {
123123
* Provides classes modelling the `pg` package.
124124
*/
125125
private module Postgres {
126-
/** Gets an expression of the form `new require('pg').Client()`. */
127-
DataFlow::SourceNode newClient() {
128-
result = DataFlow::moduleImport("pg").getAConstructorInvocation("Client")
129-
}
130-
131-
/** Gets a data flow node that holds a freshly created Postgres client instance. */
132-
DataFlow::SourceNode client() {
133-
result = newClient()
134-
or
135-
// pool.connect(function(err, client) { ... })
136-
result = newPool().getAMethodCall("connect").getCallback(0).getParameter(1)
137-
}
138-
139126
/** Gets an expression that constructs a new connection pool. */
140-
DataFlow::SourceNode newPool() {
127+
DataFlow::InvokeNode newPool() {
141128
// new require('pg').Pool()
142129
result = DataFlow::moduleImport("pg").getAConstructorInvocation("Pool")
143130
or
144131
// new require('pg-pool')
145132
result = DataFlow::moduleImport("pg-pool").getAnInstantiation()
146133
}
147134

148-
private DataFlow::SourceNode clientOrPool(DataFlow::TypeTracker t) {
135+
/** Gets a data flow node referring to a connection pool. */
136+
private DataFlow::SourceNode pool(DataFlow::TypeTracker t) {
149137
t.start() and
150-
(result = client() or result = newPool())
138+
result = newPool()
139+
or
140+
exists(DataFlow::TypeTracker t2 |
141+
result = pool(t2).track(t2, t)
142+
)
143+
}
144+
145+
/** Gets a data flow node referring to a connection pool. */
146+
DataFlow::SourceNode pool() {
147+
result = pool(DataFlow::TypeTracker::end())
148+
}
149+
150+
/** Gets a creation of a Postgres client. */
151+
DataFlow::InvokeNode newClient() {
152+
result = DataFlow::moduleImport("pg").getAConstructorInvocation("Client")
153+
}
154+
155+
/** Gets a data flow node referring to a Postgres client. */
156+
private DataFlow::SourceNode client(DataFlow::TypeTracker t) {
157+
t.start() and
158+
(
159+
result = newClient()
160+
or
161+
result = pool().getAMethodCall("connect").getABoundCallbackParameter(0, 1)
162+
)
151163
or
152-
exists(DataFlow::TypeTracker t2 | result = clientOrPool(t2).track(t2, t))
164+
exists(DataFlow::TypeTracker t2 |
165+
result = client(t2).track(t2, t)
166+
)
167+
}
168+
169+
/** Gets a data flow node referring to a Postgres client. */
170+
DataFlow::SourceNode client() {
171+
result = client(DataFlow::TypeTracker::end())
153172
}
154173

155174
private DataFlow::SourceNode clientOrPool() {
156-
result = clientOrPool(DataFlow::TypeTracker::end())
175+
result = client() or result = pool()
157176
}
158177

159178
/** A call to the Postgres `query` method. */
160-
private class QueryCall extends DatabaseAccess, DataFlow::ValueNode {
161-
override MethodCallExpr astNode;
162-
179+
private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode {
163180
QueryCall() { this = clientOrPool().getAMethodCall("query") }
164181

165182
override DataFlow::Node getAQueryArgument() {
166-
result = DataFlow::valueNode(astNode.getArgument(0))
183+
result = getArgument(0)
167184
}
168185
}
169186

@@ -177,14 +194,12 @@ private module Postgres {
177194
string kind;
178195

179196
Credentials() {
180-
exists(DataFlow::InvokeNode call, string prop |
181-
(call = newClient() or call = newPool()) and
182-
this = call.getOptionArgument(0, prop).asExpr() and
183-
(
184-
prop = "user" and kind = "user name"
185-
or
186-
prop = "password" and kind = prop
187-
)
197+
exists(string prop |
198+
this = [newClient(), newPool()].getOptionArgument(0, prop).asExpr()
199+
|
200+
prop = "user" and kind = "user name"
201+
or
202+
prop = "password" and kind = prop
188203
)
189204
}
190205

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
| postgres2.js:30:16:30:41 | 'SELECT ... number' |
1515
| postgres3.js:15:16:15:40 | 'SELECT ... s name' |
1616
| postgres5.js:8:21:8:25 | query |
17+
| postgresImport.js:4:18:4:43 | 'SELECT ... number' |
1718
| sequelize2.js:10:17:10:118 | 'SELECT ... Y name' |
1819
| sequelize.js:8:17:8:118 | 'SELECT ... Y name' |
1920
| sequelizeImport.js:3:17:3:118 | 'SELECT ... Y name' |

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,5 @@ module.exports.query = function (text, values, callback) {
3636
console.log('query:', text, values);
3737
return pool.query(text, values, callback);
3838
};
39+
40+
module.exports.pool = pool;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
const { pool } = require("./postgres1");
2+
3+
pool.connect((err, client, done) => {
4+
client.query('SELECT $1::int AS number', ['1'], function(err, result) {
5+
});
6+
});

0 commit comments

Comments
 (0)