Skip to content

Commit a6a4c1c

Browse files
committed
wip
1 parent 0a50f7e commit a6a4c1c

File tree

69 files changed

+1209
-715
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+1209
-715
lines changed

rust/ql/examples/snippets/simple_constant_password.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ module ConstantPasswordConfig implements DataFlow::ConfigSig {
3434
call.getStaticTarget() = target and
3535
v.getParameter() = target.getParam(argIndex) and
3636
v.getText().matches("pass%") and
37-
call.getArg(argIndex) = node.asExpr()
37+
call.getArgument(argIndex) = node.asExpr()
3838
)
3939
}
4040
}

rust/ql/examples/snippets/simple_sql_injection.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ module SqlInjectionConfig implements DataFlow::ConfigSig {
2525
// `node` is the first argument of a call to `sqlx_core::query::query`
2626
exists(CallExpr call |
2727
call.getStaticTarget().getCanonicalPath() = "sqlx_core::query::query" and
28-
call.getArg(0) = node.asExpr()
28+
call.getArgument(0) = node.asExpr()
2929
)
3030
}
3131
}

rust/ql/lib/codeql/rust/controlflow/CfgNodes.qll

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
*/
55

66
private import rust
7-
private import codeql.rust.elements.Call
87
private import ControlFlowGraph
98
private import internal.ControlFlowGraphImpl as CfgImpl
109
private import internal.CfgNodes
@@ -201,62 +200,67 @@ final class BreakExprCfgNode extends Nodes::BreakExprCfgNode {
201200
}
202201

203202
/**
204-
* A function or method call expression. See `CallExpr` and `MethodCallExpr` for further details.
203+
* A method call expression. For example:
204+
* ```rust
205+
* x.foo(42);
206+
* x.foo::<u32, u64>(42);
207+
* ```
205208
*/
206-
final class CallExprBaseCfgNode extends Nodes::CallExprBaseCfgNode {
207-
private CallExprBaseChildMapping node;
209+
final class MethodCallExprCfgNode extends Nodes::MethodCallExprCfgNode {
210+
private MethodCallExprChildMapping node;
208211

209-
CallExprBaseCfgNode() { node = this.getAstNode() }
212+
MethodCallExprCfgNode() { node = this.getAstNode() }
210213

211214
/** Gets the `i`th argument of this call. */
212215
ExprCfgNode getArgument(int i) {
213216
any(ChildMapping mapping).hasCfgChild(node, node.getArgList().getArg(i), this, result)
214217
}
215218
}
216219

217-
/**
218-
* A method call expression. For example:
219-
* ```rust
220-
* x.foo(42);
221-
* x.foo::<u32, u64>(42);
222-
* ```
223-
*/
224-
final class MethodCallExprCfgNode extends CallExprBaseCfgNode, Nodes::MethodCallExprCfgNode { }
225-
226220
/**
227221
* A CFG node that calls a function.
228222
*
229223
* This class abstract over the different ways in which a function can be called in Rust.
230224
*/
231-
final class CallCfgNode extends ExprCfgNode {
232-
private Call node;
225+
final class CallExprCfgNode extends ExprCfgNode {
226+
private CallExpr node;
233227

234-
CallCfgNode() { node = this.getAstNode() }
228+
CallExprCfgNode() { node = this.getAstNode() }
235229

236230
/** Gets the underlying `Call`. */
237-
Call getCall() { result = node }
231+
CallExpr getCall() { result = node }
238232

239233
/** Gets the receiver of this call if it is a method call. */
240234
ExprCfgNode getReceiver() {
241235
any(ChildMapping mapping).hasCfgChild(node, node.getReceiver(), this, result)
242236
}
243237

244238
/** Gets the `i`th argument of this call, if any. */
245-
ExprCfgNode getPositionalArgument(int i) {
246-
any(ChildMapping mapping).hasCfgChild(node, node.getPositionalArgument(i), this, result)
239+
ExprCfgNode getArgument(int i) {
240+
any(ChildMapping mapping).hasCfgChild(node, node.getArgument(i), this, result)
247241
}
248242
}
249243

250244
/**
251-
* A function call expression. For example:
245+
* An expression with parenthesized arguments. For example:
252246
* ```rust
253247
* foo(42);
254248
* foo::<u32, u64>(42);
255249
* foo[0](42);
256250
* foo(1) = 4;
251+
* Option::Some(42);
257252
* ```
258253
*/
259-
final class CallExprCfgNode extends CallExprBaseCfgNode, Nodes::CallExprCfgNode { }
254+
final class ParenArgsExprCfgNode extends Nodes::ParenArgsExprCfgNode {
255+
private ParenArgsExprChildMapping node;
256+
257+
ParenArgsExprCfgNode() { node = this.getAstNode() }
258+
259+
/** Gets the `i`th argument of this call. */
260+
ExprCfgNode getArgument(int i) {
261+
any(ChildMapping mapping).hasCfgChild(node, node.getArgList().getArg(i), this, result)
262+
}
263+
}
260264

261265
/**
262266
* A FormatArgsExpr. For example:

rust/ql/lib/codeql/rust/controlflow/internal/CfgNodes.qll

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,12 @@ class BreakExprTargetChildMapping extends ParentAstNode, Expr {
5757
override predicate relevantChild(AstNode child) { child.(BreakExpr).getTarget() = this }
5858
}
5959

60-
class CallExprBaseChildMapping extends ParentAstNode, CallExprBase {
61-
override predicate relevantChild(AstNode child) { child = this.getAnArg() }
60+
class ParenArgsExprChildMapping extends ParentAstNode, ParenArgsExpr {
61+
override predicate relevantChild(AstNode child) { child = this.getArgList().getAnArg() }
62+
}
63+
64+
class MethodCallExprChildMapping extends ParentAstNode, MethodCallExpr {
65+
override predicate relevantChild(AstNode child) { child = this.getArgList().getAnArg() }
6266
}
6367

6468
class StructExprChildMapping extends ParentAstNode, StructExpr {

rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -292,9 +292,9 @@ module ExprTrees {
292292
}
293293
}
294294

295-
class CallExprTree extends StandardPostOrderTree instanceof CallExpr {
295+
class CallExprTree extends StandardPostOrderTree instanceof ParenArgsExpr {
296296
override AstNode getChildNode(int i) {
297-
i = 0 and result = super.getFunction()
297+
i = 0 and result = super.getBase()
298298
or
299299
result = super.getArgList().getArg(i - 1)
300300
}
@@ -512,7 +512,7 @@ module ExprTrees {
512512

513513
class MethodCallExprTree extends StandardPostOrderTree, MethodCallExpr {
514514
override AstNode getChildNode(int i) {
515-
if i = 0 then result = this.getReceiver() else result = this.getArg(i - 1)
515+
if i = 0 then result = this.getReceiver() else result = this.getArgList().getArg(i - 1)
516516
}
517517
}
518518

rust/ql/lib/codeql/rust/dataflow/internal/Content.qll

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -269,8 +269,6 @@ newtype TContent =
269269
)]
270270
} or
271271
TFunctionCallReturnContent() or
272-
TFunctionCallArgumentContent(int pos) {
273-
pos in [0 .. any(CallExpr c).getArgList().getNumberOfArgs() - 1]
274-
} or
272+
TFunctionCallArgumentContent(int pos) { pos in [0 .. any(CallExpr c).getNumberOfArgs() - 1] } or
275273
TCapturedVariableContent(VariableCapture::CapturedVariable v) or
276274
TReferenceContent()

rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll

Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ private import codeql.util.Boolean
88
private import codeql.dataflow.DataFlow
99
private import codeql.dataflow.internal.DataFlowImpl
1010
private import rust
11-
private import codeql.rust.elements.Call
1211
private import SsaImpl as SsaImpl
1312
private import codeql.rust.controlflow.internal.Scope as Scope
1413
private import codeql.rust.internal.PathResolution
@@ -57,8 +56,8 @@ final class DataFlowCallable extends TDataFlowCallable {
5756
}
5857

5958
final class DataFlowCall extends TDataFlowCall {
60-
/** Gets the underlying call in the CFG, if any. */
61-
Call asCall() { this = TCall(result) }
59+
/** Gets the underlying function call, if any. */
60+
CallExpr asCallExpr() { this = TCallExpr(result) }
6261

6362
predicate isSummaryCall(
6463
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
@@ -67,13 +66,13 @@ final class DataFlowCall extends TDataFlowCall {
6766
}
6867

6968
DataFlowCallable getEnclosingCallable() {
70-
result.asCfgScope() = this.asCall().getEnclosingCfgScope()
69+
result.asCfgScope() = this.asCallExpr().getEnclosingCfgScope()
7170
or
7271
this.isSummaryCall(result.asSummarizedCallable(), _)
7372
}
7473

7574
string toString() {
76-
result = this.asCall().toString()
75+
result = this.asCallExpr().toString()
7776
or
7877
exists(
7978
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
@@ -83,7 +82,7 @@ final class DataFlowCall extends TDataFlowCall {
8382
)
8483
}
8584

86-
Location getLocation() { result = this.asCall().getLocation() }
85+
Location getLocation() { result = this.asCallExpr().getLocation() }
8786
}
8887

8988
/**
@@ -131,8 +130,8 @@ final class ParameterPosition extends TParameterPosition {
131130
*/
132131
final class ArgumentPosition extends ParameterPosition {
133132
/** Gets the argument of `call` at this position, if any. */
134-
Expr getArgument(Call call) {
135-
result = call.getPositionalArgument(this.getPosition())
133+
Expr getArgument(CallExpr call) {
134+
result = call.getArgument(this.getPosition())
136135
or
137136
this.isSelf() and result = call.getReceiver()
138137
}
@@ -141,9 +140,7 @@ final class ArgumentPosition extends ParameterPosition {
141140
/**
142141
* Holds if `arg` is an argument of `call` at the position `pos`.
143142
*/
144-
predicate isArgumentForCall(Expr arg, Call call, ArgumentPosition pos) {
145-
// TODO: Handle index expressions as calls in data flow.
146-
not call instanceof IndexExpr and
143+
predicate isArgumentForCall(Expr arg, CallExpr call, ArgumentPosition pos) {
147144
arg = pos.getArgument(call)
148145
}
149146

@@ -293,10 +290,8 @@ predicate lambdaCreationExpr(Expr creation) {
293290
* Holds if `call` is a lambda call of kind `kind` where `receiver` is the
294291
* invoked expression.
295292
*/
296-
predicate lambdaCallExpr(CallExpr call, LambdaCallKind kind, Expr receiver) {
297-
receiver = call.getFunction() and
298-
// All calls to complex expressions and local variable accesses are lambda call.
299-
(receiver instanceof PathExpr implies receiver = any(Variable v).getAnAccess()) and
293+
predicate lambdaCallExpr(ClosureCallExpr call, LambdaCallKind kind, Expr receiver) {
294+
receiver = call.getClosureExpr() and
300295
exists(kind)
301296
}
302297

@@ -406,7 +401,7 @@ module RustDataFlow implements InputSig<Location> {
406401

407402
/** Gets a viable implementation of the target of the given `Call`. */
408403
DataFlowCallable viableCallable(DataFlowCall call) {
409-
exists(Call c | c = call.asCall() |
404+
exists(CallExpr c | c = call.asCallExpr() |
410405
result.asCfgScope() = c.getARuntimeTarget()
411406
or
412407
exists(SummarizedCallable sc, Function staticTarget |
@@ -666,8 +661,8 @@ module RustDataFlow implements InputSig<Location> {
666661

667662
pragma[nomagic]
668663
additional predicate storeContentStep(Node node1, Content c, Node node2) {
669-
exists(CallExpr call, int pos |
670-
node1.asExpr() = call.getArg(pragma[only_bind_into](pos)) and
664+
exists(ParenArgsExpr call, int pos |
665+
node1.asExpr() = call.getArgument(pragma[only_bind_into](pos)) and
671666
node2.asExpr() = call and
672667
c = TTupleFieldContent(call.getTupleField(pragma[only_bind_into](pos)))
673668
)
@@ -818,7 +813,7 @@ module RustDataFlow implements InputSig<Location> {
818813
// pointer. Except if the path occurs directly in a call, then it's just a
819814
// call to the function and not a function being passed as data.
820815
resolvePath(e.(PathExpr).getPath()) = c.asCfgScope() and
821-
not any(CallExpr call).getFunction() = e
816+
not any(ParenArgsExpr call).getBase() = e
822817
)
823818
}
824819

@@ -828,11 +823,7 @@ module RustDataFlow implements InputSig<Location> {
828823
*/
829824
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
830825
(
831-
receiver.asExpr() = call.asCall().(CallExpr).getFunction() and
832-
// All calls to complex expressions and local variable accesses are lambda call.
833-
exists(Expr f | f = receiver.asExpr() |
834-
f instanceof PathExpr implies f = any(Variable v).getAnAccess()
835-
)
826+
receiver.asExpr() = call.asCallExpr().(ClosureCallExpr).getClosureExpr()
836827
or
837828
call.isSummaryCall(_, receiver.(FlowSummaryNode).getSummaryNode())
838829
) and
@@ -994,11 +985,9 @@ private module Cached {
994985

995986
cached
996987
newtype TDataFlowCall =
997-
TCall(Call call) {
988+
TCallExpr(CallExpr call) {
998989
Stages::DataFlowStage::ref() and
999-
call.hasEnclosingCfgScope() and
1000-
// TODO: Handle index expressions as calls in data flow.
1001-
not call instanceof IndexExpr
990+
call.hasEnclosingCfgScope()
1002991
} or
1003992
TSummaryCall(
1004993
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
@@ -1026,10 +1015,8 @@ private module Cached {
10261015
cached
10271016
newtype TParameterPosition =
10281017
TPositionalParameterPosition(int i) {
1029-
i in [0 .. max([any(ParamList l).getNumberOfParams(), any(ArgList l).getNumberOfArgs()]) - 1]
1030-
or
1031-
FlowSummaryImpl::ParsePositions::isParsedArgumentPosition(_, i)
1032-
or
1018+
i in [0 .. max([any(ParamList l).getNumberOfParams(), any(ArgList l).getNumberOfArgs()]) - 1] or
1019+
FlowSummaryImpl::ParsePositions::isParsedArgumentPosition(_, i) or
10331020
FlowSummaryImpl::ParsePositions::isParsedParameterPosition(_, i)
10341021
} or
10351022
TClosureSelfParameterPosition() or

rust/ql/lib/codeql/rust/dataflow/internal/FlowSummaryImpl.qll

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,17 @@ private import codeql.rust.dataflow.Ssa
1212
private import Content
1313

1414
module Input implements InputSig<Location, RustDataFlow> {
15-
private import codeql.rust.elements.internal.CallExprBaseImpl::Impl as CallExprBaseImpl
1615
private import codeql.rust.frameworks.stdlib.Stdlib
1716

1817
class SummarizedCallableBase = Function;
1918

2019
abstract private class SourceSinkBase extends AstNode {
2120
/** Gets the associated call. */
22-
abstract CallExprBase getCall();
21+
abstract CallLikeExpr getCall();
2322

2423
/** Holds if the associated call resolves to `path`. */
2524
final predicate callResolvesTo(string path) {
26-
path = this.getCall().getStaticTarget().(Addressable).getCanonicalPath()
25+
path = this.getCall().getResolvedTarget().getCanonicalPath()
2726
}
2827
}
2928

@@ -32,19 +31,19 @@ module Input implements InputSig<Location, RustDataFlow> {
3231
abstract class SinkBase extends SourceSinkBase { }
3332

3433
private class CallExprFunction extends SourceBase, SinkBase {
35-
private CallExpr call;
34+
private ParenArgsExpr call;
3635

37-
CallExprFunction() { this = call.getFunction() }
36+
CallExprFunction() { this = call.getBase() }
3837

39-
override CallExpr getCall() { result = call }
38+
override ParenArgsExpr getCall() { result = call }
4039
}
4140

4241
private class MethodCallExprNameRef extends SourceBase, SinkBase {
4342
private MethodCallExpr call;
4443

4544
MethodCallExprNameRef() { this = call.getIdentifier() }
4645

47-
override MethodCallExpr getCall() { result = call }
46+
override CallLikeExpr getCall() { result = call }
4847
}
4948

5049
RustDataFlow::ArgumentPosition callbackSelfParameterPosition() { result.isClosureSelf() }
@@ -53,9 +52,7 @@ module Input implements InputSig<Location, RustDataFlow> {
5352

5453
string encodeParameterPosition(ParameterPosition pos) { result = pos.toString() }
5554

56-
string encodeArgumentPosition(RustDataFlow::ArgumentPosition pos) {
57-
result = encodeParameterPosition(pos)
58-
}
55+
string encodeArgumentPosition(RustDataFlow::ArgumentPosition pos) { result = pos.toString() }
5956

6057
string encodeContent(ContentSet cs, string arg) {
6158
exists(Content c | cs = TSingletonContentSet(c) |
@@ -131,7 +128,9 @@ module Input implements InputSig<Location, RustDataFlow> {
131128
private import Make<Location, RustDataFlow, Input> as Impl
132129

133130
private module StepsInput implements Impl::Private::StepsInputSig {
134-
DataFlowCall getACall(Public::SummarizedCallable sc) { result.asCall().getStaticTarget() = sc }
131+
DataFlowCall getACall(Public::SummarizedCallable sc) {
132+
result.asCallExpr().getStaticTarget() = sc
133+
}
135134

136135
/** Gets the argument of `source` described by `sc`, if any. */
137136
private Expr getSourceNodeArgument(Input::SourceBase source, Impl::Private::SummaryComponent sc) {
@@ -173,7 +172,7 @@ private module StepsInput implements Impl::Private::StepsInputSig {
173172
}
174173

175174
RustDataFlow::Node getSinkNode(Input::SinkBase sink, Impl::Private::SummaryComponent sc) {
176-
exists(CallExprBase call, Expr arg, ArgumentPosition pos |
175+
exists(CallLikeExpr call, Expr arg, ArgumentPosition pos |
177176
result.asExpr() = arg and
178177
sc = Impl::Private::SummaryComponent::argument(pos) and
179178
call = sink.getCall() and

rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ private import rust
4747
private import codeql.rust.dataflow.FlowSummary
4848
private import codeql.rust.dataflow.FlowSource
4949
private import codeql.rust.dataflow.FlowSink
50-
private import codeql.rust.elements.internal.CallExprBaseImpl::Impl as CallExprBaseImpl
5150

5251
/**
5352
* Holds if in a call to the function with canonical path `path`, the value referred

0 commit comments

Comments
 (0)