Merge pull request #18784 from paldepind/rust-generate-sources-sinks

Rust: Generate sources and sinks
This commit is contained in:
Simon Friis Vindum
2025-02-20 15:59:58 +01:00
committed by GitHub
11 changed files with 83 additions and 8 deletions

View File

@@ -319,6 +319,9 @@ module Node {
n.getAstNode() = pos.getParameterIn(c.asCfgScope().(Callable).getParamList())
}
/** Get the parameter position of this parameter. */
ParameterPosition getPosition() { this.isParameterOf(_, result) }
/** Gets the parameter in the CFG that this node corresponds to. */
ParamBaseCfgNode getParameter() { result = n }
}

View File

@@ -3,6 +3,8 @@ private import rust
private import rust as R
private import codeql.rust.dataflow.DataFlow
private import codeql.rust.dataflow.internal.DataFlowImpl
private import codeql.rust.dataflow.FlowSource as FlowSource
private import codeql.rust.dataflow.FlowSink as FlowSink
private import codeql.rust.dataflow.internal.TaintTrackingImpl
private import codeql.mad.modelgenerator.internal.ModelGeneratorImpl
private import codeql.rust.dataflow.internal.FlowSummaryImpl as FlowSummary
@@ -105,14 +107,19 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, RustDataF
predicate sinkModelSanitizer(DataFlow::Node node) { none() }
predicate apiSource(DataFlow::Node source) { none() }
/**
* Holds if `source` is an API entrypoint, i.e., a source of input where data
* can flow in to a library. This is used for creating sink models, as we
* only want to mark functions as sinks if input to the function can reach
* (from an input source) a known sink.
*/
predicate apiSource(DataFlow::Node source) { source instanceof DataFlow::ParameterNode }
bindingset[sourceEnclosing, api]
predicate irrelevantSourceSinkApi(Callable sourceEnclosing, SourceTargetApi api) { none() }
string getInputArgument(DataFlow::Node source) {
// TODO: Implement when we want to generate sources and sinks
result = "getInputArgument(" + source + ")"
result = "Argument[" + source.(Node::SourceParameterNode).getPosition().toString() + "]"
}
bindingset[kind]
@@ -174,11 +181,9 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, RustDataF
string partialNeutralModelRow(Callable api, int i) { result = partialModelRow(api, i) }
// TODO: Implement this when we want to generate sources.
predicate sourceNode(DataFlow::Node node, string kind) { none() }
predicate sourceNode(DataFlow::Node node, string kind) { FlowSource::sourceNode(node, kind) }
// TODO: Implement this when we want to generate sinks.
predicate sinkNode(DataFlow::Node node, string kind) { none() }
predicate sinkNode(DataFlow::Node node, string kind) { FlowSink::sinkNode(node, kind) }
}
import MakeModelGenerator<Location, RustDataFlow, RustTaintTracking, ModelGeneratorInput>

View File

@@ -0,0 +1,2 @@
unexpectedModel
expectedModel

View File

@@ -0,0 +1,6 @@
extensions:
- addsTo:
pack: codeql/rust-all
extensible: sinkModel
data:
- ["repo::test", "crate::sinks::known_sink", "Argument[0]", "test-sink", "manual"]

View File

@@ -0,0 +1,11 @@
import rust
import utils.modelgenerator.internal.CaptureModels
import utils.test.InlineMadTest
module InlineMadTestConfig implements InlineMadTestConfigSig {
string getCapturedModel(Function f) { result = captureSink(f) }
string getKind() { result = "sink" }
}
import InlineMadTest<InlineMadTestConfig>

View File

@@ -0,0 +1,2 @@
unexpectedModel
expectedModel

View File

@@ -0,0 +1,6 @@
extensions:
- addsTo:
pack: codeql/rust-all
extensible: sourceModel
data:
- ["repo::test", "crate::sources::known_source", "ReturnValue", "test-source", "manual"]

View File

@@ -0,0 +1,12 @@
import rust
import utils.modelgenerator.internal.CaptureModels
import utils.test.InlineMadTest
import codeql.rust.dataflow.internal.ModelsAsData
module InlineMadTestConfig implements InlineMadTestConfigSig {
string getCapturedModel(Function c) { result = captureSource(c) }
string getKind() { result = "source" }
}
import InlineMadTest<InlineMadTestConfig>

View File

@@ -3,7 +3,7 @@ import utils.modelgenerator.internal.CaptureModels
import utils.test.InlineMadTest
module InlineMadTestConfig implements InlineMadTestConfigSig {
string getCapturedModel(Function c) { result = ContentSensitive::captureFlow(c, _) }
string getCapturedModel(Function f) { result = ContentSensitive::captureFlow(f, _) }
string getKind() { result = "summary" }
}

View File

@@ -0,0 +1,14 @@
// A manually modeled sink
fn known_sink(n: i64) {
()
}
// sink=repo::test;crate::sinks::derived_sink;Argument[1];test-sink;df-generated
pub fn derived_sink(c: bool, n: i64) -> i64 {
if c {
known_sink(n);
1
} else {
0
}
}

View File

@@ -0,0 +1,14 @@
// A manually modeled source
fn known_source(n: i64) -> i64 {
n
}
// source=repo::test;crate::sources::derived_source;ReturnValue;test-source;df-generated
// summary=repo::test;crate::sources::derived_source;Argument[1];ReturnValue;value;dfc-generated
pub fn derived_source(c: bool, n: i64) -> i64 {
if c {
known_source(n)
} else {
0
}
}