Skip to content

Commit 7bbf6f7

Browse files
committed
Shared: Pass SummaryComponentStack to isSource and getSourceType
1 parent 6ac0b9e commit 7bbf6f7

File tree

6 files changed

+156
-118
lines changed

6 files changed

+156
-118
lines changed

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

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ private import rust
66
private import codeql.dataflow.internal.FlowSummaryImpl
77
private import codeql.dataflow.internal.AccessPathSyntax as AccessPath
88
private import codeql.rust.dataflow.internal.DataFlowImpl
9+
private import codeql.rust.internal.PathResolution
910
private import codeql.rust.dataflow.FlowSummary
11+
private import codeql.rust.dataflow.Ssa
12+
private import codeql.rust.controlflow.CfgNodes
1013
private import Content
1114

1215
module Input implements InputSig<Location, RustDataFlow> {
@@ -133,16 +136,40 @@ private module StepsInput implements Impl::Private::StepsInputSig {
133136
result.asCallCfgNode().getCall().getStaticTarget() = sc
134137
}
135138

136-
RustDataFlow::Node getSourceNode(Input::SourceBase source, Impl::Private::SummaryComponent sc) {
137-
sc = Impl::Private::SummaryComponent::return(_) and
139+
/** Gets the argument of `source` described by `sc`, if any. */
140+
private Expr getSourceNodeArgument(Input::SourceBase source, Impl::Private::SummaryComponent sc) {
141+
exists(ArgumentPosition pos |
142+
sc = Impl::Private::SummaryComponent::argument(pos) and
143+
result = pos.getArgument(source.getCall())
144+
)
145+
}
146+
147+
/** Get the callable that `expr` refers to. */
148+
private Callable getCallable(Expr expr) {
149+
result = resolvePath(expr.(PathExpr).getPath()).(Function)
150+
or
151+
result = expr.(ClosureExpr)
152+
or
153+
// The expression is an SSA read of an assignment of a closure
154+
exists(Ssa::Definition def, ExprCfgNode value |
155+
def.getARead().getAstNode() = expr and
156+
def.getAnUltimateDefinition().(Ssa::WriteDefinition).assigns(value) and
157+
result = value.getExpr().(ClosureExpr)
158+
)
159+
}
160+
161+
RustDataFlow::Node getSourceNode(Input::SourceBase source, Impl::Private::SummaryComponentStack s) {
162+
s.head() = Impl::Private::SummaryComponent::return(_) and
138163
result.asExpr().getExpr() = source.getCall()
139164
or
140-
exists(CallExprBase call, Expr arg, ArgumentPosition pos |
141-
result.(RustDataFlow::PostUpdateNode).getPreUpdateNode().asExpr().getExpr() = arg and
142-
sc = Impl::Private::SummaryComponent::argument(pos) and
143-
call = source.getCall() and
144-
arg = pos.getArgument(call)
165+
exists(ArgumentPosition pos, Expr arg |
166+
s.head() = Impl::Private::SummaryComponent::parameter(pos) and
167+
arg = getSourceNodeArgument(source, s.tail().head()) and
168+
result.asParameter() = getCallable(arg).getParam(pos.getPosition())
145169
)
170+
or
171+
result.(RustDataFlow::PostUpdateNode).getPreUpdateNode().asExpr().getExpr() =
172+
getSourceNodeArgument(source, s.head())
146173
}
147174

148175
RustDataFlow::Node getSinkNode(Input::SinkBase sink, Impl::Private::SummaryComponent sc) {

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -258,20 +258,20 @@ mod source_into_function {
258258
}
259259

260260
fn test_source_into_function() {
261-
let a = |a| sink(a); // $ MISSING: hasValueFlow=1
261+
let a = |a| sink(a); // $ hasValueFlow=1
262262
pass_source(1, a);
263263

264264
pass_source(2, |a| {
265-
sink(a); // $ MISSING: hasValueFlow=2
265+
sink(a); // $ hasValueFlow=2
266266
});
267267

268268
fn f(a: i64) {
269-
sink(a) // $ MISSING: hasValueFlow=3
269+
sink(a) // $ hasValueFlow=3
270270
}
271271
pass_source(3, f);
272272

273273
pass_source(4, async move |a| {
274-
sink(a); // $ MISSING: hasValueFlow=4
274+
sink(a); // $ hasValueFlow=4
275275
});
276276
}
277277
}

0 commit comments

Comments
 (0)