Skip to content

Commit 7378fbc

Browse files
committed
Rust: Restructure classes representing calls
1 parent 3e5ea56 commit 7378fbc

Some content is hidden

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

48 files changed

+716
-548
lines changed

rust/ql/examples/snippets/simple_constant_password.ql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ module ConstantPasswordConfig implements DataFlow::ConfigSig {
3030

3131
predicate isSink(DataFlow::Node node) {
3232
// `node` is an argument whose corresponding parameter name matches the pattern "pass%"
33-
exists(CallExpr call, Function target, int argIndex, Variable v |
33+
exists(Call call, Function target, int argIndex, Variable v |
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.getPositionalArgument(argIndex) = node.asExpr()
3838
)
3939
}
4040
}

rust/ql/examples/snippets/simple_sql_injection.ql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ module SqlInjectionConfig implements DataFlow::ConfigSig {
2323

2424
predicate isSink(DataFlow::Node node) {
2525
// `node` is the first argument of a call to `sqlx_core::query::query`
26-
exists(CallExpr call |
26+
exists(Call call |
2727
call.getStaticTarget().getCanonicalPath() = "sqlx_core::query::query" and
28-
call.getArg(0) = node.asExpr()
28+
call.getPositionalArgument(0) = node.asExpr()
2929
)
3030
}
3131
}

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

Lines changed: 23 additions & 19 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
@@ -200,28 +199,23 @@ final class BreakExprCfgNode extends Nodes::BreakExprCfgNode {
200199
}
201200
}
202201

203-
/**
204-
* A function or method call expression. See `CallExpr` and `MethodCallExpr` for further details.
205-
*/
206-
final class CallExprBaseCfgNode extends Nodes::CallExprBaseCfgNode {
207-
private CallExprBaseChildMapping node;
208-
209-
CallExprBaseCfgNode() { node = this.getAstNode() }
210-
211-
/** Gets the `i`th argument of this call. */
212-
ExprCfgNode getArgument(int i) {
213-
any(ChildMapping mapping).hasCfgChild(node, node.getArgList().getArg(i), this, result)
214-
}
215-
}
216-
217202
/**
218203
* A method call expression. For example:
219204
* ```rust
220205
* x.foo(42);
221206
* x.foo::<u32, u64>(42);
222207
* ```
223208
*/
224-
final class MethodCallExprCfgNode extends CallExprBaseCfgNode, Nodes::MethodCallExprCfgNode { }
209+
final class MethodCallExprCfgNode extends Nodes::MethodCallExprCfgNode {
210+
private MethodCallExprChildMapping node;
211+
212+
MethodCallExprCfgNode() { node = this.getAstNode() }
213+
214+
/** Gets the `i`th argument of this call. */
215+
ExprCfgNode getPositionalArgument(int i) {
216+
any(ChildMapping mapping).hasCfgChild(node, node.getPositionalArgument(i), this, result)
217+
}
218+
}
225219

226220
/**
227221
* A CFG node that calls a function.
@@ -238,7 +232,7 @@ final class CallCfgNode extends ExprCfgNode {
238232

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

244238
/** Gets the `i`th argument of this call, if any. */
@@ -248,15 +242,25 @@ final class CallCfgNode extends ExprCfgNode {
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 CallExprCfgNode extends Nodes::CallExprCfgNode {
255+
private CallExprChildMapping node;
256+
257+
CallExprCfgNode() { node = this.getAstNode() }
258+
259+
/** Gets the `i`th argument of this call. */
260+
ExprCfgNode getSyntacticArgument(int i) {
261+
any(ChildMapping mapping).hasCfgChild(node, node.getSyntacticArgument(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 CallExprChildMapping extends ParentAstNode, CallExpr {
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: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -210,14 +210,13 @@ module ExprTrees {
210210
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
211211
}
212212

213-
class BinaryOpExprTree extends StandardPostOrderTree instanceof BinaryExpr {
214-
BinaryOpExprTree() { not this instanceof BinaryLogicalOperation }
215-
216-
override AstNode getChildNode(int i) {
217-
i = 0 and result = super.getLhs()
218-
or
219-
i = 1 and result = super.getRhs()
213+
class ArgsExprTree extends StandardPostOrderTree instanceof ArgsExpr {
214+
ArgsExprTree() {
215+
not this instanceof CallExpr and
216+
not this instanceof BinaryLogicalOperation
220217
}
218+
219+
override AstNode getChildNode(int i) { result = super.getSyntacticArgument(i) }
221220
}
222221

223222
class LogicalOrExprTree extends PostOrderTree, LogicalOrExpr {
@@ -296,7 +295,7 @@ module ExprTrees {
296295
override AstNode getChildNode(int i) {
297296
i = 0 and result = super.getFunction()
298297
or
299-
result = super.getArgList().getArg(i - 1)
298+
result = super.getSyntacticArgument(i - 1)
300299
}
301300
}
302301

@@ -371,14 +370,6 @@ module ExprTrees {
371370
}
372371
}
373372

374-
class IndexExprTree extends StandardPostOrderTree instanceof IndexExpr {
375-
override AstNode getChildNode(int i) {
376-
i = 0 and result = super.getBase()
377-
or
378-
i = 1 and result = super.getIndex()
379-
}
380-
}
381-
382373
class LetExprTree extends StandardPostOrderTree, LetExpr {
383374
override AstNode getChildNode(int i) {
384375
i = 0 and
@@ -510,12 +501,6 @@ module ExprTrees {
510501
}
511502
}
512503

513-
class MethodCallExprTree extends StandardPostOrderTree, MethodCallExpr {
514-
override AstNode getChildNode(int i) {
515-
if i = 0 then result = this.getReceiver() else result = this.getArg(i - 1)
516-
}
517-
}
518-
519504
class OffsetOfExprTree extends LeafTree instanceof OffsetOfExpr { }
520505

521506
class ParenExprTree extends ControlFlowTree, ParenExpr {
@@ -534,10 +519,6 @@ module ExprTrees {
534519

535520
class PathExprTree extends LeafTree instanceof PathExpr { }
536521

537-
class PrefixExprTree extends StandardPostOrderTree instanceof PrefixExpr {
538-
override AstNode getChildNode(int i) { i = 0 and result = super.getExpr() }
539-
}
540-
541522
class RangeExprTree extends StandardPostOrderTree instanceof RangeExpr {
542523
override AstNode getChildNode(int i) {
543524
i = 0 and result = super.getStart()

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,15 +163,15 @@ final class TuplePositionContent extends FieldContent, TTuplePositionContent {
163163
}
164164

165165
/**
166-
* A content for the index of an argument to at function call.
166+
* A content for the index of an argument to at closure call.
167167
*
168168
* Used by the model generator to create flow summaries for higher-order
169169
* functions.
170170
*/
171-
final class FunctionCallArgumentContent extends Content, TFunctionCallArgumentContent {
171+
final class ClosureCallArgumentContent extends Content, TClosureCallArgumentContent {
172172
private int pos;
173173

174-
FunctionCallArgumentContent() { this = TFunctionCallArgumentContent(pos) }
174+
ClosureCallArgumentContent() { this = TClosureCallArgumentContent(pos) }
175175

176176
int getPosition() { result = pos }
177177

@@ -269,8 +269,8 @@ newtype TContent =
269269
)]
270270
} or
271271
TFunctionCallReturnContent() or
272-
TFunctionCallArgumentContent(int pos) {
273-
pos in [0 .. any(CallExpr c).getArgList().getNumberOfArgs() - 1]
272+
TClosureCallArgumentContent(int pos) {
273+
pos in [0 .. any(ClosureCallExpr c).getNumberOfPositionalArguments()]
274274
} or
275275
TCapturedVariableContent(VariableCapture::CapturedVariable v) or
276276
TReferenceContent()

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

Lines changed: 14 additions & 17 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,7 +56,7 @@ final class DataFlowCallable extends TDataFlowCallable {
5756
}
5857

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

6362
predicate isSummaryCall(
@@ -134,7 +133,7 @@ final class ArgumentPosition extends ParameterPosition {
134133
Expr getArgument(Call call) {
135134
result = call.getPositionalArgument(this.getPosition())
136135
or
137-
result = call.getReceiver() and this.isSelf()
136+
result = call.(MethodCall).getReceiver() and this.isSelf()
138137
}
139138
}
140139

@@ -293,10 +292,8 @@ predicate lambdaCreationExpr(Expr creation) {
293292
* Holds if `call` is a lambda call of kind `kind` where `receiver` is the
294293
* invoked expression.
295294
*/
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
295+
predicate lambdaCallExpr(ClosureCallExpr call, LambdaCallKind kind, Expr receiver) {
296+
receiver = call.getClosureExpr() and
300297
exists(kind)
301298
}
302299

@@ -666,10 +663,14 @@ module RustDataFlow implements InputSig<Location> {
666663

667664
pragma[nomagic]
668665
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
671-
node2.asExpr() = call and
672-
c = TTupleFieldContent(call.getTupleField(pragma[only_bind_into](pos)))
666+
exists(CallExpr ce, TupleField tf, int pos |
667+
node1.asExpr() = ce.getSyntacticArgument(pos) and
668+
node2.asExpr() = ce and
669+
c = TTupleFieldContent(tf)
670+
|
671+
tf = ce.(TupleStructExpr).getTupleField(pos)
672+
or
673+
tf = ce.(TupleVariantExpr).getTupleField(pos)
673674
)
674675
or
675676
exists(StructExpr re, string field |
@@ -715,7 +716,7 @@ module RustDataFlow implements InputSig<Location> {
715716
exists(DataFlowCall call, int i |
716717
isArgumentNode(node1, call, TPositionalParameterPosition(i)) and
717718
lambdaCall(call, _, node2.(PostUpdateNode).getPreUpdateNode()) and
718-
c.(FunctionCallArgumentContent).getPosition() = i
719+
c.(ClosureCallArgumentContent).getPosition() = i
719720
)
720721
or
721722
VariableCapture::storeStep(node1, c, node2)
@@ -824,11 +825,7 @@ module RustDataFlow implements InputSig<Location> {
824825
*/
825826
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
826827
(
827-
receiver.asExpr() = call.asCall().(CallExpr).getFunction() and
828-
// All calls to complex expressions and local variable accesses are lambda call.
829-
exists(Expr f | f = receiver.asExpr() |
830-
f instanceof PathExpr implies f = any(Variable v).getAnAccess()
831-
)
828+
receiver.asExpr() = call.asCall().(ClosureCallExpr).getClosureExpr()
832829
or
833830
call.isSummaryCall(_, receiver.(FlowSummaryNode).getSummaryNode())
834831
) and

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

Lines changed: 5 additions & 8 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 Call 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

@@ -36,7 +35,7 @@ module Input implements InputSig<Location, RustDataFlow> {
3635

3736
CallExprFunction() { this = call.getFunction() }
3837

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

4241
private class MethodCallExprNameRef extends SourceBase, SinkBase {
@@ -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) |
@@ -173,7 +170,7 @@ private module StepsInput implements Impl::Private::StepsInputSig {
173170
}
174171

175172
RustDataFlow::Node getSinkNode(Input::SinkBase sink, Impl::Private::SummaryComponent sc) {
176-
exists(CallExprBase call, Expr arg, ArgumentPosition pos |
173+
exists(ArgsExpr call, Expr arg, ArgumentPosition pos |
177174
result.asExpr() = arg and
178175
sc = Impl::Private::SummaryComponent::argument(pos) and
179176
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

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -294,13 +294,12 @@ final class SummaryArgumentNode extends FlowSummaryNode, ArgumentNode {
294294
* passed into the closure body at an invocation.
295295
*/
296296
final class ClosureArgumentNode extends ArgumentNode, ExprNode {
297-
private CallExpr call_;
297+
private Call call_;
298298

299299
ClosureArgumentNode() { lambdaCallExpr(call_, _, this.asExpr()) }
300300

301301
override predicate isArgumentOf(DataFlowCall call, RustDataFlow::ArgumentPosition pos) {
302-
call.asCall() = call_ and
303-
pos.isClosureSelf()
302+
call.asCall() = call_ and pos.isClosureSelf()
304303
}
305304
}
306305

0 commit comments

Comments
 (0)