mirror of
https://github.com/github/codeql.git
synced 2026-04-27 17:55:19 +02:00
Java/Dataflow: Propagate MaD-id/model-id to PathGraph.
This commit is contained in:
@@ -15,7 +15,8 @@ private newtype TSinkModel =
|
||||
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string input, string kind, string provenance
|
||||
) {
|
||||
ExternalFlow::sinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance)
|
||||
ExternalFlow::sinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance,
|
||||
_)
|
||||
}
|
||||
|
||||
class SinkModel extends TSinkModel {
|
||||
|
||||
@@ -259,7 +259,7 @@ module ApplicationCandidatesImpl implements SharedCharacteristics::CandidateSig
|
||||
|
|
||||
sinkSpec(e, package, type, subtypes, name, signature, ext, input) and
|
||||
ExternalFlow::sinkModel(package, type, subtypes, name, [signature, ""], ext, input, kind,
|
||||
provenance)
|
||||
provenance, _)
|
||||
)
|
||||
or
|
||||
isCustomSink(e, kind) and provenance = "custom-sink"
|
||||
@@ -272,7 +272,7 @@ module ApplicationCandidatesImpl implements SharedCharacteristics::CandidateSig
|
||||
|
|
||||
sourceSpec(e, package, type, subtypes, name, signature, ext, output) and
|
||||
ExternalFlow::sourceModel(package, type, subtypes, name, [signature, ""], ext, output, kind,
|
||||
provenance)
|
||||
provenance, _)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -215,7 +215,7 @@ module FrameworkCandidatesImpl implements SharedCharacteristics::CandidateSig {
|
||||
|
|
||||
sinkSpec(e, package, type, subtypes, name, signature, ext, input) and
|
||||
ExternalFlow::sinkModel(package, type, subtypes, name, [signature, ""], ext, input, kind,
|
||||
provenance)
|
||||
provenance, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -226,7 +226,7 @@ module FrameworkCandidatesImpl implements SharedCharacteristics::CandidateSig {
|
||||
|
|
||||
sourceSpec(e, package, type, subtypes, name, signature, ext, output) and
|
||||
ExternalFlow::sourceModel(package, type, subtypes, name, [signature, ""], ext, output, kind,
|
||||
provenance)
|
||||
provenance, _)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -113,10 +113,10 @@ abstract class ActiveExperimentalModels extends string {
|
||||
*/
|
||||
predicate sourceModel(
|
||||
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string output, string kind, string provenance
|
||||
string output, string kind, string provenance, QlBuiltins::ExtensionId madId
|
||||
) {
|
||||
Extensions::experimentalSourceModel(package, type, subtypes, name, signature, ext, output, kind,
|
||||
provenance, this)
|
||||
provenance, this, madId)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,10 +124,10 @@ abstract class ActiveExperimentalModels extends string {
|
||||
*/
|
||||
predicate sinkModel(
|
||||
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string output, string kind, string provenance
|
||||
string output, string kind, string provenance, QlBuiltins::ExtensionId madId
|
||||
) {
|
||||
Extensions::experimentalSinkModel(package, type, subtypes, name, signature, ext, output, kind,
|
||||
provenance, this)
|
||||
provenance, this, madId)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,54 +135,63 @@ abstract class ActiveExperimentalModels extends string {
|
||||
*/
|
||||
predicate summaryModel(
|
||||
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string input, string output, string kind, string provenance
|
||||
string input, string output, string kind, string provenance, QlBuiltins::ExtensionId madId
|
||||
) {
|
||||
Extensions::experimentalSummaryModel(package, type, subtypes, name, signature, ext, input,
|
||||
output, kind, provenance, this)
|
||||
output, kind, provenance, this, madId)
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if a source model exists for the given parameters. */
|
||||
predicate sourceModel(
|
||||
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string output, string kind, string provenance
|
||||
string output, string kind, string provenance, QlBuiltins::ExtensionId madId
|
||||
) {
|
||||
Extensions::sourceModel(package, type, subtypes, name, signature, ext, output, kind, provenance)
|
||||
or
|
||||
any(ActiveExperimentalModels q)
|
||||
.sourceModel(package, type, subtypes, name, signature, ext, output, kind, provenance)
|
||||
(
|
||||
Extensions::sourceModel(package, type, subtypes, name, signature, ext, output, kind, provenance,
|
||||
madId)
|
||||
or
|
||||
any(ActiveExperimentalModels q)
|
||||
.sourceModel(package, type, subtypes, name, signature, ext, output, kind, provenance, madId)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if a sink model exists for the given parameters. */
|
||||
predicate sinkModel(
|
||||
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string input, string kind, string provenance
|
||||
string input, string kind, string provenance, QlBuiltins::ExtensionId madId
|
||||
) {
|
||||
Extensions::sinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance)
|
||||
or
|
||||
any(ActiveExperimentalModels q)
|
||||
.sinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance)
|
||||
(
|
||||
Extensions::sinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance,
|
||||
madId)
|
||||
or
|
||||
any(ActiveExperimentalModels q)
|
||||
.sinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance, madId)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if a summary model exists for the given parameters. */
|
||||
predicate summaryModel(
|
||||
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string input, string output, string kind, string provenance
|
||||
string input, string output, string kind, string provenance, QlBuiltins::ExtensionId madId
|
||||
) {
|
||||
Extensions::summaryModel(package, type, subtypes, name, signature, ext, input, output, kind,
|
||||
provenance)
|
||||
or
|
||||
any(ActiveExperimentalModels q)
|
||||
.summaryModel(package, type, subtypes, name, signature, ext, input, output, kind, provenance)
|
||||
(
|
||||
Extensions::summaryModel(package, type, subtypes, name, signature, ext, input, output, kind,
|
||||
provenance, madId)
|
||||
or
|
||||
any(ActiveExperimentalModels q)
|
||||
.summaryModel(package, type, subtypes, name, signature, ext, input, output, kind,
|
||||
provenance, madId)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if a neutral model exists for the given parameters. */
|
||||
predicate neutralModel = Extensions::neutralModel/6;
|
||||
|
||||
private predicate relevantPackage(string package) {
|
||||
sourceModel(package, _, _, _, _, _, _, _, _) or
|
||||
sinkModel(package, _, _, _, _, _, _, _, _) or
|
||||
summaryModel(package, _, _, _, _, _, _, _, _, _)
|
||||
sourceModel(package, _, _, _, _, _, _, _, _, _) or
|
||||
sinkModel(package, _, _, _, _, _, _, _, _, _) or
|
||||
summaryModel(package, _, _, _, _, _, _, _, _, _, _)
|
||||
}
|
||||
|
||||
private predicate packageLink(string shortpkg, string longpkg) {
|
||||
@@ -212,7 +221,7 @@ predicate modelCoverage(string package, int pkgs, string kind, string part, int
|
||||
strictcount(string subpkg, string type, boolean subtypes, string name, string signature,
|
||||
string ext, string output, string provenance |
|
||||
canonicalPkgLink(package, subpkg) and
|
||||
sourceModel(subpkg, type, subtypes, name, signature, ext, output, kind, provenance)
|
||||
sourceModel(subpkg, type, subtypes, name, signature, ext, output, kind, provenance, _)
|
||||
)
|
||||
or
|
||||
part = "sink" and
|
||||
@@ -220,7 +229,7 @@ predicate modelCoverage(string package, int pkgs, string kind, string part, int
|
||||
strictcount(string subpkg, string type, boolean subtypes, string name, string signature,
|
||||
string ext, string input, string provenance |
|
||||
canonicalPkgLink(package, subpkg) and
|
||||
sinkModel(subpkg, type, subtypes, name, signature, ext, input, kind, provenance)
|
||||
sinkModel(subpkg, type, subtypes, name, signature, ext, input, kind, provenance, _)
|
||||
)
|
||||
or
|
||||
part = "summary" and
|
||||
@@ -228,7 +237,8 @@ predicate modelCoverage(string package, int pkgs, string kind, string part, int
|
||||
strictcount(string subpkg, string type, boolean subtypes, string name, string signature,
|
||||
string ext, string input, string output, string provenance |
|
||||
canonicalPkgLink(package, subpkg) and
|
||||
summaryModel(subpkg, type, subtypes, name, signature, ext, input, output, kind, provenance)
|
||||
summaryModel(subpkg, type, subtypes, name, signature, ext, input, output, kind, provenance,
|
||||
_)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -238,10 +248,10 @@ module ModelValidation {
|
||||
private import codeql.dataflow.internal.AccessPathSyntax as AccessPathSyntax
|
||||
|
||||
private predicate getRelevantAccessPath(string path) {
|
||||
summaryModel(_, _, _, _, _, _, path, _, _, _) or
|
||||
summaryModel(_, _, _, _, _, _, _, path, _, _) or
|
||||
sinkModel(_, _, _, _, _, _, path, _, _) or
|
||||
sourceModel(_, _, _, _, _, _, path, _, _)
|
||||
summaryModel(_, _, _, _, _, _, path, _, _, _, _) or
|
||||
summaryModel(_, _, _, _, _, _, _, path, _, _, _) or
|
||||
sinkModel(_, _, _, _, _, _, path, _, _, _) or
|
||||
sourceModel(_, _, _, _, _, _, path, _, _, _)
|
||||
}
|
||||
|
||||
private module MkAccessPath = AccessPathSyntax::AccessPath<getRelevantAccessPath/1>;
|
||||
@@ -252,9 +262,9 @@ module ModelValidation {
|
||||
|
||||
private string getInvalidModelInput() {
|
||||
exists(string pred, AccessPath input, AccessPathToken part |
|
||||
sinkModel(_, _, _, _, _, _, input, _, _) and pred = "sink"
|
||||
sinkModel(_, _, _, _, _, _, input, _, _, _) and pred = "sink"
|
||||
or
|
||||
summaryModel(_, _, _, _, _, _, input, _, _, _) and pred = "summary"
|
||||
summaryModel(_, _, _, _, _, _, input, _, _, _, _) and pred = "summary"
|
||||
|
|
||||
(
|
||||
invalidSpecComponent(input, part) and
|
||||
@@ -274,9 +284,9 @@ module ModelValidation {
|
||||
|
||||
private string getInvalidModelOutput() {
|
||||
exists(string pred, AccessPath output, AccessPathToken part |
|
||||
sourceModel(_, _, _, _, _, _, output, _, _) and pred = "source"
|
||||
sourceModel(_, _, _, _, _, _, output, _, _, _) and pred = "source"
|
||||
or
|
||||
summaryModel(_, _, _, _, _, _, _, output, _, _) and pred = "summary"
|
||||
summaryModel(_, _, _, _, _, _, _, output, _, _, _) and pred = "summary"
|
||||
|
|
||||
(
|
||||
invalidSpecComponent(output, part) and
|
||||
@@ -291,11 +301,11 @@ module ModelValidation {
|
||||
}
|
||||
|
||||
private module KindValConfig implements SharedModelVal::KindValidationConfigSig {
|
||||
predicate summaryKind(string kind) { summaryModel(_, _, _, _, _, _, _, _, kind, _) }
|
||||
predicate summaryKind(string kind) { summaryModel(_, _, _, _, _, _, _, _, kind, _, _) }
|
||||
|
||||
predicate sinkKind(string kind) { sinkModel(_, _, _, _, _, _, _, kind, _) }
|
||||
predicate sinkKind(string kind) { sinkModel(_, _, _, _, _, _, _, kind, _, _) }
|
||||
|
||||
predicate sourceKind(string kind) { sourceModel(_, _, _, _, _, _, _, kind, _) }
|
||||
predicate sourceKind(string kind) { sourceModel(_, _, _, _, _, _, _, kind, _, _) }
|
||||
|
||||
predicate neutralKind(string kind) { neutralModel(_, _, _, _, kind, _) }
|
||||
}
|
||||
@@ -307,11 +317,11 @@ module ModelValidation {
|
||||
string pred, string package, string type, string name, string signature, string ext,
|
||||
string provenance
|
||||
|
|
||||
sourceModel(package, type, _, name, signature, ext, _, _, provenance) and pred = "source"
|
||||
sourceModel(package, type, _, name, signature, ext, _, _, provenance, _) and pred = "source"
|
||||
or
|
||||
sinkModel(package, type, _, name, signature, ext, _, _, provenance) and pred = "sink"
|
||||
sinkModel(package, type, _, name, signature, ext, _, _, provenance, _) and pred = "sink"
|
||||
or
|
||||
summaryModel(package, type, _, name, signature, ext, _, _, _, provenance) and
|
||||
summaryModel(package, type, _, name, signature, ext, _, _, _, provenance, _) and
|
||||
pred = "summary"
|
||||
or
|
||||
neutralModel(package, type, name, signature, _, provenance) and
|
||||
@@ -352,11 +362,11 @@ pragma[nomagic]
|
||||
private predicate elementSpec(
|
||||
string package, string type, boolean subtypes, string name, string signature, string ext
|
||||
) {
|
||||
sourceModel(package, type, subtypes, name, signature, ext, _, _, _)
|
||||
sourceModel(package, type, subtypes, name, signature, ext, _, _, _, _)
|
||||
or
|
||||
sinkModel(package, type, subtypes, name, signature, ext, _, _, _)
|
||||
sinkModel(package, type, subtypes, name, signature, ext, _, _, _, _)
|
||||
or
|
||||
summaryModel(package, type, subtypes, name, signature, ext, _, _, _, _)
|
||||
summaryModel(package, type, subtypes, name, signature, ext, _, _, _, _, _)
|
||||
or
|
||||
neutralModel(package, type, name, signature, _, _) and ext = "" and subtypes = false
|
||||
}
|
||||
@@ -494,9 +504,9 @@ private module Cached {
|
||||
* model.
|
||||
*/
|
||||
cached
|
||||
predicate sourceNode(Node node, string kind) {
|
||||
predicate sourceNode(Node node, string kind, string model) {
|
||||
exists(SourceSinkInterpretationInput::InterpretNode n |
|
||||
isSourceNode(n, kind) and n.asNode() = node
|
||||
isSourceNode(n, kind, model) and n.asNode() = node
|
||||
)
|
||||
}
|
||||
|
||||
@@ -505,29 +515,45 @@ private module Cached {
|
||||
* model.
|
||||
*/
|
||||
cached
|
||||
predicate sinkNode(Node node, string kind) {
|
||||
predicate sinkNode(Node node, string kind, string model) {
|
||||
exists(SourceSinkInterpretationInput::InterpretNode n |
|
||||
isSinkNode(n, kind) and n.asNode() = node
|
||||
isSinkNode(n, kind, model) and n.asNode() = node
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import Cached
|
||||
|
||||
/**
|
||||
* Holds if `node` is specified as a source with the given kind in a MaD flow
|
||||
* model.
|
||||
*/
|
||||
predicate sourceNode(Node node, string kind) { sourceNode(node, kind, _) }
|
||||
|
||||
/**
|
||||
* Holds if `node` is specified as a sink with the given kind in a MaD flow
|
||||
* model.
|
||||
*/
|
||||
predicate sinkNode(Node node, string kind) { sinkNode(node, kind, _) }
|
||||
|
||||
// adapter class for converting Mad summaries to `SummarizedCallable`s
|
||||
private class SummarizedCallableAdapter extends SummarizedCallable {
|
||||
SummarizedCallableAdapter() { summaryElement(this, _, _, _, _) }
|
||||
SummarizedCallableAdapter() { summaryElement(this, _, _, _, _, _) }
|
||||
|
||||
private predicate relevantSummaryElementManual(string input, string output, string kind) {
|
||||
private predicate relevantSummaryElementManual(
|
||||
string input, string output, string kind, string model
|
||||
) {
|
||||
exists(Provenance provenance |
|
||||
summaryElement(this, input, output, kind, provenance) and
|
||||
summaryElement(this, input, output, kind, provenance, model) and
|
||||
provenance.isManual()
|
||||
)
|
||||
}
|
||||
|
||||
private predicate relevantSummaryElementGenerated(string input, string output, string kind) {
|
||||
private predicate relevantSummaryElementGenerated(
|
||||
string input, string output, string kind, string model
|
||||
) {
|
||||
exists(Provenance provenance |
|
||||
summaryElement(this, input, output, kind, provenance) and
|
||||
summaryElement(this, input, output, kind, provenance, model) and
|
||||
provenance.isGenerated()
|
||||
) and
|
||||
not exists(Provenance provenance |
|
||||
@@ -536,19 +562,21 @@ private class SummarizedCallableAdapter extends SummarizedCallable {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||
override predicate propagatesFlow(
|
||||
string input, string output, boolean preservesValue, string model
|
||||
) {
|
||||
exists(string kind |
|
||||
this.relevantSummaryElementManual(input, output, kind)
|
||||
this.relevantSummaryElementManual(input, output, kind, model)
|
||||
or
|
||||
not this.relevantSummaryElementManual(_, _, _) and
|
||||
this.relevantSummaryElementGenerated(input, output, kind)
|
||||
not this.relevantSummaryElementManual(_, _, _, _) and
|
||||
this.relevantSummaryElementGenerated(input, output, kind, model)
|
||||
|
|
||||
if kind = "value" then preservesValue = true else preservesValue = false
|
||||
)
|
||||
}
|
||||
|
||||
override predicate hasProvenance(Provenance provenance) {
|
||||
summaryElement(this, _, _, _, provenance)
|
||||
summaryElement(this, _, _, _, provenance, _)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -126,8 +126,14 @@ class SummarizedCallable = Impl::Public::SummarizedCallable;
|
||||
* to `SummarizedCallable`.
|
||||
*/
|
||||
private class SummarizedSyntheticCallableAdapter extends SummarizedCallable, TSyntheticCallable {
|
||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||
this.asSyntheticCallable().propagatesFlow(input, output, preservesValue)
|
||||
override predicate propagatesFlow(
|
||||
string input, string output, boolean preservesValue, string model
|
||||
) {
|
||||
exists(SyntheticCallable sc |
|
||||
sc = this.asSyntheticCallable() and
|
||||
sc.propagatesFlow(input, output, preservesValue) and
|
||||
model = sc
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -263,9 +263,10 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
|
||||
predicate isBarrierOut(Node node, FlowState state) { none() }
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, Node node2) {
|
||||
predicate isAdditionalFlowStep(Node node1, Node node2, string model) {
|
||||
singleConfiguration() and
|
||||
any(Configuration config).isAdditionalFlowStep(node1, node2)
|
||||
any(Configuration config).isAdditionalFlowStep(node1, node2) and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
|
||||
@@ -7,6 +7,7 @@ private import semmle.code.java.dataflow.SSA
|
||||
private import ContainerFlow
|
||||
private import semmle.code.java.dataflow.FlowSteps
|
||||
private import semmle.code.java.dataflow.FlowSummary
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
private import FlowSummaryImpl as FlowSummaryImpl
|
||||
private import DataFlowNodes
|
||||
private import codeql.dataflow.VariableCapture as VariableCapture
|
||||
@@ -576,6 +577,10 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
|
||||
/** Extra data-flow steps needed for lambda flow analysis. */
|
||||
predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() }
|
||||
|
||||
predicate knownSourceModel(Node source, string model) { sourceNode(source, _, model) }
|
||||
|
||||
predicate knownSinkModel(Node sink, string model) { sinkNode(sink, _, model) }
|
||||
|
||||
/**
|
||||
* Holds if flow is allowed to pass from parameter `p` and back to itself as a
|
||||
* side-effect, resulting in a summary from `p` to itself.
|
||||
|
||||
@@ -106,7 +106,7 @@ private module Cached {
|
||||
*/
|
||||
cached
|
||||
predicate localFlowStep(Node node1, Node node2) {
|
||||
simpleLocalFlowStep0(node1, node2)
|
||||
simpleLocalFlowStep0(node1, node2, _)
|
||||
or
|
||||
adjacentUseUse(node1.asExpr(), node2.asExpr())
|
||||
or
|
||||
@@ -122,12 +122,13 @@ private module Cached {
|
||||
* data flow. It may have less flow than the `localFlowStep` predicate.
|
||||
*/
|
||||
cached
|
||||
predicate simpleLocalFlowStep(Node node1, Node node2) {
|
||||
simpleLocalFlowStep0(node1, node2)
|
||||
predicate simpleLocalFlowStep(Node node1, Node node2, string model) {
|
||||
simpleLocalFlowStep0(node1, node2, model)
|
||||
or
|
||||
any(AdditionalValueStep a).step(node1, node2) and
|
||||
pragma[only_bind_out](node1.getEnclosingCallable()) =
|
||||
pragma[only_bind_out](node2.getEnclosingCallable()) and
|
||||
model = "AdditionalValueStep" and
|
||||
// prevent recursive call
|
||||
(any(AdditionalValueStep a).step(_, _) implies any())
|
||||
}
|
||||
@@ -162,7 +163,7 @@ predicate localMustFlowStep(Node node1, Node node2) {
|
||||
node1 =
|
||||
unique(FlowSummaryNode n1 |
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(n1.getSummaryNode(),
|
||||
node2.(FlowSummaryNode).getSummaryNode(), true)
|
||||
node2.(FlowSummaryNode).getSummaryNode(), true, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -210,51 +211,55 @@ predicate simpleAstFlowStep(Expr e1, Expr e2) {
|
||||
exists(InstanceOfExpr ioe | e1 = ioe.getExpr() and e2 = ioe.getPattern().asRecordPattern())
|
||||
}
|
||||
|
||||
private predicate simpleLocalFlowStep0(Node node1, Node node2) {
|
||||
TaintTrackingUtil::forceCachingInSameStage() and
|
||||
// Variable flow steps through adjacent def-use and use-use pairs.
|
||||
exists(SsaExplicitUpdate upd |
|
||||
upd.getDefiningExpr().(VariableAssign).getSource() = node1.asExpr() or
|
||||
upd.getDefiningExpr().(AssignOp) = node1.asExpr() or
|
||||
upd.getDefiningExpr().(RecordBindingVariableExpr) = node1.asExpr()
|
||||
|
|
||||
node2.asExpr() = upd.getAFirstUse() and
|
||||
private predicate simpleLocalFlowStep0(Node node1, Node node2, string model) {
|
||||
(
|
||||
TaintTrackingUtil::forceCachingInSameStage() and
|
||||
// Variable flow steps through adjacent def-use and use-use pairs.
|
||||
exists(SsaExplicitUpdate upd |
|
||||
upd.getDefiningExpr().(VariableAssign).getSource() = node1.asExpr() or
|
||||
upd.getDefiningExpr().(AssignOp) = node1.asExpr() or
|
||||
upd.getDefiningExpr().(RecordBindingVariableExpr) = node1.asExpr()
|
||||
|
|
||||
node2.asExpr() = upd.getAFirstUse() and
|
||||
not capturedVariableRead(node2)
|
||||
)
|
||||
or
|
||||
exists(SsaImplicitInit init |
|
||||
init.isParameterDefinition(node1.asParameter()) and
|
||||
node2.asExpr() = init.getAFirstUse() and
|
||||
not capturedVariableRead(node2)
|
||||
)
|
||||
or
|
||||
adjacentUseUse(node1.asExpr(), node2.asExpr()) and
|
||||
not exists(FieldRead fr |
|
||||
hasNonlocalValue(fr) and fr.getField().isStatic() and fr = node1.asExpr()
|
||||
) and
|
||||
not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(node1, _) and
|
||||
not capturedVariableRead(node2)
|
||||
)
|
||||
or
|
||||
exists(SsaImplicitInit init |
|
||||
init.isParameterDefinition(node1.asParameter()) and
|
||||
node2.asExpr() = init.getAFirstUse() and
|
||||
or
|
||||
ThisFlow::adjacentThisRefs(node1, node2)
|
||||
or
|
||||
adjacentUseUse(node1.(PostUpdateNode).getPreUpdateNode().asExpr(), node2.asExpr()) and
|
||||
not capturedVariableRead(node2)
|
||||
)
|
||||
or
|
||||
adjacentUseUse(node1.asExpr(), node2.asExpr()) and
|
||||
not exists(FieldRead fr |
|
||||
hasNonlocalValue(fr) and fr.getField().isStatic() and fr = node1.asExpr()
|
||||
or
|
||||
ThisFlow::adjacentThisRefs(node1.(PostUpdateNode).getPreUpdateNode(), node2)
|
||||
or
|
||||
simpleAstFlowStep(node1.asExpr(), node2.asExpr())
|
||||
or
|
||||
captureValueStep(node1, node2)
|
||||
) and
|
||||
not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(node1, _) and
|
||||
not capturedVariableRead(node2)
|
||||
or
|
||||
ThisFlow::adjacentThisRefs(node1, node2)
|
||||
or
|
||||
adjacentUseUse(node1.(PostUpdateNode).getPreUpdateNode().asExpr(), node2.asExpr()) and
|
||||
not capturedVariableRead(node2)
|
||||
or
|
||||
ThisFlow::adjacentThisRefs(node1.(PostUpdateNode).getPreUpdateNode(), node2)
|
||||
or
|
||||
simpleAstFlowStep(node1.asExpr(), node2.asExpr())
|
||||
model = ""
|
||||
or
|
||||
exists(MethodCall ma, ValuePreservingMethod m, int argNo |
|
||||
ma.getCallee().getSourceDeclaration() = m and m.returnsValue(argNo)
|
||||
|
|
||||
node2.asExpr() = ma and
|
||||
node1.(ArgumentNode).argumentOf(any(DataFlowCall c | c.asCall() = ma), argNo)
|
||||
node1.(ArgumentNode).argumentOf(any(DataFlowCall c | c.asCall() = ma), argNo) and
|
||||
model = "ValuePreservingMethod"
|
||||
)
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(node1.(FlowSummaryNode).getSummaryNode(),
|
||||
node2.(FlowSummaryNode).getSummaryNode(), true)
|
||||
or
|
||||
captureValueStep(node1, node2)
|
||||
node2.(FlowSummaryNode).getSummaryNode(), true, model)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
extensible predicate sourceModel(
|
||||
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string output, string kind, string provenance
|
||||
string output, string kind, string provenance, QlBuiltins::ExtensionId madId
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -15,7 +15,7 @@ extensible predicate sourceModel(
|
||||
*/
|
||||
extensible predicate sinkModel(
|
||||
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string input, string kind, string provenance
|
||||
string input, string kind, string provenance, QlBuiltins::ExtensionId madId
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -23,7 +23,7 @@ extensible predicate sinkModel(
|
||||
*/
|
||||
extensible predicate summaryModel(
|
||||
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string input, string output, string kind, string provenance
|
||||
string input, string output, string kind, string provenance, QlBuiltins::ExtensionId madId
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -39,7 +39,7 @@ extensible predicate neutralModel(
|
||||
*/
|
||||
extensible predicate experimentalSourceModel(
|
||||
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string output, string kind, string provenance, string filter
|
||||
string output, string kind, string provenance, string filter, QlBuiltins::ExtensionId madId
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -48,7 +48,7 @@ extensible predicate experimentalSourceModel(
|
||||
*/
|
||||
extensible predicate experimentalSinkModel(
|
||||
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string input, string kind, string provenance, string filter
|
||||
string input, string kind, string provenance, string filter, QlBuiltins::ExtensionId madId
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -57,5 +57,6 @@ extensible predicate experimentalSinkModel(
|
||||
*/
|
||||
extensible predicate experimentalSummaryModel(
|
||||
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string input, string output, string kind, string provenance, string filter
|
||||
string input, string output, string kind, string provenance, string filter,
|
||||
QlBuiltins::ExtensionId madId
|
||||
);
|
||||
|
||||
@@ -126,10 +126,10 @@ private predicate relatedArgSpec(Callable c, string spec) {
|
||||
exists(
|
||||
string namespace, string type, boolean subtypes, string name, string signature, string ext
|
||||
|
|
||||
summaryModel(namespace, type, subtypes, name, signature, ext, spec, _, _, _) or
|
||||
summaryModel(namespace, type, subtypes, name, signature, ext, _, spec, _, _) or
|
||||
sourceModel(namespace, type, subtypes, name, signature, ext, spec, _, _) or
|
||||
sinkModel(namespace, type, subtypes, name, signature, ext, spec, _, _)
|
||||
summaryModel(namespace, type, subtypes, name, signature, ext, spec, _, _, _, _) or
|
||||
summaryModel(namespace, type, subtypes, name, signature, ext, _, spec, _, _, _) or
|
||||
sourceModel(namespace, type, subtypes, name, signature, ext, spec, _, _, _) or
|
||||
sinkModel(namespace, type, subtypes, name, signature, ext, spec, _, _, _)
|
||||
|
|
||||
c = interpretElement(namespace, type, subtypes, name, signature, ext)
|
||||
)
|
||||
@@ -192,12 +192,16 @@ module SourceSinkInterpretationInput implements
|
||||
|
||||
class Element = J::Element;
|
||||
|
||||
predicate sourceElement(Element e, string output, string kind, Public::Provenance provenance) {
|
||||
predicate sourceElement(
|
||||
Element e, string output, string kind, Public::Provenance provenance, string model
|
||||
) {
|
||||
exists(
|
||||
string namespace, string type, boolean subtypes, string name, string signature, string ext,
|
||||
SourceOrSinkElement baseSource, string originalOutput
|
||||
SourceOrSinkElement baseSource, string originalOutput, QlBuiltins::ExtensionId madId
|
||||
|
|
||||
sourceModel(namespace, type, subtypes, name, signature, ext, originalOutput, kind, provenance) and
|
||||
sourceModel(namespace, type, subtypes, name, signature, ext, originalOutput, kind, provenance,
|
||||
madId) and
|
||||
model = "MaD:" + madId.toString() and
|
||||
baseSource = interpretElement(namespace, type, subtypes, name, signature, ext) and
|
||||
(
|
||||
e = baseSource and output = originalOutput
|
||||
@@ -207,12 +211,16 @@ module SourceSinkInterpretationInput implements
|
||||
)
|
||||
}
|
||||
|
||||
predicate sinkElement(Element e, string input, string kind, Public::Provenance provenance) {
|
||||
predicate sinkElement(
|
||||
Element e, string input, string kind, Public::Provenance provenance, string model
|
||||
) {
|
||||
exists(
|
||||
string namespace, string type, boolean subtypes, string name, string signature, string ext,
|
||||
SourceOrSinkElement baseSink, string originalInput
|
||||
SourceOrSinkElement baseSink, string originalInput, QlBuiltins::ExtensionId madId
|
||||
|
|
||||
sinkModel(namespace, type, subtypes, name, signature, ext, originalInput, kind, provenance) and
|
||||
sinkModel(namespace, type, subtypes, name, signature, ext, originalInput, kind, provenance,
|
||||
madId) and
|
||||
model = "MaD:" + madId.toString() and
|
||||
baseSink = interpretElement(namespace, type, subtypes, name, signature, ext) and
|
||||
(
|
||||
e = baseSink and originalInput = input
|
||||
@@ -301,14 +309,17 @@ module Private {
|
||||
* `input`, output specification `output`, kind `kind`, and provenance `provenance`.
|
||||
*/
|
||||
predicate summaryElement(
|
||||
Input::SummarizedCallableBase c, string input, string output, string kind, string provenance
|
||||
Input::SummarizedCallableBase c, string input, string output, string kind, string provenance,
|
||||
string model
|
||||
) {
|
||||
exists(
|
||||
string namespace, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string originalInput, string originalOutput, Callable baseCallable
|
||||
string originalInput, string originalOutput, Callable baseCallable,
|
||||
QlBuiltins::ExtensionId madId
|
||||
|
|
||||
summaryModel(namespace, type, subtypes, name, signature, ext, originalInput, originalOutput,
|
||||
kind, provenance) and
|
||||
kind, provenance, madId) and
|
||||
model = "MaD:" + madId.toString() and
|
||||
baseCallable = interpretElement(namespace, type, subtypes, name, signature, ext) and
|
||||
(
|
||||
c.asCallable() = baseCallable and input = originalInput and output = originalOutput
|
||||
|
||||
@@ -98,7 +98,7 @@ private module Cached {
|
||||
predicate localTaintStep(DataFlow::Node src, DataFlow::Node sink) {
|
||||
DataFlow::localFlowStep(src, sink)
|
||||
or
|
||||
localAdditionalTaintStep(src, sink)
|
||||
localAdditionalTaintStep(src, sink, _)
|
||||
or
|
||||
// Simple flow through library code is included in the exposed local
|
||||
// step relation, even though flow is technically inter-procedural
|
||||
@@ -119,14 +119,15 @@ private module Cached {
|
||||
* different objects.
|
||||
*/
|
||||
cached
|
||||
predicate localAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) {
|
||||
localAdditionalTaintExprStep(src.asExpr(), sink.asExpr())
|
||||
predicate localAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink, string model) {
|
||||
localAdditionalTaintExprStep(src.asExpr(), sink.asExpr(), model)
|
||||
or
|
||||
localAdditionalTaintUpdateStep(src.asExpr(),
|
||||
sink.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr())
|
||||
sink.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr(), model)
|
||||
or
|
||||
exists(DataFlow::Content f |
|
||||
readStep(src, f, sink) and
|
||||
model = "" and
|
||||
not sink.getTypeBound() instanceof PrimitiveType and
|
||||
not sink.getTypeBound() instanceof BoxedType and
|
||||
not sink.getTypeBound() instanceof NumberType and
|
||||
@@ -138,7 +139,7 @@ private module Cached {
|
||||
)
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(src.(DataFlowPrivate::FlowSummaryNode)
|
||||
.getSummaryNode(), sink.(DataFlowPrivate::FlowSummaryNode).getSummaryNode(), false)
|
||||
.getSummaryNode(), sink.(DataFlowPrivate::FlowSummaryNode).getSummaryNode(), false, model)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,10 +147,12 @@ private module Cached {
|
||||
* global taint flow configurations.
|
||||
*/
|
||||
cached
|
||||
predicate defaultAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) {
|
||||
localAdditionalTaintStep(src, sink) or
|
||||
entrypointFieldStep(src, sink) or
|
||||
any(AdditionalTaintStep a).step(src, sink)
|
||||
predicate defaultAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink, string model) {
|
||||
localAdditionalTaintStep(src, sink, model)
|
||||
or
|
||||
entrypointFieldStep(src, sink) and model = "entrypointFieldStep"
|
||||
or
|
||||
any(AdditionalTaintStep a).step(src, sink) and model = "AdditionalTaintStep"
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -198,26 +201,29 @@ predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::ContentSet c)
|
||||
* local data flow steps. That is, `src` and `sink` are likely to represent
|
||||
* different objects.
|
||||
*/
|
||||
private predicate localAdditionalTaintExprStep(Expr src, Expr sink) {
|
||||
sink.(AddExpr).getAnOperand() = src and sink.getType() instanceof TypeString
|
||||
private predicate localAdditionalTaintExprStep(Expr src, Expr sink, string model) {
|
||||
(
|
||||
sink.(AddExpr).getAnOperand() = src and sink.getType() instanceof TypeString
|
||||
or
|
||||
sink.(AssignAddExpr).getSource() = src and sink.getType() instanceof TypeString
|
||||
or
|
||||
sink.(StringTemplateExpr).getComponent(_) = src
|
||||
or
|
||||
sink.(LogicExpr).getAnOperand() = src
|
||||
) and
|
||||
model = ""
|
||||
or
|
||||
sink.(AssignAddExpr).getSource() = src and sink.getType() instanceof TypeString
|
||||
constructorStep(src, sink, model)
|
||||
or
|
||||
sink.(StringTemplateExpr).getComponent(_) = src
|
||||
qualifierToMethodStep(src, sink, model)
|
||||
or
|
||||
sink.(LogicExpr).getAnOperand() = src
|
||||
argToMethodStep(src, sink, model)
|
||||
or
|
||||
constructorStep(src, sink)
|
||||
comparisonStep(src, sink) and model = ""
|
||||
or
|
||||
qualifierToMethodStep(src, sink)
|
||||
serializationStep(src, sink) and model = "serializationStep"
|
||||
or
|
||||
argToMethodStep(src, sink)
|
||||
or
|
||||
comparisonStep(src, sink)
|
||||
or
|
||||
serializationStep(src, sink)
|
||||
or
|
||||
formatStep(src, sink)
|
||||
formatStep(src, sink) and model = "formatStep"
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -226,12 +232,12 @@ private predicate localAdditionalTaintExprStep(Expr src, Expr sink) {
|
||||
* different objects.
|
||||
* This is restricted to cases where the step updates the value of `sink`.
|
||||
*/
|
||||
private predicate localAdditionalTaintUpdateStep(Expr src, Expr sink) {
|
||||
qualifierToArgumentStep(src, sink)
|
||||
private predicate localAdditionalTaintUpdateStep(Expr src, Expr sink, string model) {
|
||||
qualifierToArgumentStep(src, sink, model)
|
||||
or
|
||||
argToArgStep(src, sink)
|
||||
argToArgStep(src, sink, model)
|
||||
or
|
||||
argToQualifierStep(src, sink)
|
||||
argToQualifierStep(src, sink, model)
|
||||
}
|
||||
|
||||
private class BulkData extends RefType {
|
||||
@@ -263,19 +269,21 @@ private predicate inputStreamWrapper(Constructor c, int argi) {
|
||||
}
|
||||
|
||||
/** An object construction that preserves the data flow status of any of its arguments. */
|
||||
private predicate constructorStep(Expr tracked, ConstructorCall sink) {
|
||||
private predicate constructorStep(Expr tracked, ConstructorCall sink, string model) {
|
||||
exists(int argi | sink.getArgument(argi) = tracked |
|
||||
// wrappers constructed by extension
|
||||
exists(Constructor c, Parameter p, SuperConstructorInvocationStmt sup |
|
||||
c = sink.getConstructor() and
|
||||
p = c.getParameter(argi) and
|
||||
sup.getEnclosingCallable() = c and
|
||||
constructorStep(p.getAnAccess(), sup)
|
||||
constructorStep(p.getAnAccess(), sup, model)
|
||||
)
|
||||
or
|
||||
// a custom InputStream that wraps a tainted data source is tainted
|
||||
model = "inputStreamWrapper" and
|
||||
inputStreamWrapper(sink.getConstructor(), argi)
|
||||
or
|
||||
model = "TaintPreservingCallable" and
|
||||
sink.getConstructor().(TaintPreservingCallable).returnsTaintFrom(argToParam(sink, argi))
|
||||
)
|
||||
}
|
||||
@@ -289,8 +297,9 @@ private int argToParam(Call call, int argIdx) {
|
||||
}
|
||||
|
||||
/** Access to a method that passes taint from qualifier to argument. */
|
||||
private predicate qualifierToArgumentStep(Expr tracked, Expr sink) {
|
||||
private predicate qualifierToArgumentStep(Expr tracked, Expr sink, string model) {
|
||||
exists(MethodCall ma, int arg |
|
||||
model = "TaintPreservingCallable" and
|
||||
ma.getMethod().(TaintPreservingCallable).transfersTaint(-1, argToParam(ma, arg)) and
|
||||
tracked = ma.getQualifier() and
|
||||
sink = ma.getArgument(arg)
|
||||
@@ -298,17 +307,19 @@ private predicate qualifierToArgumentStep(Expr tracked, Expr sink) {
|
||||
}
|
||||
|
||||
/** Access to a method that passes taint from the qualifier. */
|
||||
private predicate qualifierToMethodStep(Expr tracked, MethodCall sink) {
|
||||
taintPreservingQualifierToMethod(sink.getMethod()) and
|
||||
private predicate qualifierToMethodStep(Expr tracked, MethodCall sink, string model) {
|
||||
taintPreservingQualifierToMethod(sink.getMethod(), model) and
|
||||
tracked = sink.getQualifier()
|
||||
}
|
||||
|
||||
/**
|
||||
* Methods that return tainted data when called on tainted data.
|
||||
*/
|
||||
private predicate taintPreservingQualifierToMethod(Method m) {
|
||||
private predicate taintPreservingQualifierToMethod(Method m, string model) {
|
||||
model = "" and
|
||||
m instanceof CloneMethod
|
||||
or
|
||||
model = "%StringWriter" and
|
||||
m.getDeclaringType().getQualifiedName().matches("%StringWriter") and
|
||||
(
|
||||
m.getName() = "getBuffer"
|
||||
@@ -316,29 +327,34 @@ private predicate taintPreservingQualifierToMethod(Method m) {
|
||||
m.getName() = "toString"
|
||||
)
|
||||
or
|
||||
model = "TypeObjectInputStream.read%" and
|
||||
m.getDeclaringType() instanceof TypeObjectInputStream and
|
||||
m.getName().matches("read%")
|
||||
or
|
||||
model = "SpringUntrustedDataType.getter" and
|
||||
m instanceof GetterMethod and
|
||||
m.getDeclaringType().getADescendant() instanceof SpringUntrustedDataType and
|
||||
not m.getDeclaringType() instanceof TypeObject
|
||||
or
|
||||
model = "TaintPreservingCallable" and
|
||||
m.(TaintPreservingCallable).returnsTaintFrom(-1)
|
||||
or
|
||||
model = "JaxRsResourceMethod" and
|
||||
exists(JaxRsResourceMethod resourceMethod |
|
||||
m.(GetterMethod).getDeclaringType() = resourceMethod.getAParameter().getType()
|
||||
)
|
||||
}
|
||||
|
||||
/** Access to a method that passes taint from an argument. */
|
||||
private predicate argToMethodStep(Expr tracked, MethodCall sink) {
|
||||
private predicate argToMethodStep(Expr tracked, MethodCall sink, string model) {
|
||||
exists(Method m, int i |
|
||||
m = sink.getMethod() and
|
||||
taintPreservingArgumentToMethod(m, argToParam(sink, i)) and
|
||||
taintPreservingArgumentToMethod(m, argToParam(sink, i), model) and
|
||||
tracked = sink.getArgument(i)
|
||||
)
|
||||
or
|
||||
exists(Method springResponseEntityOfOk |
|
||||
model = "SpringResponseEntity" and
|
||||
sink.getMethod() = springResponseEntityOfOk and
|
||||
springResponseEntityOfOk.getDeclaringType() instanceof SpringResponseEntity and
|
||||
springResponseEntityOfOk.hasName(["ok", "of"]) and
|
||||
@@ -347,6 +363,7 @@ private predicate argToMethodStep(Expr tracked, MethodCall sink) {
|
||||
)
|
||||
or
|
||||
exists(Method springResponseEntityBody |
|
||||
model = "SpringResponseEntityBodyBuilder" and
|
||||
sink.getMethod() = springResponseEntityBody and
|
||||
springResponseEntityBody.getDeclaringType() instanceof SpringResponseEntityBodyBuilder and
|
||||
springResponseEntityBody.hasName("body") and
|
||||
@@ -359,7 +376,8 @@ private predicate argToMethodStep(Expr tracked, MethodCall sink) {
|
||||
* Holds if `method` is a library method that returns tainted data if its
|
||||
* `arg`th argument is tainted.
|
||||
*/
|
||||
private predicate taintPreservingArgumentToMethod(Method method, int arg) {
|
||||
private predicate taintPreservingArgumentToMethod(Method method, int arg, string model) {
|
||||
model = "org.apache.commons.codec.binary.Base64" and
|
||||
method.getDeclaringType().hasQualifiedName("org.apache.commons.codec.binary", "Base64") and
|
||||
(
|
||||
method.getName() = "decodeBase64" and arg = 0
|
||||
@@ -367,6 +385,7 @@ private predicate taintPreservingArgumentToMethod(Method method, int arg) {
|
||||
method.getName().matches("encodeBase64%") and arg = 0
|
||||
)
|
||||
or
|
||||
model = "TaintPreservingCallable" and
|
||||
method.(TaintPreservingCallable).returnsTaintFrom(arg)
|
||||
}
|
||||
|
||||
@@ -374,8 +393,9 @@ private predicate taintPreservingArgumentToMethod(Method method, int arg) {
|
||||
* Holds if `tracked` and `sink` are arguments to a method that transfers taint
|
||||
* between arguments.
|
||||
*/
|
||||
private predicate argToArgStep(Expr tracked, Expr sink) {
|
||||
private predicate argToArgStep(Expr tracked, Expr sink, string model) {
|
||||
exists(MethodCall ma, Method method, int input, int output |
|
||||
model = "TaintPreservingCallable" and
|
||||
method.(TaintPreservingCallable).transfersTaint(argToParam(ma, input), argToParam(ma, output)) and
|
||||
ma.getMethod() = method and
|
||||
ma.getArgument(input) = tracked and
|
||||
@@ -387,8 +407,9 @@ private predicate argToArgStep(Expr tracked, Expr sink) {
|
||||
* Holds if `tracked` is the argument of a method that transfers taint
|
||||
* from the argument to the qualifier and `sink` is the qualifier.
|
||||
*/
|
||||
private predicate argToQualifierStep(Expr tracked, Expr sink) {
|
||||
private predicate argToQualifierStep(Expr tracked, Expr sink, string model) {
|
||||
exists(Method m, int i, MethodCall ma |
|
||||
model = "TaintPreservingCallable" and
|
||||
taintPreservingArgumentToQualifier(m, argToParam(ma, i)) and
|
||||
ma.getMethod() = m and
|
||||
tracked = ma.getArgument(i) and
|
||||
|
||||
@@ -127,7 +127,7 @@ abstract deprecated class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
this.isAdditionalTaintStep(node1, node2) or
|
||||
defaultAdditionalTaintStep(node1, node2)
|
||||
defaultAdditionalTaintStep(node1, node2, _)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -127,7 +127,7 @@ abstract deprecated class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
this.isAdditionalTaintStep(node1, node2) or
|
||||
defaultAdditionalTaintStep(node1, node2)
|
||||
defaultAdditionalTaintStep(node1, node2, _)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -127,7 +127,7 @@ abstract deprecated class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
this.isAdditionalTaintStep(node1, node2) or
|
||||
defaultAdditionalTaintStep(node1, node2)
|
||||
defaultAdditionalTaintStep(node1, node2, _)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -71,10 +71,13 @@ private class SummarizedCallableWithCallback extends SummarizedCallable {
|
||||
|
||||
SummarizedCallableWithCallback() { mayInvokeCallback(this.asCallable(), pos) }
|
||||
|
||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||
override predicate propagatesFlow(
|
||||
string input, string output, boolean preservesValue, string model
|
||||
) {
|
||||
input = "Argument[" + pos + "]" and
|
||||
output = "Argument[" + pos + "].Parameter[-1]" and
|
||||
preservesValue = true
|
||||
preservesValue = true and
|
||||
model = "heuristic-callback"
|
||||
}
|
||||
|
||||
override predicate hasProvenance(Provenance provenance) { provenance = "hq-generated" }
|
||||
|
||||
@@ -18,7 +18,7 @@ private class ExploitableStringLiteral extends StringLiteral {
|
||||
* where -1 is the qualifier; or -2 if no such argument exists.
|
||||
*/
|
||||
private predicate regexSinkKindInfo(string kind, boolean full, int strArg) {
|
||||
sinkModel(_, _, _, _, _, _, _, kind, _) and
|
||||
sinkModel(_, _, _, _, _, _, _, kind, _, _) and
|
||||
exists(string fullStr, string strArgStr |
|
||||
(
|
||||
full = true and fullStr = "f"
|
||||
|
||||
@@ -77,7 +77,7 @@ class ExternalApiDataNode extends DataFlow::Node {
|
||||
) and
|
||||
// Not already modeled as a taint step (we need both of these to handle `AdditionalTaintStep` subclasses as well)
|
||||
not TaintTracking::localTaintStep(this, _) and
|
||||
not TaintTracking::defaultAdditionalTaintStep(this, _) and
|
||||
not TaintTracking::defaultAdditionalTaintStep(this, _, _) and
|
||||
// Not a call to a known safe external API
|
||||
not call.getCallee() instanceof SafeExternalApiMethod
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ class ExternalApi extends Callable {
|
||||
pragma[nomagic]
|
||||
predicate hasSummary() {
|
||||
this = any(SummarizedCallable sc).asCallable() or
|
||||
TaintTracking::localAdditionalTaintStep(this.getAnInput(), _)
|
||||
TaintTracking::localAdditionalTaintStep(this.getAnInput(), _, _)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
|
||||
@@ -27,7 +27,7 @@ predicate summaryModelRow(
|
||||
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string input, string output, string kind, string provenance, string row
|
||||
) {
|
||||
summaryModel(package, type, subtypes, name, signature, ext, input, output, kind, provenance) and
|
||||
summaryModel(package, type, subtypes, name, signature, ext, input, output, kind, provenance, _) and
|
||||
row =
|
||||
package + ";" //
|
||||
+ type + ";" //
|
||||
@@ -61,7 +61,7 @@ private class CallableToTest extends Callable {
|
||||
exists(
|
||||
string namespace, string type, boolean subtypes, string name, string signature, string ext
|
||||
|
|
||||
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _, _) and
|
||||
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _, _, _) and
|
||||
this = interpretElement(namespace, type, subtypes, name, signature, ext) and
|
||||
this.isPublic() and
|
||||
getRootType(this.getDeclaringType()).(RefType).isPublic()
|
||||
|
||||
@@ -11,7 +11,7 @@ from
|
||||
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string input, string kind, string provenance
|
||||
where
|
||||
sinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance) and
|
||||
sinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance, _) and
|
||||
not provenance.matches("%generated")
|
||||
select package, type, subtypes, name, signature, ext, input, kind, provenance order by
|
||||
package, type, name, signature, input, kind
|
||||
|
||||
@@ -11,7 +11,7 @@ from
|
||||
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string output, string kind, string provenance
|
||||
where
|
||||
sourceModel(package, type, subtypes, name, signature, ext, output, kind, provenance) and
|
||||
sourceModel(package, type, subtypes, name, signature, ext, output, kind, provenance, _) and
|
||||
not provenance.matches("%generated")
|
||||
select package, type, subtypes, name, signature, ext, output, kind, provenance order by
|
||||
package, type, name, signature, output, kind
|
||||
|
||||
@@ -11,7 +11,7 @@ from
|
||||
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string input, string output, string kind, string provenance
|
||||
where
|
||||
summaryModel(package, type, subtypes, name, signature, ext, input, output, kind, provenance) and
|
||||
summaryModel(package, type, subtypes, name, signature, ext, input, output, kind, provenance, _) and
|
||||
not provenance.matches("%generated")
|
||||
select package, type, subtypes, name, signature, ext, input, output, kind, provenance order by
|
||||
package, type, name, signature, input, output, kind
|
||||
|
||||
@@ -29,7 +29,7 @@ class ExternalEndpoint extends Endpoint {
|
||||
override predicate hasSummary() {
|
||||
Endpoint.super.hasSummary()
|
||||
or
|
||||
TaintTracking::localAdditionalTaintStep(this.getAnInput(), _)
|
||||
TaintTracking::localAdditionalTaintStep(this.getAnInput(), _, _)
|
||||
}
|
||||
|
||||
override predicate isSource() {
|
||||
|
||||
@@ -8,7 +8,7 @@ private import ModelEditor
|
||||
* A class of effectively public callables from source code.
|
||||
*/
|
||||
class PublicEndpointFromSource extends Endpoint, ModelApi {
|
||||
override predicate isSource() { SourceSinkInterpretationInput::sourceElement(this, _, _, _) }
|
||||
override predicate isSource() { SourceSinkInterpretationInput::sourceElement(this, _, _, _, _) }
|
||||
|
||||
override predicate isSink() { SourceSinkInterpretationInput::sinkElement(this, _, _, _) }
|
||||
override predicate isSink() { SourceSinkInterpretationInput::sinkElement(this, _, _, _, _) }
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ predicate taintFlowUpdate(DataFlow::ParameterNode p1, DataFlow::ParameterNode p2
|
||||
|
||||
predicate summaryStep(FlowSummaryNode src, FlowSummaryNode sink) {
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(src.getSummaryNode(), sink.getSummaryNode(),
|
||||
false) or
|
||||
false, _) or
|
||||
FlowSummaryImpl::Private::Steps::summaryReadStep(src.getSummaryNode(), _, sink.getSummaryNode()) or
|
||||
FlowSummaryImpl::Private::Steps::summaryStoreStep(src.getSummaryNode(), _, sink.getSummaryNode())
|
||||
}
|
||||
@@ -22,7 +22,7 @@ predicate summaryStep(FlowSummaryNode src, FlowSummaryNode sink) {
|
||||
from DataFlow::Node src, DataFlow::Node sink
|
||||
where
|
||||
(
|
||||
localAdditionalTaintStep(src, sink) or
|
||||
localAdditionalTaintStep(src, sink, _) or
|
||||
FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(src, sink, _)
|
||||
) and
|
||||
not summaryStep(src, sink)
|
||||
|
||||
Reference in New Issue
Block a user