Skip to content

Commit cd49df0

Browse files
authored
Merge pull request #18784 from paldepind/rust-generate-sources-sinks
Rust: Generate sources and sinks
2 parents 22ed2e5 + a253b77 commit cd49df0

File tree

11 files changed

+83
-8
lines changed

11 files changed

+83
-8
lines changed

Diff for: rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll

+3
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,9 @@ module Node {
319319
n.getAstNode() = pos.getParameterIn(c.asCfgScope().(Callable).getParamList())
320320
}
321321

322+
/** Get the parameter position of this parameter. */
323+
ParameterPosition getPosition() { this.isParameterOf(_, result) }
324+
322325
/** Gets the parameter in the CFG that this node corresponds to. */
323326
ParamBaseCfgNode getParameter() { result = n }
324327
}

Diff for: rust/ql/src/utils/modelgenerator/internal/CaptureModels.qll

+12-7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ private import rust
33
private import rust as R
44
private import codeql.rust.dataflow.DataFlow
55
private import codeql.rust.dataflow.internal.DataFlowImpl
6+
private import codeql.rust.dataflow.FlowSource as FlowSource
7+
private import codeql.rust.dataflow.FlowSink as FlowSink
68
private import codeql.rust.dataflow.internal.TaintTrackingImpl
79
private import codeql.mad.modelgenerator.internal.ModelGeneratorImpl
810
private import codeql.rust.dataflow.internal.FlowSummaryImpl as FlowSummary
@@ -105,14 +107,19 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, RustDataF
105107

106108
predicate sinkModelSanitizer(DataFlow::Node node) { none() }
107109

108-
predicate apiSource(DataFlow::Node source) { none() }
110+
/**
111+
* Holds if `source` is an API entrypoint, i.e., a source of input where data
112+
* can flow in to a library. This is used for creating sink models, as we
113+
* only want to mark functions as sinks if input to the function can reach
114+
* (from an input source) a known sink.
115+
*/
116+
predicate apiSource(DataFlow::Node source) { source instanceof DataFlow::ParameterNode }
109117

110118
bindingset[sourceEnclosing, api]
111119
predicate irrelevantSourceSinkApi(Callable sourceEnclosing, SourceTargetApi api) { none() }
112120

113121
string getInputArgument(DataFlow::Node source) {
114-
// TODO: Implement when we want to generate sources and sinks
115-
result = "getInputArgument(" + source + ")"
122+
result = "Argument[" + source.(Node::SourceParameterNode).getPosition().toString() + "]"
116123
}
117124

118125
bindingset[kind]
@@ -174,11 +181,9 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, RustDataF
174181

175182
string partialNeutralModelRow(Callable api, int i) { result = partialModelRow(api, i) }
176183

177-
// TODO: Implement this when we want to generate sources.
178-
predicate sourceNode(DataFlow::Node node, string kind) { none() }
184+
predicate sourceNode(DataFlow::Node node, string kind) { FlowSource::sourceNode(node, kind) }
179185

180-
// TODO: Implement this when we want to generate sinks.
181-
predicate sinkNode(DataFlow::Node node, string kind) { none() }
186+
predicate sinkNode(DataFlow::Node node, string kind) { FlowSink::sinkNode(node, kind) }
182187
}
183188

184189
import MakeModelGenerator<Location, RustDataFlow, RustTaintTracking, ModelGeneratorInput>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
unexpectedModel
2+
expectedModel
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
extensions:
2+
- addsTo:
3+
pack: codeql/rust-all
4+
extensible: sinkModel
5+
data:
6+
- ["repo::test", "crate::sinks::known_sink", "Argument[0]", "test-sink", "manual"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import rust
2+
import utils.modelgenerator.internal.CaptureModels
3+
import utils.test.InlineMadTest
4+
5+
module InlineMadTestConfig implements InlineMadTestConfigSig {
6+
string getCapturedModel(Function f) { result = captureSink(f) }
7+
8+
string getKind() { result = "sink" }
9+
}
10+
11+
import InlineMadTest<InlineMadTestConfig>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
unexpectedModel
2+
expectedModel
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
extensions:
2+
- addsTo:
3+
pack: codeql/rust-all
4+
extensible: sourceModel
5+
data:
6+
- ["repo::test", "crate::sources::known_source", "ReturnValue", "test-source", "manual"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import rust
2+
import utils.modelgenerator.internal.CaptureModels
3+
import utils.test.InlineMadTest
4+
import codeql.rust.dataflow.internal.ModelsAsData
5+
6+
module InlineMadTestConfig implements InlineMadTestConfigSig {
7+
string getCapturedModel(Function c) { result = captureSource(c) }
8+
9+
string getKind() { result = "source" }
10+
}
11+
12+
import InlineMadTest<InlineMadTestConfig>

Diff for: rust/ql/test/utils-tests/modelgenerator/CaptureSummaryModels.ql

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import utils.modelgenerator.internal.CaptureModels
33
import utils.test.InlineMadTest
44

55
module InlineMadTestConfig implements InlineMadTestConfigSig {
6-
string getCapturedModel(Function c) { result = ContentSensitive::captureFlow(c, _) }
6+
string getCapturedModel(Function f) { result = ContentSensitive::captureFlow(f, _) }
77

88
string getKind() { result = "summary" }
99
}

Diff for: rust/ql/test/utils-tests/modelgenerator/sinks.rs

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// A manually modeled sink
2+
fn known_sink(n: i64) {
3+
()
4+
}
5+
6+
// sink=repo::test;crate::sinks::derived_sink;Argument[1];test-sink;df-generated
7+
pub fn derived_sink(c: bool, n: i64) -> i64 {
8+
if c {
9+
known_sink(n);
10+
1
11+
} else {
12+
0
13+
}
14+
}

Diff for: rust/ql/test/utils-tests/modelgenerator/sources.rs

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// A manually modeled source
2+
fn known_source(n: i64) -> i64 {
3+
n
4+
}
5+
6+
// source=repo::test;crate::sources::derived_source;ReturnValue;test-source;df-generated
7+
// summary=repo::test;crate::sources::derived_source;Argument[1];ReturnValue;value;dfc-generated
8+
pub fn derived_source(c: bool, n: i64) -> i64 {
9+
if c {
10+
known_source(n)
11+
} else {
12+
0
13+
}
14+
}

0 commit comments

Comments
 (0)