Skip to content

Commit d41290b

Browse files
committed
wip
1 parent f2abf80 commit d41290b

File tree

13 files changed

+100
-95
lines changed

13 files changed

+100
-95
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ predicate lambdaCreationExpr(Expr creation) {
290290
* Holds if `call` is a lambda call of kind `kind` where `receiver` is the
291291
* invoked expression.
292292
*/
293-
predicate lambdaCallExpr(ClosureCall call, LambdaCallKind kind, Expr receiver) {
293+
predicate lambdaCallExpr(ClosureCallExpr call, LambdaCallKind kind, Expr receiver) {
294294
receiver = call.getClosureExpr() and
295295
exists(kind)
296296
}
@@ -823,7 +823,7 @@ module RustDataFlow implements InputSig<Location> {
823823
*/
824824
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
825825
(
826-
receiver.asExpr() = call.asCall().(ClosureCall).getClosureExpr()
826+
receiver.asExpr() = call.asCall().(ClosureCallExpr).getClosureExpr()
827827
or
828828
call.isSummaryCall(_, receiver.(FlowSummaryNode).getSummaryNode())
829829
) and

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

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,6 @@ private import internal.CallImpl
77

88
final class Call = Impl::Call;
99

10-
// todo: remove once internal query has been updated
11-
final class CallExpr extends ParenArgsExpr {
12-
Expr getFunction() { result = this.getBase() }
13-
14-
Expr getArg(int i) { result = this.getArgument(i) }
15-
16-
int getNumberOfArgs() { result = this.getNumberOfArguments() }
17-
}
18-
19-
private predicate isClosureCall(ParenArgsExpr call) {
20-
exists(Expr receiver | receiver = call.getBase() |
21-
// All calls to complex expressions and local variable accesses are lambda calls
22-
receiver instanceof PathExpr implies receiver = any(Variable v).getAnAccess()
23-
)
24-
}
25-
2610
private predicate isGuaranteedMethodCall(ArgsExpr call) {
2711
call instanceof MethodCallExpr
2812
or
@@ -36,7 +20,7 @@ private predicate isGuaranteedMethodCall(ArgsExpr call) {
3620
*
3721
* Either
3822
*
39-
* - a `ParenArgsExpr` where we can resolve the target as a method,
23+
* - a `CallExpr` where we can resolve the target as a method,
4024
* - a `MethodCallExpr`,
4125
* - an `Operation` that targets an overloadable opeator, or
4226
* - an `IndexExpr`.
@@ -51,16 +35,3 @@ final class MethodCall extends Call {
5135
/** Gets the static target of this method call, if any. */
5236
Method getStaticTarget() { result = super.getStaticTarget() }
5337
}
54-
55-
/**
56-
* A call expression that targets a closure.
57-
*
58-
* Closure calls never have a static target, and the set of potential
59-
* run-time targets is only available internally to the data flow library.
60-
*/
61-
final class ClosureCall extends Call instanceof ParenArgsExpr {
62-
ClosureCall() { isClosureCall(this) }
63-
64-
/** Gets the closure expression being called. */
65-
Expr getClosureExpr() { result = super.getBase() }
66-
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* This module provides the public class `CallExpr`.
3+
*/
4+
5+
private import rust
6+
private import internal.CallExprImpl
7+
8+
final class CallExpr = Impl::CallExpr;
9+
10+
final class ClosureCallExpr = Impl::ClosureCallExpr;

rust/ql/lib/codeql/rust/elements/internal/ArgsExprImpl.qll

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,6 @@ module Impl {
1919
/** Gets the number of positional arguments of this expression. */
2020
int getNumberOfArguments() { result = count(Expr arg | arg = this.getArgument(_)) }
2121

22-
/**
23-
* Gets the receiver of this expression, if any.
24-
*
25-
* This is either an actual receiver of a method call, the first operand of an operation,
26-
* or the base expression of an index expression.
27-
*/
28-
Expr getReceiver() { none() }
29-
3022
/** Gets the resolved target (function or tuple struct/variant) of this call, if any. */
3123
Addressable getResolvedTarget() { result = TypeInference::resolveCallTarget(this) }
3224
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/**
2+
* INTERNAL: This module contains the customizable definition of `CallExpr` and should not
3+
* be referenced directly.
4+
*/
5+
module Impl {
6+
private import rust
7+
private import codeql.rust.elements.internal.CallImpl::Impl as CallImpl
8+
private import codeql.rust.elements.internal.ParenArgsExprImpl::Impl as ParenArgsExprImpl
9+
private import codeql.rust.internal.TypeInference as TypeInference
10+
11+
private predicate isClosureCall(ParenArgsExpr call) {
12+
exists(Expr receiver | receiver = call.getBase() |
13+
// All calls to complex expressions and local variable accesses are lambda calls
14+
receiver instanceof PathExpr implies receiver = any(Variable v).getAnAccess()
15+
)
16+
}
17+
18+
/**
19+
* A call expression. For example:
20+
* ```rust
21+
* foo(42);
22+
* foo::<u32, u64>(42);
23+
* foo[0](42);
24+
* foo(1) = 4;
25+
* ```
26+
*/
27+
class CallExpr extends CallImpl::Call, ParenArgsExprImpl::ParenArgsExpr {
28+
CallExpr() {
29+
forall(Addressable target |
30+
// Cannot use `this.getResolvedTarget()` as that results in non-monotonic recursion
31+
target = TypeInference::resolveCallTarget(this)
32+
|
33+
target instanceof Callable
34+
)
35+
or
36+
isClosureCall(this)
37+
}
38+
39+
private predicate isMethodCall() { this.getResolvedTarget() instanceof Method }
40+
41+
override Expr getArgument(int i) {
42+
if this.isMethodCall()
43+
then result = super.getArgList().getArg(i + 1)
44+
else result = super.getArgList().getArg(i)
45+
}
46+
47+
override Expr getReceiver() { this.isMethodCall() and result = super.getArgList().getArg(0) }
48+
49+
// todo: remove once internal query has been updated
50+
Expr getFunction() { result = this.getBase() }
51+
52+
// todo: remove once internal query has been updated
53+
Expr getArg(int i) { result = this.getArgument(i) }
54+
55+
// todo: remove once internal query has been updated
56+
int getNumberOfArgs() { result = this.getNumberOfArguments() }
57+
}
58+
59+
/**
60+
* A call expression that targets a closure.
61+
*
62+
* Closure calls never have a static target, and the set of potential
63+
* run-time targets is only available internally to the data flow library.
64+
*/
65+
class ClosureCallExpr extends CallExpr {
66+
ClosureCallExpr() { isClosureCall(this) }
67+
68+
/** Gets the closure expression being called. */
69+
Expr getClosureExpr() { result = super.getBase() }
70+
}
71+
}

rust/ql/lib/codeql/rust/elements/internal/CallImpl.qll

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,25 @@ private import rust
33
module Impl {
44
private import codeql.rust.internal.TypeInference as TypeInference
55
private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl
6+
private import codeql.rust.elements.internal.ArgsExprImpl::Impl as ArgsExprImpl
67

78
/**
89
* A call.
910
*
1011
* Either
1112
*
12-
* - a `ParenArgsExpr` that targets a function,
13+
* - a `CallExpr`,
1314
* - a `MethodCallExpr`,
1415
* - an `Operation` that targets an overloadable opeator, or
1516
* - an `IndexExpr`.
1617
*/
17-
abstract class Call extends ExprImpl::Expr {
18-
/** Gets the `i`th positional argument of this call, if any. */
19-
Expr getArgument(int i) { none() }
20-
21-
// todo: remove once internal query has been updated
22-
Expr getArg(int i) { result = this.getArgument(i) }
23-
24-
/** Gets a positional argument of this call, if any. */
25-
Expr getAnArgument() { result = this.getArgument(_) }
26-
27-
/** Gets the number of positional arguments of this call. */
28-
int getNumberOfArguments() { result = count(Expr arg | arg = this.getArgument(_)) }
29-
30-
// todo: remove once internal query has been updated
31-
int getNumberOfArgs() { result = this.getNumberOfArguments() }
32-
18+
abstract class Call extends ArgsExprImpl::ArgsExpr {
3319
/**
3420
* Gets the receiver of this call, if any.
3521
*
36-
* This is either an actual receiver of a method call, the first operand of an operation,
22+
* This is either an actual receiver of a method call, the first argument of a call
23+
* to a method
24+
* the first operand of an operation,
3725
* or the base expression of an index expression.
3826
*/
3927
Expr getReceiver() { none() }

rust/ql/lib/codeql/rust/elements/internal/IndexExprImpl.qll

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,4 @@ module Impl {
3232

3333
override Expr getReceiver() { result = this.getBase() }
3434
}
35-
36-
private class IndexArgsExpr extends ArgsExprImpl::ArgsExpr instanceof IndexExpr {
37-
override Expr getArgument(int i) { result = IndexExpr.super.getArgument(i) }
38-
39-
override Expr getReceiver() { result = IndexExpr.super.getReceiver() }
40-
}
4135
}

rust/ql/lib/codeql/rust/elements/internal/MethodCallExprImpl.qll

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,4 @@ module Impl {
4949

5050
override Expr getReceiver() { result = Generated::MethodCallExpr.super.getReceiver() }
5151
}
52-
53-
private class MethodCallArgsExpr extends ArgsExprImpl::ArgsExpr instanceof MethodCallExpr {
54-
override Expr getArgument(int i) { result = MethodCallExpr.super.getArgument(i) }
55-
56-
override Expr getReceiver() { result = MethodCallExpr.super.getReceiver() }
57-
}
5852
}

rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,10 @@ module Impl {
115115
/** Gets the `n`th operand of this operation, if any. */
116116
abstract Expr getOperand(int n);
117117

118-
override Expr getArgument(int i) { result = this.getOperand(i + 1) and i >= 0 }
119-
120-
override Expr getReceiver() { result = this.getOperand(0) }
118+
override Expr getArgument(int i) {
119+
not this.isOverloaded(_, _, _) and
120+
result = this.getOperand(i)
121+
}
121122

122123
/**
123124
* Gets the number of operands of this operation.
@@ -142,8 +143,8 @@ module Impl {
142143
private class CallOperation extends CallImpl::Call instanceof Operation {
143144
CallOperation() { super.isOverloaded(_, _, _) }
144145

145-
override Expr getArgument(int i) { result = Operation.super.getArgument(i) }
146+
override Expr getArgument(int i) { result = super.getOperand(i + 1) and i >= 0 }
146147

147-
override Expr getReceiver() { result = Operation.super.getReceiver() }
148+
override Expr getReceiver() { result = super.getOperand(0) }
148149
}
149150
}

rust/ql/lib/codeql/rust/elements/internal/ParenArgsExprImpl.qll

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ private import codeql.rust.elements.internal.generated.ParenArgsExpr
1212
*/
1313
module Impl {
1414
private import rust
15-
private import codeql.rust.elements.internal.CallImpl::Impl as CallImpl
1615
private import codeql.rust.elements.internal.ArgsExprImpl::Impl as ArgsExprImpl
1716
private import codeql.rust.internal.PathResolution as PathResolution
1817

@@ -66,20 +65,4 @@ module Impl {
6665
)
6766
}
6867
}
69-
70-
private class ParenArgsCallExpr extends CallImpl::Call instanceof ParenArgsExpr {
71-
ParenArgsCallExpr() {
72-
forall(Addressable target | target = super.getResolvedTarget() | target instanceof Callable)
73-
}
74-
75-
private predicate isMethodCall() { super.getResolvedTarget() instanceof Method }
76-
77-
override Expr getArgument(int i) {
78-
if this.isMethodCall()
79-
then result = super.getArgList().getArg(i + 1)
80-
else result = super.getArgList().getArg(i)
81-
}
82-
83-
override Expr getReceiver() { this.isMethodCall() and result = super.getArgList().getArg(0) }
84-
}
8568
}

0 commit comments

Comments
 (0)