Skip to content

Commit 278d251

Browse files
authored
Merge pull request #19107 from hvitved/rust/mad-argument-source
Rust: Support `Argument[x]` MaD source definitions
2 parents 3ad4de4 + b492647 commit 278d251

File tree

5 files changed

+112
-64
lines changed

5 files changed

+112
-64
lines changed

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

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@ final class DataFlowCall extends TDataFlowCall {
9090
}
9191

9292
/**
93-
* The position of a parameter or an argument in a function or call.
93+
* The position of a parameter in a function.
9494
*
95-
* As there is a 1-to-1 correspondence between parameter positions and
96-
* arguments positions in Rust we use the same type for both.
95+
* In Rust there is a 1-to-1 correspondence between parameter positions and
96+
* arguments positions, so we use the same underlying type for both.
9797
*/
9898
final class ParameterPosition extends TParameterPosition {
9999
/** Gets the underlying integer position, if any. */
@@ -126,6 +126,22 @@ final class ParameterPosition extends TParameterPosition {
126126
}
127127
}
128128

129+
/**
130+
* The position of an argument in a call.
131+
*
132+
* In Rust there is a 1-to-1 correspondence between parameter positions and
133+
* arguments positions, so we use the same underlying type for both.
134+
*/
135+
final class ArgumentPosition extends ParameterPosition {
136+
/** Gets the argument of `call` at this position, if any. */
137+
Expr getArgument(CallExprBase call) {
138+
result = call.getArgList().getArg(this.getPosition())
139+
or
140+
this.isSelf() and
141+
result = call.(MethodCallExpr).getReceiver()
142+
}
143+
}
144+
129145
/** Holds if `call` invokes a qualified path that resolves to a method. */
130146
private predicate callToMethod(CallExpr call) {
131147
exists(Path path |
@@ -432,6 +448,8 @@ private module Aliases {
432448

433449
class ParameterPositionAlias = ParameterPosition;
434450

451+
class ArgumentPositionAlias = ArgumentPosition;
452+
435453
class ContentAlias = Content;
436454

437455
class ContentSetAlias = ContentSet;
@@ -550,7 +568,7 @@ module RustDataFlow implements InputSig<Location> {
550568

551569
class ParameterPosition = ParameterPositionAlias;
552570

553-
class ArgumentPosition = ParameterPosition;
571+
class ArgumentPosition = ArgumentPositionAlias;
554572

555573
/**
556574
* Holds if the parameter position `ppos` matches the argument position

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

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ module Input implements InputSig<Location, RustDataFlow> {
5858

5959
string encodeParameterPosition(ParameterPosition pos) { result = pos.toString() }
6060

61-
predicate encodeArgumentPosition = encodeParameterPosition/1;
61+
string encodeArgumentPosition(RustDataFlow::ArgumentPosition pos) {
62+
result = encodeParameterPosition(pos)
63+
}
6264

6365
string encodeContent(ContentSet cs, string arg) {
6466
exists(Content c | cs = TSingletonContentSet(c) |
@@ -146,17 +148,21 @@ private module StepsInput implements Impl::Private::StepsInputSig {
146148
RustDataFlow::Node getSourceNode(Input::SourceBase source, Impl::Private::SummaryComponent sc) {
147149
sc = Impl::Private::SummaryComponent::return(_) and
148150
result.asExpr().getExpr() = source.getCall()
151+
or
152+
exists(CallExprBase call, Expr arg, ArgumentPosition pos |
153+
result.(RustDataFlow::PostUpdateNode).getPreUpdateNode().asExpr().getExpr() = arg and
154+
sc = Impl::Private::SummaryComponent::argument(pos) and
155+
call = source.getCall() and
156+
arg = pos.getArgument(call)
157+
)
149158
}
150159

151160
RustDataFlow::Node getSinkNode(Input::SinkBase sink, Impl::Private::SummaryComponent sc) {
152-
exists(CallExprBase call, Expr arg, ParameterPosition pos |
161+
exists(CallExprBase call, Expr arg, ArgumentPosition pos |
153162
result.asExpr().getExpr() = arg and
154163
sc = Impl::Private::SummaryComponent::argument(pos) and
155-
call = sink.getCall()
156-
|
157-
arg = call.getArgList().getArg(pos.getPosition())
158-
or
159-
arg = call.(MethodCallExpr).getReceiver() and pos.isSelf()
164+
call = sink.getCall() and
165+
arg = pos.getArgument(call)
160166
)
161167
}
162168
}

rust/ql/test/library-tests/dataflow/models/main.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,15 @@ fn test_simple_sink() {
279279
simple_sink(s); // $ hasValueFlow=17
280280
}
281281

282+
// has a source model
283+
fn arg_source(i: i64) {}
284+
285+
fn test_arg_source() {
286+
let i = 19;
287+
arg_source(i);
288+
sink(i) // $ hasValueFlow=i
289+
}
290+
282291
#[tokio::main]
283292
async fn main() {
284293
test_identify();
@@ -299,5 +308,6 @@ async fn main() {
299308
test_simple_source();
300309
test_simple_sink();
301310
test_get_async_number().await;
311+
test_arg_source();
302312
let dummy = Some(0); // ensure that the the `lang:core` crate is extracted
303313
}

0 commit comments

Comments
 (0)