Skip to content

Commit 3938385

Browse files
committed
wip2
1 parent 645ff85 commit 3938385

File tree

7 files changed

+70
-58
lines changed

7 files changed

+70
-58
lines changed

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

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ final class DataFlowCallable extends TDataFlowCallable {
5757
}
5858

5959
final class DataFlowCall extends TDataFlowCall {
60-
/** Gets the underlying call in the CFG, if any. */
61-
Call asCall() { this = TCall(result) }
60+
/** Gets the underlying function call, if any. */
61+
FunctionCall asFunctionCall() { this = TFunctionCall(result) }
6262

6363
predicate isSummaryCall(
6464
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
@@ -67,13 +67,13 @@ final class DataFlowCall extends TDataFlowCall {
6767
}
6868

6969
DataFlowCallable getEnclosingCallable() {
70-
result.asCfgScope() = this.asCall().getEnclosingCfgScope()
70+
result.asCfgScope() = this.asFunctionCall().getEnclosingCfgScope()
7171
or
7272
this.isSummaryCall(result.asSummarizedCallable(), _)
7373
}
7474

7575
string toString() {
76-
result = this.asCall().toString()
76+
result = this.asFunctionCall().toString()
7777
or
7878
exists(
7979
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
@@ -83,7 +83,7 @@ final class DataFlowCall extends TDataFlowCall {
8383
)
8484
}
8585

86-
Location getLocation() { result = this.asCall().getLocation() }
86+
Location getLocation() { result = this.asFunctionCall().getLocation() }
8787
}
8888

8989
/**
@@ -141,13 +141,8 @@ final class ArgumentPosition extends ParameterPosition {
141141

142142
/**
143143
* Holds if `arg` is an argument of `call` at the position `pos`.
144-
*
145-
* Note that this does not hold for the receiever expression of a method call
146-
* as the synthetic `ReceiverNode` is the argument for the `self` parameter.
147144
*/
148-
predicate isArgumentForCall(Expr arg, Call call, ArgumentPosition pos) {
149-
// TODO: Handle index expressions as calls in data flow.
150-
not call instanceof IndexExpr and
145+
predicate isArgumentForCall(Expr arg, FunctionCall call, ArgumentPosition pos) {
151146
arg = pos.getArgument(call)
152147
}
153148

@@ -408,7 +403,7 @@ module RustDataFlow implements InputSig<Location> {
408403

409404
/** Gets a viable implementation of the target of the given `Call`. */
410405
DataFlowCallable viableCallable(DataFlowCall call) {
411-
exists(Call c | c = call.asCall() |
406+
exists(FunctionCall c | c = call.asFunctionCall() |
412407
result.asCfgScope() = c.getARuntimeTarget()
413408
or
414409
exists(SummarizedCallable sc, Function staticTarget |
@@ -831,11 +826,7 @@ module RustDataFlow implements InputSig<Location> {
831826
*/
832827
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
833828
(
834-
receiver.asExpr() = call.asCall().(CallExpr).getFunction() and
835-
// All calls to complex expressions and local variable accesses are lambda call.
836-
exists(Expr f | f = receiver.asExpr() |
837-
f instanceof PathExpr implies f = any(Variable v).getAnAccess()
838-
)
829+
receiver.asExpr() = call.asFunctionCall().(ClosureCall).getFunction()
839830
or
840831
call.isSummaryCall(_, receiver.(FlowSummaryNode).getSummaryNode())
841832
) and
@@ -997,11 +988,9 @@ private module Cached {
997988

998989
cached
999990
newtype TDataFlowCall =
1000-
TCall(Call call) {
991+
TFunctionCall(FunctionCall call) {
1001992
Stages::DataFlowStage::ref() and
1002-
call.hasEnclosingCfgScope() and
1003-
// TODO: Handle index expressions as calls in data flow.
1004-
not call instanceof IndexExpr
993+
call.hasEnclosingCfgScope()
1005994
} or
1006995
TSummaryCall(
1007996
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ module Input implements InputSig<Location, RustDataFlow> {
2222

2323
/** Holds if the associated call resolves to `path`. */
2424
final predicate callResolvesTo(string path) {
25-
path = this.getCall().getStaticTarget().(Addressable).getCanonicalPath()
25+
path = this.getCall().getStaticTarget().getCanonicalPath()
2626
}
2727
}
2828

@@ -128,7 +128,9 @@ module Input implements InputSig<Location, RustDataFlow> {
128128
private import Make<Location, RustDataFlow, Input> as Impl
129129

130130
private module StepsInput implements Impl::Private::StepsInputSig {
131-
DataFlowCall getACall(Public::SummarizedCallable sc) { result.asCall().getStaticTarget() = sc }
131+
DataFlowCall getACall(Public::SummarizedCallable sc) {
132+
result.asFunctionCall().getStaticTarget() = sc
133+
}
132134

133135
/** Gets the argument of `source` described by `sc`, if any. */
134136
private Expr getSourceNodeArgument(Input::SourceBase source, Impl::Private::SummaryComponent sc) {

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

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ abstract class ArgumentNode extends Node {
224224
}
225225

226226
final class ExprArgumentNode extends ArgumentNode, ExprNode {
227-
private Call call_;
227+
private FunctionCall call_;
228228
private RustDataFlow::ArgumentPosition pos_;
229229

230230
ExprArgumentNode() {
@@ -234,7 +234,7 @@ final class ExprArgumentNode extends ArgumentNode, ExprNode {
234234
}
235235

236236
override predicate isArgumentOf(DataFlowCall call, RustDataFlow::ArgumentPosition pos) {
237-
call.asCall() = call_ and pos = pos_
237+
call.asFunctionCall() = call_ and pos = pos_
238238
}
239239
}
240240

@@ -268,7 +268,7 @@ final class DerefBorrowArgNode extends DerefBorrowNode, ArgumentNode {
268268
private DataFlowCall call_;
269269
private RustDataFlow::ArgumentPosition pos_;
270270

271-
DerefBorrowArgNode() { isArgumentForCall(n, call_.asCall(), pos_) }
271+
DerefBorrowArgNode() { isArgumentForCall(n, call_.asFunctionCall(), pos_) }
272272

273273
override predicate isArgumentOf(DataFlowCall call, RustDataFlow::ArgumentPosition pos) {
274274
call = call_ and pos = pos_
@@ -298,7 +298,7 @@ final class ClosureArgumentNode extends ArgumentNode, ExprNode {
298298
ClosureArgumentNode() { lambdaCallExpr(call_, _, this.asExpr()) }
299299

300300
override predicate isArgumentOf(DataFlowCall call, RustDataFlow::ArgumentPosition pos) {
301-
call.asCall() = call_ and pos.isClosureSelf()
301+
call.asFunctionCall() = call_ and pos.isClosureSelf()
302302
}
303303
}
304304

@@ -346,11 +346,11 @@ abstract class OutNode extends Node {
346346
}
347347

348348
final private class ExprOutNode extends ExprNode, OutNode {
349-
ExprOutNode() { this.asExpr() instanceof Call }
349+
ExprOutNode() { this.asExpr() instanceof FunctionCall }
350350

351351
/** Gets the underlying call CFG node that includes this out node. */
352352
override DataFlowCall getCall(ReturnKind kind) {
353-
result.asCall() = n and
353+
result.asFunctionCall() = n and
354354
kind = TNormalReturnKind()
355355
}
356356
}
@@ -482,10 +482,8 @@ newtype TNode =
482482
or
483483
e =
484484
[
485-
any(IndexExpr i).getBase(), // todo: remove once `IndexExpr`s are treated as calls in data flow
486485
any(FieldExpr access).getContainer(), //
487486
any(TryExpr try).getExpr(), //
488-
any(PrefixExpr pe | pe.getOperatorName() = "*").getExpr(), //
489487
any(AwaitExpr a).getExpr(), //
490488
getPostUpdateReverseStep(any(PostUpdateNode n).getPreUpdateNode().asExpr(), _)
491489
]

rust/ql/lib/codeql/rust/elements/Call.qll

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,35 @@ private import internal.CallImpl
77

88
final class Call = Impl::Call;
99

10+
private predicate isClosureCallExpr(CallExpr call) {
11+
exists(Expr receiver | receiver = call.getFunction() |
12+
// All calls to complex expressions and local variable accesses are lambda calls
13+
receiver instanceof PathExpr implies receiver = any(Variable v).getAnAccess()
14+
)
15+
}
16+
17+
private predicate isGuaranteedMethodCall(Call call) {
18+
// even if we cannot resolve the target, we know that the following calls always
19+
// target functions
20+
call instanceof MethodCallExpr
21+
or
22+
call.(Operation).isOverloaded(_, _, _)
23+
or
24+
call instanceof IndexExpr
25+
}
26+
1027
/**
11-
* A call expression that targets a function.
28+
* A call expression that targets a function or a closure.
1229
*
1330
* For example, call expressions like `Some(42)` and `x && y` are _not_ function calls.
1431
*/
1532
final class FunctionCall extends Call {
1633
FunctionCall() {
1734
this.getStaticTarget() instanceof Function
1835
or
19-
// even if we cannot resolve the target, we know that the following calls always
20-
// target functions
21-
this instanceof MethodCallExpr
22-
or
23-
this.(Operation).isOverloaded(_, _, _)
36+
isClosureCallExpr(this)
2437
or
25-
this instanceof IndexExpr
38+
isGuaranteedMethodCall(this)
2639
}
2740

2841
/** Gets the static target of this function call, if any. */
@@ -34,28 +47,20 @@ final class FunctionCall extends Call {
3447
*/
3548
final class MethodCall extends FunctionCall {
3649
MethodCall() {
37-
this.getStaticTarget().(Function).hasSelfParam()
50+
this.getStaticTarget() instanceof Method
3851
or
39-
// even if we cannot resolve the target, we know that the following calls always
40-
// target methods
41-
this instanceof MethodCallExpr
42-
or
43-
this.(Operation).isOverloaded(_, _, _)
44-
or
45-
this instanceof IndexExpr
52+
isGuaranteedMethodCall(this)
4653
}
54+
55+
/** Gets the static target of this method call, if any. */
56+
Method getStaticTarget() { result = super.getStaticTarget() }
4757
}
4858

4959
/**
5060
* A call expression that targets a closure.
5161
*
5262
* For closure calls, the static target never exists.
5363
*/
54-
final class ClosureCall extends CallExpr {
55-
ClosureCall() {
56-
exists(Expr receiver | receiver = this.getFunction() |
57-
// All calls to complex expressions and local variable accesses are lambda calls
58-
receiver instanceof PathExpr implies receiver = any(Variable v).getAnAccess()
59-
)
60-
}
64+
final class ClosureCall extends FunctionCall, CallExpr {
65+
ClosureCall() { isClosureCallExpr(this) }
6166
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/**
2+
* This module provides the public class `Method`.
3+
*/
4+
5+
private import rust
6+
7+
/**
8+
* A method declaration. For example
9+
* ```rust
10+
* fn foo(self, x: u32) -> u64 { (x + 1).into() }
11+
* ```
12+
*
13+
* A method declaration within a trait might not have a body:
14+
* ```rust
15+
* trait Trait {
16+
* fn bar(self);
17+
* }
18+
* ```
19+
*/
20+
final class Method extends Function {
21+
Method() { this.hasSelfParam() }
22+
}

rust/ql/lib/codeql/rust/internal/TypeInference.qll

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -230,11 +230,6 @@ module Consistency {
230230
}
231231
}
232232

233-
/** A method, that is, a function with a `self` parameter. */
234-
private class Method extends Function {
235-
Method() { this.hasSelfParam() }
236-
}
237-
238233
/** A function without a `self` parameter. */
239234
private class NonMethodFunction extends Function {
240235
NonMethodFunction() { not this.hasSelfParam() }

rust/ql/lib/rust.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ import codeql.rust.elements.NamedFormatArgument
1919
import codeql.rust.elements.PositionalFormatArgument
2020
import codeql.rust.elements.RangeExprExt
2121
import codeql.rust.elements.Call
22+
import codeql.rust.elements.Method

0 commit comments

Comments
 (0)