@@ -112,7 +112,7 @@ This query finds the argument passed in each call to ``File::create``:
112
112
113
113
from CallExpr call
114
114
where call.getStaticTarget().(Function).getCanonicalPath() = "<std::fs::File>::create"
115
- select call.getArg(0)
115
+ select call.getArgList(). getArg(0)
116
116
117
117
Unfortunately this will only give the expression in the argument, not the values which could be passed to it.
118
118
So we use local data flow to find all expressions that flow into the argument:
@@ -125,7 +125,7 @@ So we use local data flow to find all expressions that flow into the argument:
125
125
from CallExpr call, DataFlow::ExprNode source, DataFlow::ExprNode sink
126
126
where
127
127
call.getStaticTarget().(Function).getCanonicalPath() = "<std::fs::File>::create" and
128
- sink.asExpr().getExpr() = call.getArg(0) and
128
+ sink.asExpr().getExpr() = call.getArgList(). getArg(0) and
129
129
DataFlow::localFlow(source, sink)
130
130
select source, sink
131
131
@@ -136,30 +136,12 @@ We can vary the source, for example, making the source the parameter of a functi
136
136
import rust
137
137
import codeql.rust.dataflow.DataFlow
138
138
139
- from CallExpr call, Method method, ParamDecl sourceParam, Expr sinkExpr
139
+ from CallExpr call, DataFlow::ParameterNode source, DataFlow::ExprNode sink
140
140
where
141
- call.getStaticTarget() = method and
142
- method.hasQualifiedName("String", "init(format:_:)") and
143
- sinkExpr = call.getArgument(0).getExpr() and
144
- DataFlow::localFlow(DataFlow::parameterNode(sourceParam), DataFlow::exprNode(sinkExpr))
145
- select sourceParam, sinkExpr
146
-
147
- The following example finds calls to ``String.init(format:_:) `` where the format string is not a hard-coded string literal:
148
-
149
- .. code-block :: ql
150
-
151
- import rust
152
- import codeql.rust.dataflow.DataFlow
153
-
154
- from CallExpr call, Method method, DataFlow::Node sinkNode
155
- where
156
- call.getStaticTarget() = method and
157
- method.hasQualifiedName("String", "init(format:_:)") and
158
- sinkNode.asExpr() = call.getArgument(0).getExpr() and
159
- not exists(StringLiteralExpr sourceLiteral |
160
- DataFlow::localFlow(DataFlow::exprNode(sourceLiteral), sinkNode)
161
- )
162
- select call, "Format argument to " + method.getName() + " isn't hard-coded."
141
+ call.getStaticTarget().(Function).getCanonicalPath() = "<std::fs::File>::create" and
142
+ sink.asExpr().getExpr() = call.getArgList().getArg(0) and
143
+ DataFlow::localFlow(source, sink)
144
+ select source, sink
163
145
164
146
Global data flow
165
147
----------------
@@ -242,53 +224,29 @@ The following global taint-tracking query finds places where a string literal is
242
224
243
225
.. code-block :: ql
244
226
245
- import rust
246
- import codeql.rust.dataflow.DataFlow
247
- import codeql.rust.dataflow.TaintTracking
248
-
249
- module ConstantPasswordConfig implements DataFlow::ConfigSig {
250
- predicate isSource(DataFlow::Node node) { node.asExpr() instanceof StringLiteralExpr }
251
-
252
- predicate isSink(DataFlow::Node node) {
253
- // any argument called `password`
254
- exists(CallExpr call | call.getArgumentWithLabel("password").getExpr() = node.asExpr())
255
- }
256
-
257
- module ConstantPasswordFlow = TaintTracking::Global<ConstantPasswordConfig>;
258
-
259
- from DataFlow::Node sourceNode, DataFlow::Node sinkNode
260
- where ConstantPasswordFlow::flow(sourceNode, sinkNode)
261
- select sinkNode, "The value $@ is used as a constant password.", sourceNode, sourceNode.toString()
262
-
263
-
264
- The following global taint-tracking query finds places where a value from a remote or local user input is used as an argument to the SQLite ``Connection.execute(_:) `` function.
265
- - Since this is a taint-tracking query, the ``TaintTracking::Global `` module is used.
266
- - The ``isSource `` predicate defines sources as a ``FlowSource `` (remote or local user input).
267
- - The ``isSink `` predicate defines sinks as the first argument in any call to ``Connection.execute(_:) ``.
268
-
269
- .. code-block :: ql
227
+ import rust
228
+ import codeql.rust.dataflow.DataFlow
229
+ import codeql.rust.dataflow.TaintTracking
270
230
271
- import rust
272
- import codeql.rust.dataflow.DataFlow
273
- import codeql.rust.dataflow.TaintTracking
274
- import codeql.rust.dataflow.FlowSources
231
+ module ConstantPasswordConfig implements DataFlow::ConfigSig {
232
+ predicate isSource(DataFlow::Node node) { node.asExpr().getExpr() instanceof StringLiteralExpr }
275
233
276
- module SqlInjectionConfig implements DataFlow::ConfigSig {
277
- predicate isSource(DataFlow::Node node) { node instanceof FlowSource }
234
+ predicate isSink(DataFlow::Node node) {
235
+ // any argument going to a parameter called `password`
236
+ exists(Function f, CallExpr call, int index |
237
+ call.getArgList().getArg(index) = node.asExpr().getExpr() and
238
+ call.getStaticTarget() = f and
239
+ f.getParamList().getParam(index).getPat().(IdentPat).getName().getText() = "password"
240
+ )
241
+ }
242
+ }
278
243
279
- predicate isSink(DataFlow::Node node) {
280
- exists(CallExpr call |
281
- call.getStaticTarget().(Method).hasQualifiedName("Connection", "execute(_:)") and
282
- call.getArgument(0).getExpr() = node.asExpr()
283
- )
284
- }
285
- }
244
+ module ConstantPasswordFlow = TaintTracking::Global<ConstantPasswordConfig>;
286
245
287
- module SqlInjectionFlow = TaintTracking::Global<SqlInjectionConfig>;
246
+ from DataFlow::Node sourceNode, DataFlow::Node sinkNode
247
+ where ConstantPasswordFlow::flow(sourceNode, sinkNode)
248
+ select sinkNode, "The value $@ is used as a constant password.", sourceNode, sourceNode.toString()
288
249
289
- from DataFlow::Node sourceNode, DataFlow::Node sinkNode
290
- where SqlInjectionFlow::flow(sourceNode, sinkNode)
291
- select sinkNode, "This query depends on a $@.", sourceNode, "user-provided value"
292
250
293
251
Further reading
294
252
---------------
0 commit comments