mirror of
https://github.com/github/codeql.git
synced 2026-04-24 00:05:14 +02:00
Merge pull request #16759 from michaelnebel/modelgen/sourcesinkmodelgen
C#/Java: Introduce source and sink model generation sanitisers.
This commit is contained in:
@@ -145,7 +145,7 @@ private class TaintStore extends TaintState, TTaintStore {
|
||||
*
|
||||
* This can be used to generate Flow summaries for APIs from parameter to return.
|
||||
*/
|
||||
module ThroughFlowConfig implements DataFlow::StateConfigSig {
|
||||
module PropagateFlowConfig implements DataFlow::StateConfigSig {
|
||||
class FlowState = TaintState;
|
||||
|
||||
predicate isSource(DataFlow::Node source, FlowState state) {
|
||||
@@ -190,14 +190,14 @@ module ThroughFlowConfig implements DataFlow::StateConfigSig {
|
||||
}
|
||||
}
|
||||
|
||||
private module ThroughFlow = TaintTracking::GlobalWithState<ThroughFlowConfig>;
|
||||
private module PropagateFlow = TaintTracking::GlobalWithState<PropagateFlowConfig>;
|
||||
|
||||
/**
|
||||
* Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter.
|
||||
*/
|
||||
string captureThroughFlow(DataFlowTargetApi api) {
|
||||
exists(DataFlow::ParameterNode p, ReturnNodeExt returnNodeExt, string input, string output |
|
||||
ThroughFlow::flow(p, returnNodeExt) and
|
||||
PropagateFlow::flow(p, returnNodeExt) and
|
||||
returnNodeExt.(DataFlow::Node).getEnclosingCallable() = api and
|
||||
input = parameterNodeAsInput(p) and
|
||||
output = returnNodeExt.getOutput() and
|
||||
@@ -213,8 +213,13 @@ string captureThroughFlow(DataFlowTargetApi api) {
|
||||
* This can be used to generate Source summaries for an API, if the API expose an already known source
|
||||
* via its return (then the API itself becomes a source).
|
||||
*/
|
||||
module FromSourceConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { ExternalFlow::sourceNode(source, _) }
|
||||
module PropagateFromSourceConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(string kind |
|
||||
isRelevantSourceKind(kind) and
|
||||
ExternalFlow::sourceNode(source, kind)
|
||||
)
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(DataFlowTargetApi c |
|
||||
@@ -225,22 +230,26 @@ module FromSourceConfig implements DataFlow::ConfigSig {
|
||||
|
||||
DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSinkCallContext }
|
||||
|
||||
predicate isBarrier(DataFlow::Node n) {
|
||||
exists(Type t | t = n.getType() and not isRelevantType(t))
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
isRelevantTaintStep(node1, node2)
|
||||
}
|
||||
}
|
||||
|
||||
private module FromSource = TaintTracking::Global<FromSourceConfig>;
|
||||
private module PropagateFromSource = TaintTracking::Global<PropagateFromSourceConfig>;
|
||||
|
||||
/**
|
||||
* Gets the source model(s) of `api`, if there is flow from an existing known source to the return of `api`.
|
||||
*/
|
||||
string captureSource(DataFlowTargetApi api) {
|
||||
exists(DataFlow::Node source, ReturnNodeExt sink, string kind |
|
||||
FromSource::flow(source, sink) and
|
||||
PropagateFromSource::flow(source, sink) and
|
||||
ExternalFlow::sourceNode(source, kind) and
|
||||
api = sink.getEnclosingCallable() and
|
||||
isRelevantSourceKind(kind) and
|
||||
not irrelevantSourceSinkApi(source.getEnclosingCallable(), api) and
|
||||
result = ModelPrinting::asSourceModel(api, sink.getOutput(), kind)
|
||||
)
|
||||
}
|
||||
@@ -255,9 +264,15 @@ string captureSource(DataFlowTargetApi api) {
|
||||
module PropagateToSinkConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { apiSource(source) }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { ExternalFlow::sinkNode(sink, _) }
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(string kind | isRelevantSinkKind(kind) and ExternalFlow::sinkNode(sink, kind))
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { sinkModelSanitizer(node) }
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
exists(Type t | t = node.getType() and not isRelevantType(t))
|
||||
or
|
||||
sinkModelSanitizer(node)
|
||||
}
|
||||
|
||||
DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSourceCallContext }
|
||||
|
||||
@@ -276,7 +291,6 @@ string captureSink(DataFlowTargetApi api) {
|
||||
PropagateToSink::flow(src, sink) and
|
||||
ExternalFlow::sinkNode(sink, kind) and
|
||||
api = src.getEnclosingCallable() and
|
||||
isRelevantSinkKind(kind) and
|
||||
result = ModelPrinting::asSinkModel(api, asInputArgument(src), kind)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -278,6 +278,12 @@ predicate apiSource(DataFlow::Node source) {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if it is not relevant to generate a source model for `api`, even
|
||||
* if flow is detected from a node within `source` to a sink within `api`.
|
||||
*/
|
||||
predicate irrelevantSourceSinkApi(Callable source, TargetApiSpecific api) { none() }
|
||||
|
||||
/**
|
||||
* Gets the MaD input string representation of `source`.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user