mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Merge pull request #12539 from michaelnebel/modelgenerator/configuration
Java/C#: Re-factor model generator taint tracking configurations to use the new API
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
|
||||
import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
|
||||
import internal.CaptureModels
|
||||
import internal.CaptureSummaryFlow
|
||||
import internal.CaptureSummaryFlowQuery
|
||||
|
||||
from DataFlowTargetApi api, string flow
|
||||
where
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
|
||||
import internal.CaptureModels
|
||||
import internal.CaptureSummaryFlow
|
||||
import internal.CaptureSummaryFlowQuery
|
||||
|
||||
from DataFlowTargetApi api, string noflow
|
||||
where
|
||||
|
||||
@@ -8,10 +8,6 @@
|
||||
|
||||
import internal.CaptureModels
|
||||
|
||||
class Activate extends ActiveConfiguration {
|
||||
override predicate activateToSinkConfig() { any() }
|
||||
}
|
||||
|
||||
from DataFlowTargetApi api, string sink
|
||||
where sink = captureSink(api)
|
||||
select sink order by sink
|
||||
|
||||
@@ -8,10 +8,6 @@
|
||||
|
||||
import internal.CaptureModels
|
||||
|
||||
class Activate extends ActiveConfiguration {
|
||||
override predicate activateFromSourceConfig() { any() }
|
||||
}
|
||||
|
||||
from DataFlowTargetApi api, string source
|
||||
where source = captureSource(api)
|
||||
select source order by source
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
|
||||
import internal.CaptureModels
|
||||
import internal.CaptureSummaryFlow
|
||||
import internal.CaptureSummaryFlowQuery
|
||||
|
||||
from DataFlowTargetApi api, string flow
|
||||
where flow = captureFlow(api) and not api.(FlowSummaryImpl::Public::SummarizedCallable).isManual()
|
||||
|
||||
@@ -5,14 +5,6 @@
|
||||
|
||||
private import CaptureModelsSpecific
|
||||
|
||||
class ActiveConfiguration extends Unit {
|
||||
predicate activateThroughFlowConfig() { none() }
|
||||
|
||||
predicate activateFromSourceConfig() { none() }
|
||||
|
||||
predicate activateToSinkConfig() { none() }
|
||||
}
|
||||
|
||||
class DataFlowTargetApi extends TargetApiSpecific {
|
||||
DataFlowTargetApi() { isRelevantForDataFlowModels(this) }
|
||||
}
|
||||
@@ -46,6 +38,20 @@ private predicate isRelevantContent(DataFlow::Content c) {
|
||||
DataFlowPrivate::containerContent(c)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MaD string representation of the parameter node `p`.
|
||||
*/
|
||||
string parameterNodeAsInput(DataFlow::ParameterNode p) {
|
||||
result = parameterAccess(p.asParameter())
|
||||
or
|
||||
result = qualifierString() and p instanceof InstanceParameterNode
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MaD input string representation of `source`.
|
||||
*/
|
||||
string asInputArgument(DataFlow::Node source) { result = asInputArgumentSpecific(source) }
|
||||
|
||||
/**
|
||||
* Gets the summary model for `api` with `input`, `output` and `kind`.
|
||||
*/
|
||||
@@ -111,61 +117,70 @@ string captureQualifierFlow(TargetApiSpecific api) {
|
||||
|
||||
private int accessPathLimit() { result = 2 }
|
||||
|
||||
private newtype TTaintState =
|
||||
TTaintRead(int n) { n in [0 .. accessPathLimit()] } or
|
||||
TTaintStore(int n) { n in [1 .. accessPathLimit()] }
|
||||
|
||||
abstract private class TaintState extends TTaintState {
|
||||
abstract string toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* A FlowState representing a tainted read.
|
||||
*/
|
||||
private class TaintRead extends DataFlow::FlowState {
|
||||
private class TaintRead extends TaintState, TTaintRead {
|
||||
private int step;
|
||||
|
||||
TaintRead() { this = "TaintRead(" + step + ")" and step in [0 .. accessPathLimit()] }
|
||||
TaintRead() { this = TTaintRead(step) }
|
||||
|
||||
/**
|
||||
* Gets the flow state step number.
|
||||
*/
|
||||
int getStep() { result = step }
|
||||
|
||||
override string toString() { result = "TaintRead(" + step + ")" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A FlowState representing a tainted write.
|
||||
*/
|
||||
private class TaintStore extends DataFlow::FlowState {
|
||||
private class TaintStore extends TaintState, TTaintStore {
|
||||
private int step;
|
||||
|
||||
TaintStore() { this = "TaintStore(" + step + ")" and step in [1 .. accessPathLimit()] }
|
||||
TaintStore() { this = TTaintStore(step) }
|
||||
|
||||
/**
|
||||
* Gets the flow state step number.
|
||||
*/
|
||||
int getStep() { result = step }
|
||||
|
||||
override string toString() { result = "TaintStore(" + step + ")" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A TaintTracking Configuration used for tracking flow through APIs.
|
||||
* A data-flow configuration for tracking flow through APIs.
|
||||
* The sources are the parameters of an API and the sinks are the return values (excluding `this`) and parameters.
|
||||
*
|
||||
* This can be used to generate Flow summaries for APIs from parameter to return.
|
||||
*/
|
||||
private class ThroughFlowConfig extends TaintTracking::Configuration {
|
||||
ThroughFlowConfig() {
|
||||
this = "ThroughFlowConfig" and any(ActiveConfiguration ac).activateThroughFlowConfig()
|
||||
}
|
||||
module ThroughFlowConfig implements DataFlow::StateConfigSig {
|
||||
class FlowState = TaintState;
|
||||
|
||||
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) {
|
||||
predicate isSource(DataFlow::Node source, FlowState state) {
|
||||
source instanceof DataFlow::ParameterNode and
|
||||
source.getEnclosingCallable() instanceof DataFlowTargetApi and
|
||||
state.(TaintRead).getStep() = 0
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) {
|
||||
predicate isSink(DataFlow::Node sink, FlowState state) {
|
||||
sink instanceof DataFlowImplCommon::ReturnNodeExt and
|
||||
not isOwnInstanceAccessNode(sink) and
|
||||
not exists(captureQualifierFlow(sink.asExpr().getEnclosingCallable())) and
|
||||
(state instanceof TaintRead or state instanceof TaintStore)
|
||||
}
|
||||
|
||||
override predicate isAdditionalTaintStep(
|
||||
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
|
||||
DataFlow::FlowState state2
|
||||
predicate isAdditionalFlowStep(
|
||||
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
|
||||
) {
|
||||
exists(DataFlowImplCommon::TypedContent tc |
|
||||
DataFlowImplCommon::store(node1, tc, node2, _) and
|
||||
@@ -184,24 +199,28 @@ private class ThroughFlowConfig extends TaintTracking::Configuration {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node n) {
|
||||
predicate isBarrier(DataFlow::Node n) {
|
||||
exists(Type t | t = n.getType() and not isRelevantType(t))
|
||||
}
|
||||
|
||||
override DataFlow::FlowFeature getAFeature() {
|
||||
predicate isBarrier(DataFlow::Node node, FlowState state) { none() }
|
||||
|
||||
DataFlow::FlowFeature getAFeature() {
|
||||
result instanceof DataFlow::FeatureEqualSourceSinkCallContext
|
||||
}
|
||||
}
|
||||
|
||||
private module ThroughFlow = TaintTracking::MakeWithState<ThroughFlowConfig>;
|
||||
|
||||
/**
|
||||
* Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter.
|
||||
*/
|
||||
string captureThroughFlow(DataFlowTargetApi api) {
|
||||
exists(
|
||||
ThroughFlowConfig config, DataFlow::ParameterNode p,
|
||||
DataFlowImplCommon::ReturnNodeExt returnNodeExt, string input, string output
|
||||
DataFlow::ParameterNode p, DataFlowImplCommon::ReturnNodeExt returnNodeExt, string input,
|
||||
string output
|
||||
|
|
||||
config.hasFlow(p, returnNodeExt) and
|
||||
ThroughFlow::hasFlow(p, returnNodeExt) and
|
||||
returnNodeExt.getEnclosingCallable() = api and
|
||||
input = parameterNodeAsInput(p) and
|
||||
output = returnNodeAsOutput(returnNodeExt) and
|
||||
@@ -211,41 +230,37 @@ string captureThroughFlow(DataFlowTargetApi api) {
|
||||
}
|
||||
|
||||
/**
|
||||
* A TaintTracking Configuration used for tracking flow through APIs.
|
||||
* A dataflow configuration used for finding new sources.
|
||||
* The sources are the already known existing sources and the sinks are the API return nodes.
|
||||
*
|
||||
* 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).
|
||||
*/
|
||||
private class FromSourceConfiguration extends TaintTracking::Configuration {
|
||||
FromSourceConfiguration() {
|
||||
this = "FromSourceConfiguration" and any(ActiveConfiguration ac).activateFromSourceConfig()
|
||||
}
|
||||
module FromSourceConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { ExternalFlow::sourceNode(source, _) }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { ExternalFlow::sourceNode(source, _) }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(DataFlowTargetApi c |
|
||||
sink instanceof DataFlowImplCommon::ReturnNodeExt and
|
||||
sink.getEnclosingCallable() = c
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::FlowFeature getAFeature() {
|
||||
result instanceof DataFlow::FeatureHasSinkCallContext
|
||||
}
|
||||
DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSinkCallContext }
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
isRelevantTaintStep(node1, node2)
|
||||
}
|
||||
}
|
||||
|
||||
private module FromSource = TaintTracking::Make<FromSourceConfig>;
|
||||
|
||||
/**
|
||||
* 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, DataFlow::Node sink, FromSourceConfiguration config, string kind |
|
||||
config.hasFlow(source, sink) and
|
||||
exists(DataFlow::Node source, DataFlow::Node sink, string kind |
|
||||
FromSource::hasFlow(source, sink) and
|
||||
ExternalFlow::sourceNode(source, kind) and
|
||||
api = sink.getEnclosingCallable() and
|
||||
isRelevantSourceKind(kind) and
|
||||
@@ -254,35 +269,30 @@ string captureSource(DataFlowTargetApi api) {
|
||||
}
|
||||
|
||||
/**
|
||||
* A TaintTracking Configuration used for tracking flow through APIs.
|
||||
* A dataflow configuration used for finding new sinks.
|
||||
* The sources are the parameters of the API and the fields of the enclosing type.
|
||||
*
|
||||
* This can be used to generate Sink summaries for APIs, if the API propagates a parameter (or enclosing type field)
|
||||
* into an existing known sink (then the API itself becomes a sink).
|
||||
*/
|
||||
private class PropagateToSinkConfiguration extends TaintTracking::Configuration {
|
||||
PropagateToSinkConfiguration() {
|
||||
this = "parameters or fields flowing into sinks" and
|
||||
any(ActiveConfiguration ac).activateToSinkConfig()
|
||||
}
|
||||
module PropagateToSinkConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { apiSource(source) }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { apiSource(source) }
|
||||
predicate isSink(DataFlow::Node sink) { ExternalFlow::sinkNode(sink, _) }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { ExternalFlow::sinkNode(sink, _) }
|
||||
predicate isBarrier(DataFlow::Node node) { sinkModelSanitizer(node) }
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) { sinkModelSanitizer(node) }
|
||||
|
||||
override DataFlow::FlowFeature getAFeature() {
|
||||
result instanceof DataFlow::FeatureHasSourceCallContext
|
||||
}
|
||||
DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSourceCallContext }
|
||||
}
|
||||
|
||||
private module PropagateToSink = TaintTracking::Make<PropagateToSinkConfig>;
|
||||
|
||||
/**
|
||||
* Gets the sink model(s) of `api`, if there is flow from a parameter to an existing known sink.
|
||||
*/
|
||||
string captureSink(DataFlowTargetApi api) {
|
||||
exists(DataFlow::Node src, DataFlow::Node sink, PropagateToSinkConfiguration config, string kind |
|
||||
config.hasFlow(src, sink) and
|
||||
exists(DataFlow::Node src, DataFlow::Node sink, string kind |
|
||||
PropagateToSink::hasFlow(src, sink) and
|
||||
ExternalFlow::sinkNode(sink, kind) and
|
||||
api = src.getEnclosingCallable() and
|
||||
isRelevantSinkKind(kind) and
|
||||
|
||||
@@ -7,7 +7,6 @@ private import dotnet
|
||||
private import semmle.code.csharp.commons.Util as Util
|
||||
private import semmle.code.csharp.commons.Collections as Collections
|
||||
private import semmle.code.csharp.dataflow.internal.DataFlowDispatch
|
||||
private import semmle.code.csharp.frameworks.System as System
|
||||
private import semmle.code.csharp.frameworks.system.linq.Expressions
|
||||
import semmle.code.csharp.dataflow.ExternalFlow as ExternalFlow
|
||||
import semmle.code.csharp.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon
|
||||
@@ -110,7 +109,7 @@ predicate isRelevantType(CS::Type t) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the CSV string representation of the qualifier.
|
||||
* Gets the MaD string representation of the qualifier.
|
||||
*/
|
||||
string qualifierString() { result = "Argument[this]" }
|
||||
|
||||
@@ -120,14 +119,7 @@ string parameterAccess(CS::Parameter p) {
|
||||
else result = "Argument[" + p.getPosition() + "]"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the CSV string representation of the parameter node `p`.
|
||||
*/
|
||||
string parameterNodeAsInput(DataFlow::ParameterNode p) {
|
||||
result = parameterAccess(p.asParameter())
|
||||
or
|
||||
result = qualifierString() and p instanceof DataFlowPrivate::InstanceParameterNode
|
||||
}
|
||||
class InstanceParameterNode = DataFlowPrivate::InstanceParameterNode;
|
||||
|
||||
pragma[nomagic]
|
||||
private CS::Parameter getParameter(DataFlowImplCommon::ReturnNodeExt node, ParameterPosition pos) {
|
||||
@@ -135,7 +127,7 @@ private CS::Parameter getParameter(DataFlowImplCommon::ReturnNodeExt node, Param
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the CSV string representation of the the return node `node`.
|
||||
* Gets the MaD string representation of the the return node `node`.
|
||||
*/
|
||||
string returnNodeAsOutput(DataFlowImplCommon::ReturnNodeExt node) {
|
||||
if node.getKind() instanceof DataFlowImplCommon::ValueReturnKind
|
||||
@@ -188,9 +180,9 @@ predicate apiSource(DataFlow::Node source) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the CSV input string representation of `source`.
|
||||
* Gets the MaD input string representation of `source`.
|
||||
*/
|
||||
string asInputArgument(DataFlow::Node source) {
|
||||
string asInputArgumentSpecific(DataFlow::Node source) {
|
||||
exists(int pos |
|
||||
pos = source.(DataFlow::ParameterNode).getParameter().getPosition() and
|
||||
result = "Argument[" + pos + "]"
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
private import CaptureModels
|
||||
|
||||
private class Activate extends ActiveConfiguration {
|
||||
override predicate activateThroughFlowConfig() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Capture fluent APIs that return `this`.
|
||||
* Example of a fluent API:
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import internal.CaptureModels
|
||||
import internal.CaptureSummaryFlow
|
||||
import internal.CaptureSummaryFlowQuery
|
||||
|
||||
from DataFlowTargetApi api, string noflow
|
||||
where noflow = captureNoFlow(api)
|
||||
|
||||
@@ -8,10 +8,6 @@
|
||||
|
||||
import internal.CaptureModels
|
||||
|
||||
class Activate extends ActiveConfiguration {
|
||||
override predicate activateToSinkConfig() { any() }
|
||||
}
|
||||
|
||||
from DataFlowTargetApi api, string sink
|
||||
where sink = captureSink(api)
|
||||
select sink order by sink
|
||||
|
||||
@@ -8,10 +8,6 @@
|
||||
|
||||
import internal.CaptureModels
|
||||
|
||||
class Activate extends ActiveConfiguration {
|
||||
override predicate activateFromSourceConfig() { any() }
|
||||
}
|
||||
|
||||
from DataFlowTargetApi api, string source
|
||||
where source = captureSource(api)
|
||||
select source order by source
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import internal.CaptureModels
|
||||
import internal.CaptureSummaryFlow
|
||||
import internal.CaptureSummaryFlowQuery
|
||||
|
||||
from DataFlowTargetApi api, string flow
|
||||
where flow = captureFlow(api)
|
||||
|
||||
@@ -5,14 +5,6 @@
|
||||
|
||||
private import CaptureModelsSpecific
|
||||
|
||||
class ActiveConfiguration extends Unit {
|
||||
predicate activateThroughFlowConfig() { none() }
|
||||
|
||||
predicate activateFromSourceConfig() { none() }
|
||||
|
||||
predicate activateToSinkConfig() { none() }
|
||||
}
|
||||
|
||||
class DataFlowTargetApi extends TargetApiSpecific {
|
||||
DataFlowTargetApi() { isRelevantForDataFlowModels(this) }
|
||||
}
|
||||
@@ -46,6 +38,20 @@ private predicate isRelevantContent(DataFlow::Content c) {
|
||||
DataFlowPrivate::containerContent(c)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MaD string representation of the parameter node `p`.
|
||||
*/
|
||||
string parameterNodeAsInput(DataFlow::ParameterNode p) {
|
||||
result = parameterAccess(p.asParameter())
|
||||
or
|
||||
result = qualifierString() and p instanceof InstanceParameterNode
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MaD input string representation of `source`.
|
||||
*/
|
||||
string asInputArgument(DataFlow::Node source) { result = asInputArgumentSpecific(source) }
|
||||
|
||||
/**
|
||||
* Gets the summary model for `api` with `input`, `output` and `kind`.
|
||||
*/
|
||||
@@ -111,61 +117,70 @@ string captureQualifierFlow(TargetApiSpecific api) {
|
||||
|
||||
private int accessPathLimit() { result = 2 }
|
||||
|
||||
private newtype TTaintState =
|
||||
TTaintRead(int n) { n in [0 .. accessPathLimit()] } or
|
||||
TTaintStore(int n) { n in [1 .. accessPathLimit()] }
|
||||
|
||||
abstract private class TaintState extends TTaintState {
|
||||
abstract string toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* A FlowState representing a tainted read.
|
||||
*/
|
||||
private class TaintRead extends DataFlow::FlowState {
|
||||
private class TaintRead extends TaintState, TTaintRead {
|
||||
private int step;
|
||||
|
||||
TaintRead() { this = "TaintRead(" + step + ")" and step in [0 .. accessPathLimit()] }
|
||||
TaintRead() { this = TTaintRead(step) }
|
||||
|
||||
/**
|
||||
* Gets the flow state step number.
|
||||
*/
|
||||
int getStep() { result = step }
|
||||
|
||||
override string toString() { result = "TaintRead(" + step + ")" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A FlowState representing a tainted write.
|
||||
*/
|
||||
private class TaintStore extends DataFlow::FlowState {
|
||||
private class TaintStore extends TaintState, TTaintStore {
|
||||
private int step;
|
||||
|
||||
TaintStore() { this = "TaintStore(" + step + ")" and step in [1 .. accessPathLimit()] }
|
||||
TaintStore() { this = TTaintStore(step) }
|
||||
|
||||
/**
|
||||
* Gets the flow state step number.
|
||||
*/
|
||||
int getStep() { result = step }
|
||||
|
||||
override string toString() { result = "TaintStore(" + step + ")" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A TaintTracking Configuration used for tracking flow through APIs.
|
||||
* A data-flow configuration for tracking flow through APIs.
|
||||
* The sources are the parameters of an API and the sinks are the return values (excluding `this`) and parameters.
|
||||
*
|
||||
* This can be used to generate Flow summaries for APIs from parameter to return.
|
||||
*/
|
||||
private class ThroughFlowConfig extends TaintTracking::Configuration {
|
||||
ThroughFlowConfig() {
|
||||
this = "ThroughFlowConfig" and any(ActiveConfiguration ac).activateThroughFlowConfig()
|
||||
}
|
||||
module ThroughFlowConfig implements DataFlow::StateConfigSig {
|
||||
class FlowState = TaintState;
|
||||
|
||||
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) {
|
||||
predicate isSource(DataFlow::Node source, FlowState state) {
|
||||
source instanceof DataFlow::ParameterNode and
|
||||
source.getEnclosingCallable() instanceof DataFlowTargetApi and
|
||||
state.(TaintRead).getStep() = 0
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) {
|
||||
predicate isSink(DataFlow::Node sink, FlowState state) {
|
||||
sink instanceof DataFlowImplCommon::ReturnNodeExt and
|
||||
not isOwnInstanceAccessNode(sink) and
|
||||
not exists(captureQualifierFlow(sink.asExpr().getEnclosingCallable())) and
|
||||
(state instanceof TaintRead or state instanceof TaintStore)
|
||||
}
|
||||
|
||||
override predicate isAdditionalTaintStep(
|
||||
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
|
||||
DataFlow::FlowState state2
|
||||
predicate isAdditionalFlowStep(
|
||||
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
|
||||
) {
|
||||
exists(DataFlowImplCommon::TypedContent tc |
|
||||
DataFlowImplCommon::store(node1, tc, node2, _) and
|
||||
@@ -184,24 +199,28 @@ private class ThroughFlowConfig extends TaintTracking::Configuration {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node n) {
|
||||
predicate isBarrier(DataFlow::Node n) {
|
||||
exists(Type t | t = n.getType() and not isRelevantType(t))
|
||||
}
|
||||
|
||||
override DataFlow::FlowFeature getAFeature() {
|
||||
predicate isBarrier(DataFlow::Node node, FlowState state) { none() }
|
||||
|
||||
DataFlow::FlowFeature getAFeature() {
|
||||
result instanceof DataFlow::FeatureEqualSourceSinkCallContext
|
||||
}
|
||||
}
|
||||
|
||||
private module ThroughFlow = TaintTracking::MakeWithState<ThroughFlowConfig>;
|
||||
|
||||
/**
|
||||
* Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter.
|
||||
*/
|
||||
string captureThroughFlow(DataFlowTargetApi api) {
|
||||
exists(
|
||||
ThroughFlowConfig config, DataFlow::ParameterNode p,
|
||||
DataFlowImplCommon::ReturnNodeExt returnNodeExt, string input, string output
|
||||
DataFlow::ParameterNode p, DataFlowImplCommon::ReturnNodeExt returnNodeExt, string input,
|
||||
string output
|
||||
|
|
||||
config.hasFlow(p, returnNodeExt) and
|
||||
ThroughFlow::hasFlow(p, returnNodeExt) and
|
||||
returnNodeExt.getEnclosingCallable() = api and
|
||||
input = parameterNodeAsInput(p) and
|
||||
output = returnNodeAsOutput(returnNodeExt) and
|
||||
@@ -211,41 +230,37 @@ string captureThroughFlow(DataFlowTargetApi api) {
|
||||
}
|
||||
|
||||
/**
|
||||
* A TaintTracking Configuration used for tracking flow through APIs.
|
||||
* A dataflow configuration used for finding new sources.
|
||||
* The sources are the already known existing sources and the sinks are the API return nodes.
|
||||
*
|
||||
* 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).
|
||||
*/
|
||||
private class FromSourceConfiguration extends TaintTracking::Configuration {
|
||||
FromSourceConfiguration() {
|
||||
this = "FromSourceConfiguration" and any(ActiveConfiguration ac).activateFromSourceConfig()
|
||||
}
|
||||
module FromSourceConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { ExternalFlow::sourceNode(source, _) }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { ExternalFlow::sourceNode(source, _) }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(DataFlowTargetApi c |
|
||||
sink instanceof DataFlowImplCommon::ReturnNodeExt and
|
||||
sink.getEnclosingCallable() = c
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::FlowFeature getAFeature() {
|
||||
result instanceof DataFlow::FeatureHasSinkCallContext
|
||||
}
|
||||
DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSinkCallContext }
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
isRelevantTaintStep(node1, node2)
|
||||
}
|
||||
}
|
||||
|
||||
private module FromSource = TaintTracking::Make<FromSourceConfig>;
|
||||
|
||||
/**
|
||||
* 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, DataFlow::Node sink, FromSourceConfiguration config, string kind |
|
||||
config.hasFlow(source, sink) and
|
||||
exists(DataFlow::Node source, DataFlow::Node sink, string kind |
|
||||
FromSource::hasFlow(source, sink) and
|
||||
ExternalFlow::sourceNode(source, kind) and
|
||||
api = sink.getEnclosingCallable() and
|
||||
isRelevantSourceKind(kind) and
|
||||
@@ -254,35 +269,30 @@ string captureSource(DataFlowTargetApi api) {
|
||||
}
|
||||
|
||||
/**
|
||||
* A TaintTracking Configuration used for tracking flow through APIs.
|
||||
* A dataflow configuration used for finding new sinks.
|
||||
* The sources are the parameters of the API and the fields of the enclosing type.
|
||||
*
|
||||
* This can be used to generate Sink summaries for APIs, if the API propagates a parameter (or enclosing type field)
|
||||
* into an existing known sink (then the API itself becomes a sink).
|
||||
*/
|
||||
private class PropagateToSinkConfiguration extends TaintTracking::Configuration {
|
||||
PropagateToSinkConfiguration() {
|
||||
this = "parameters or fields flowing into sinks" and
|
||||
any(ActiveConfiguration ac).activateToSinkConfig()
|
||||
}
|
||||
module PropagateToSinkConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { apiSource(source) }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { apiSource(source) }
|
||||
predicate isSink(DataFlow::Node sink) { ExternalFlow::sinkNode(sink, _) }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { ExternalFlow::sinkNode(sink, _) }
|
||||
predicate isBarrier(DataFlow::Node node) { sinkModelSanitizer(node) }
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) { sinkModelSanitizer(node) }
|
||||
|
||||
override DataFlow::FlowFeature getAFeature() {
|
||||
result instanceof DataFlow::FeatureHasSourceCallContext
|
||||
}
|
||||
DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSourceCallContext }
|
||||
}
|
||||
|
||||
private module PropagateToSink = TaintTracking::Make<PropagateToSinkConfig>;
|
||||
|
||||
/**
|
||||
* Gets the sink model(s) of `api`, if there is flow from a parameter to an existing known sink.
|
||||
*/
|
||||
string captureSink(DataFlowTargetApi api) {
|
||||
exists(DataFlow::Node src, DataFlow::Node sink, PropagateToSinkConfiguration config, string kind |
|
||||
config.hasFlow(src, sink) and
|
||||
exists(DataFlow::Node src, DataFlow::Node sink, string kind |
|
||||
PropagateToSink::hasFlow(src, sink) and
|
||||
ExternalFlow::sinkNode(sink, kind) and
|
||||
api = src.getEnclosingCallable() and
|
||||
isRelevantSinkKind(kind) and
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*/
|
||||
|
||||
private import java as J
|
||||
private import semmle.code.java.dataflow.internal.DataFlowNodes
|
||||
private import semmle.code.java.dataflow.internal.DataFlowPrivate
|
||||
private import semmle.code.java.dataflow.internal.ContainerFlow as ContainerFlow
|
||||
private import semmle.code.java.dataflow.DataFlow as Df
|
||||
@@ -130,7 +129,7 @@ private predicate partialModel(TargetApiSpecific api, string type, string name,
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the first 6 columns for CSV rows.
|
||||
* Computes the first 6 columns for MaD rows.
|
||||
*/
|
||||
string asPartialModel(TargetApiSpecific api) {
|
||||
exists(string type, string name, string parameters |
|
||||
@@ -145,7 +144,7 @@ string asPartialModel(TargetApiSpecific api) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the first 4 columns for neutral CSV rows.
|
||||
* Computes the first 4 columns for neutral MaD rows.
|
||||
*/
|
||||
string asPartialNeutralModel(TargetApiSpecific api) {
|
||||
exists(string type, string name, string parameters |
|
||||
@@ -187,11 +186,14 @@ predicate isRelevantType(J::Type t) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the CSV string representation of the qualifier.
|
||||
* Gets the MaD string representation of the qualifier.
|
||||
*/
|
||||
string qualifierString() { result = "Argument[this]" }
|
||||
|
||||
private string parameterAccess(J::Parameter p) {
|
||||
/**
|
||||
* Gets the MaD string representation of the parameter `p`.
|
||||
*/
|
||||
string parameterAccess(J::Parameter p) {
|
||||
if
|
||||
p.getType() instanceof J::Array and
|
||||
not isPrimitiveTypeUsedForBulkData(p.getType().(J::Array).getElementType())
|
||||
@@ -202,17 +204,10 @@ private string parameterAccess(J::Parameter p) {
|
||||
else result = "Argument[" + p.getPosition() + "]"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the CSV string representation of the parameter node `p`.
|
||||
*/
|
||||
string parameterNodeAsInput(DataFlow::ParameterNode p) {
|
||||
result = parameterAccess(p.asParameter())
|
||||
or
|
||||
result = qualifierString() and p instanceof DataFlow::InstanceParameterNode
|
||||
}
|
||||
class InstanceParameterNode = DataFlow::InstanceParameterNode;
|
||||
|
||||
/**
|
||||
* Gets the CSV string represention of the the return node `node`.
|
||||
* Gets the MaD string represention of the the return node `node`.
|
||||
*/
|
||||
string returnNodeAsOutput(DataFlowImplCommon::ReturnNodeExt node) {
|
||||
if node.getKind() instanceof DataFlowImplCommon::ValueReturnKind
|
||||
@@ -268,9 +263,9 @@ predicate apiSource(DataFlow::Node source) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the CSV input string representation of `source`.
|
||||
* Gets the MaD input string representation of `source`.
|
||||
*/
|
||||
string asInputArgument(DataFlow::Node source) {
|
||||
string asInputArgumentSpecific(DataFlow::Node source) {
|
||||
exists(int pos |
|
||||
source.(DataFlow::ParameterNode).isParameterOf(_, pos) and
|
||||
result = "Argument[" + pos + "]"
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
private import CaptureModels
|
||||
|
||||
private class Activate extends ActiveConfiguration {
|
||||
override predicate activateThroughFlowConfig() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Capture fluent APIs that return `this`.
|
||||
* Example of a fluent API:
|
||||
Reference in New Issue
Block a user