Java/Dataflow: Propagate MaD-id/model-id to PathGraph.

This commit is contained in:
Anders Schack-Mulligen
2024-01-10 14:40:07 +01:00
parent 1015ee9872
commit 2925e45434
31 changed files with 682 additions and 425 deletions

View File

@@ -208,7 +208,7 @@ signature module InputSig<LocationSig Location> {
* Holds if there is a simple local flow step from `node1` to `node2`. These
* are the value-preserving intra-callable flow steps.
*/
predicate simpleLocalFlowStep(Node node1, Node node2);
predicate simpleLocalFlowStep(Node node1, Node node2, string model);
/**
* Holds if the data-flow step from `node1` to `node2` can be used to
@@ -289,6 +289,10 @@ signature module InputSig<LocationSig Location> {
/** Extra data-flow steps needed for lambda flow analysis. */
predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue);
predicate knownSourceModel(Node sink, string model);
predicate knownSinkModel(Node sink, string model);
/**
* Holds if `n` should never be skipped over in the `PathGraph` and in path
* explanations.
@@ -585,6 +589,10 @@ module DataFlowMake<LocationSig Location, InputSig<Location> Lang> {
import Config
predicate accessPathLimit = Config::accessPathLimit/0;
predicate isAdditionalFlowStep(Node node1, Node node2, string model) {
Config::isAdditionalFlowStep(node1, node2) and model = ""
}
}
import Impl<C>
@@ -603,6 +611,10 @@ module DataFlowMake<LocationSig Location, InputSig<Location> Lang> {
import Config
predicate accessPathLimit = Config::accessPathLimit/0;
predicate isAdditionalFlowStep(Node node1, Node node2, string model) {
Config::isAdditionalFlowStep(node1, node2) and model = ""
}
}
import Impl<C>

View File

@@ -21,7 +21,7 @@ signature module InputSig<LocationSig Location, DF::InputSig<Location> Lang> {
* Holds if the additional step from `src` to `sink` should be included in all
* global taint flow configurations.
*/
predicate defaultAdditionalTaintStep(Lang::Node src, Lang::Node sink);
predicate defaultAdditionalTaintStep(Lang::Node src, Lang::Node sink, string model);
/**
* Holds if taint flow configurations should allow implicit reads of `c` at sinks
@@ -51,9 +51,9 @@ module TaintFlowMake<
Config::isBarrier(node) or defaultTaintSanitizer(node)
}
predicate isAdditionalFlowStep(DataFlowLang::Node node1, DataFlowLang::Node node2) {
Config::isAdditionalFlowStep(node1, node2) or
defaultAdditionalTaintStep(node1, node2)
predicate isAdditionalFlowStep(DataFlowLang::Node node1, DataFlowLang::Node node2, string model) {
Config::isAdditionalFlowStep(node1, node2, model) or
defaultAdditionalTaintStep(node1, node2, model)
}
predicate allowImplicitRead(DataFlowLang::Node node, DataFlowLang::ContentSet c) {
@@ -62,7 +62,7 @@ module TaintFlowMake<
(
Config::isSink(node) or
Config::isSink(node, _) or
Config::isAdditionalFlowStep(node, _) or
Config::isAdditionalFlowStep(node, _, _) or
Config::isAdditionalFlowStep(node, _, _, _)
) and
defaultImplicitTaintRead(node, c)
@@ -76,6 +76,12 @@ module TaintFlowMake<
private module Config0 implements DataFlowInternal::FullStateConfigSig {
import DataFlowInternal::DefaultState<Config>
import Config
predicate isAdditionalFlowStep(
DataFlowLang::Node node1, DataFlowLang::Node node2, string model
) {
Config::isAdditionalFlowStep(node1, node2) and model = ""
}
}
private module C implements DataFlowInternal::FullStateConfigSig {
@@ -96,6 +102,12 @@ module TaintFlowMake<
module GlobalWithState<DataFlow::StateConfigSig Config> implements DataFlow::GlobalFlowSig {
private module Config0 implements DataFlowInternal::FullStateConfigSig {
import Config
predicate isAdditionalFlowStep(
DataFlowLang::Node node1, DataFlowLang::Node node2, string model
) {
Config::isAdditionalFlowStep(node1, node2) and model = ""
}
}
private module C implements DataFlowInternal::FullStateConfigSig {

View File

@@ -67,7 +67,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
/**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
*/
predicate isAdditionalFlowStep(Node node1, Node node2);
predicate isAdditionalFlowStep(Node node1, Node node2, string model);
/**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
@@ -332,11 +332,11 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
/**
* Holds if data can flow in one local step from `node1` to `node2`.
*/
private predicate localFlowStepEx(NodeEx node1, NodeEx node2) {
private predicate localFlowStepEx(NodeEx node1, NodeEx node2, string model) {
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2), model) and
stepFilter(node1, node2)
)
or
@@ -344,18 +344,19 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
Config::allowImplicitRead(n, _) and
node1.asNode() = n and
node2.isImplicitReadNode(n, false) and
not fullBarrier(node1)
not fullBarrier(node1) and
model = ""
)
}
/**
* Holds if the additional step from `node1` to `node2` does not jump between callables.
*/
private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2) {
private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, string model) {
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
Config::isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
Config::isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2), model) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
stepFilter(node1, node2)
)
@@ -364,7 +365,8 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
Config::allowImplicitRead(n, _) and
node1.isImplicitReadNode(n, true) and
node2.asNode() = n and
not fullBarrier(node2)
not fullBarrier(node2) and
model = ""
)
}
@@ -396,11 +398,11 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
/**
* Holds if the additional step from `node1` to `node2` jumps between callables.
*/
private predicate additionalJumpStep(NodeEx node1, NodeEx node2) {
private predicate additionalJumpStep(NodeEx node1, NodeEx node2, string model) {
exists(Node n1, Node n2 |
node1.asNode() = n1 and
node2.asNode() = n2 and
Config::isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
Config::isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2), model) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
stepFilter(node1, node2) and
not Config::getAFeature() instanceof FeatureEqualSourceSinkCallContext
@@ -538,14 +540,14 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
if hasSourceCallCtx() then cc = true else cc = false
or
exists(NodeEx mid | fwdFlow(mid, cc) |
localFlowStepEx(mid, node) or
additionalLocalFlowStep(mid, node) or
localFlowStepEx(mid, node, _) or
additionalLocalFlowStep(mid, node, _) or
additionalLocalStateStep(mid, _, node, _)
)
or
exists(NodeEx mid | fwdFlow(mid, _) and cc = false |
jumpStepEx(mid, node) or
additionalJumpStep(mid, node) or
additionalJumpStep(mid, node, _) or
additionalJumpStateStep(mid, _, node, _)
)
or
@@ -731,14 +733,14 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
if hasSinkCallCtx() then toReturn = true else toReturn = false
or
exists(NodeEx mid | revFlow(mid, toReturn) |
localFlowStepEx(node, mid) or
additionalLocalFlowStep(node, mid) or
localFlowStepEx(node, mid, _) or
additionalLocalFlowStep(node, mid, _) or
additionalLocalStateStep(node, _, mid, _)
)
or
exists(NodeEx mid | revFlow(mid, _) and toReturn = false |
jumpStepEx(node, mid) or
additionalJumpStep(node, mid) or
additionalJumpStep(node, mid, _) or
additionalJumpStateStep(node, _, mid, _)
)
or
@@ -1018,16 +1020,49 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
private predicate sinkNode = Stage1::sinkNode/2;
pragma[noinline]
private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2) {
Stage1::revFlow(node2) and
localFlowStepEx(node1, node2)
private predicate sourceLabel(NodeEx node, string label) {
sourceNode(node, _) and
exists(Node n | n = node.asNode() |
exists(string model | knownSourceModel(n, model) and label = model)
or
not knownSourceModel(n, _) and label = ""
)
}
private predicate sinkLabel(NodeEx node, string label) {
sinkNode(node, _) and
exists(Node n | n = node.asNode() |
exists(string model | knownSinkModel(n, model) and label = model)
or
not knownSinkModel(n, _) and label = ""
)
}
bindingset[label1, label2]
pragma[inline_late]
private string mergeLabels(string label1, string label2) {
// Big-step, hidden nodes, and summaries all may need to merge labels.
// These cases are expected to involve at most one non-empty label, so
// we'll just discard the 2nd+ label for now.
if label1 = "" then result = label2 else result = label1
}
pragma[noinline]
private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2) {
Stage1::revFlow(node2) and
additionalLocalFlowStep(node1, node2)
private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, string label) {
exists(string model |
Stage1::revFlow(node2) and
localFlowStepEx(node1, node2, model) and
label = model
)
}
pragma[noinline]
private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, string label) {
exists(string model |
Stage1::revFlow(node2) and
additionalLocalFlowStep(node1, node2, model) and
label = model
)
}
pragma[nomagic]
@@ -1416,7 +1451,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
or
exists(NodeEx mid |
fwdFlow(mid, state, _, _, _, _, _, ap, apa) and
additionalJumpStep(mid, node) and
additionalJumpStep(mid, node, _) and
t = getNodeTyp(node) and
ap instanceof ApNil
)
@@ -2044,7 +2079,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
)
or
exists(NodeEx mid |
additionalJumpStep(node, mid) and
additionalJumpStep(node, mid, _) and
revFlow(pragma[only_bind_into](mid), state, _, _, ap) and
ap instanceof ApNil
)
@@ -2565,11 +2600,11 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
) {
(
preservesValue = true and
localFlowStepNodeCand1(node1, node2) and
localFlowStepNodeCand1(node1, node2, _) and
state1 = state2
or
preservesValue = false and
additionalLocalFlowStepNodeCand1(node1, node2) and
additionalLocalFlowStepNodeCand1(node1, node2, _) and
state1 = state2
or
preservesValue = false and
@@ -2654,7 +2689,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
or
jumpStepEx(_, node)
or
additionalJumpStep(_, node)
additionalJumpStep(_, node, _)
or
additionalJumpStateStep(_, _, node, state)
or
@@ -2682,7 +2717,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
private predicate localFlowExit(NodeEx node, FlowState state) {
exists(NodeEx next | Stage2::revFlow(next, state) |
jumpStepEx(node, next) or
additionalJumpStep(node, next) or
additionalJumpStep(node, next, _) or
flowIntoCallNodeCand2(_, node, next, _) or
flowOutOfCallNodeCand2(_, node, _, next, _) or
Stage2::storeStepCand(node, _, _, next, _, _) or
@@ -2704,14 +2739,15 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[noinline]
private predicate additionalLocalFlowStepNodeCand2(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, string label
) {
additionalLocalFlowStepNodeCand1(node1, node2) and
additionalLocalFlowStepNodeCand1(node1, node2, label) and
state1 = state2 and
Stage2::revFlow(node1, pragma[only_bind_into](state1), false) and
Stage2::revFlow(node2, pragma[only_bind_into](state2), false)
or
additionalLocalStateStep(node1, state1, node2, state2) and
label = "" and
Stage2::revFlow(node1, state1, false) and
Stage2::revFlow(node2, state2, false)
}
@@ -2726,7 +2762,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic]
private predicate localFlowStepPlus(
NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t,
LocalCallContext cc
LocalCallContext cc, string label
) {
not isUnreachableInCall1(node2, cc) and
not inBarrier(node2, state) and
@@ -2734,12 +2770,12 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
(
localFlowEntry(node1, pragma[only_bind_into](state)) and
(
localFlowStepNodeCand1(node1, node2) and
localFlowStepNodeCand1(node1, node2, label) and
preservesValue = true and
t = node1.getDataFlowType() and // irrelevant dummy value
Stage2::revFlow(node2, pragma[only_bind_into](state))
or
additionalLocalFlowStepNodeCand2(node1, state, node2, state) and
additionalLocalFlowStepNodeCand2(node1, state, node2, state, label) and
preservesValue = false and
t = node2.getDataFlowType()
) and
@@ -2748,21 +2784,24 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
not isUnreachableInCall1(node1, cc) and
not outBarrier(node1, state)
or
exists(NodeEx mid |
localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, cc) and
localFlowStepNodeCand1(mid, node2) and
exists(NodeEx mid, string label1, string label2 |
localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, cc,
label1) and
localFlowStepNodeCand1(mid, node2, label2) and
not outBarrier(mid, state) and
not mid instanceof FlowCheckNode and
Stage2::revFlow(node2, pragma[only_bind_into](state))
Stage2::revFlow(node2, pragma[only_bind_into](state)) and
label = mergeLabels(label1, label2)
)
or
exists(NodeEx mid |
localFlowStepPlus(node1, state, mid, _, _, cc) and
additionalLocalFlowStepNodeCand2(mid, state, node2, state) and
exists(NodeEx mid, string label1, string label2 |
localFlowStepPlus(node1, state, mid, _, _, cc, label1) and
additionalLocalFlowStepNodeCand2(mid, state, node2, state, label2) and
not outBarrier(mid, state) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = node2.getDataFlowType()
t = node2.getDataFlowType() and
label = mergeLabels(label1, label2)
)
)
}
@@ -2774,13 +2813,13 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic]
predicate localFlowBigStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, LocalCallContext callContext
DataFlowType t, LocalCallContext callContext, string label
) {
localFlowStepPlus(node1, state1, node2, preservesValue, t, callContext) and
localFlowStepPlus(node1, state1, node2, preservesValue, t, callContext, label) and
localFlowExit(node2, state1) and
state1 = state2
or
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2) and
additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, label) and
state1 != state2 and
preservesValue = false and
t = node2.getDataFlowType() and
@@ -2847,7 +2886,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
Typ t, LocalCc lcc
) {
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _, _) and
exists(lcc)
}
@@ -2934,7 +2973,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
Typ t, LocalCc lcc
) {
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _, _) and
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
PrevStage::revFlow(node2, pragma[only_bind_into](state2), _) and
exists(lcc)
@@ -3239,7 +3278,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
Typ t, LocalCc lcc
) {
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc, _) and
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
PrevStage::revFlow(node2, pragma[only_bind_into](state2), _)
}
@@ -3446,7 +3485,8 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
private newtype TPathNode =
TPathNodeMid(
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap,
string summaryLabel
) {
// A PathNode is introduced by a source ...
Stage5::revFlow(node, state) and
@@ -3454,14 +3494,15 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
sourceCallCtx(cc) and
sc instanceof SummaryCtxNone and
t = node.getDataFlowType() and
ap = TAccessPathNil()
ap = TAccessPathNil() and
summaryLabel = ""
or
// ... or a step from an existing PathNode to another node.
pathStep(_, node, state, cc, sc, t, ap)
pathStep(_, node, state, cc, sc, t, ap, summaryLabel, _)
} or
TPathNodeSink(NodeEx node, FlowState state) {
exists(PathNodeMid sink |
sink.isAtSink() and
sink.isAtSink(_) and
node = sink.getNodeEx() and
state = sink.getState()
)
@@ -3644,24 +3685,27 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
abstract FlowState getState();
/** Holds if this node is a source. */
abstract predicate isSource();
abstract predicate isSource(string label);
abstract PathNodeImpl getASuccessorImpl();
abstract PathNodeImpl getASuccessorImpl(string label);
private PathNodeImpl getASuccessorIfHidden() {
private PathNodeImpl getASuccessorIfHidden(string label) {
this.isHidden() and
result = this.getASuccessorImpl()
result = this.getASuccessorImpl(label)
}
pragma[nomagic]
private PathNodeImpl getANonHiddenSuccessor0() {
result = this.getASuccessorIfHidden*() and
not result.isHidden()
}
final PathNodeImpl getANonHiddenSuccessor() {
result = this.getASuccessorImpl().getANonHiddenSuccessor0() and
private PathNodeImpl getASuccessorFromNonHidden(string label) {
result = this.getASuccessorImpl(label) and
not this.isHidden()
or
exists(string l1, string l2 |
result = this.getASuccessorFromNonHidden(l1).getASuccessorIfHidden(l2) and
label = mergeLabels(l1, l2)
)
}
final PathNodeImpl getANonHiddenSuccessor(string label) {
result = this.getASuccessorFromNonHidden(label) and not result.isHidden()
}
abstract NodeEx getNodeEx();
@@ -3670,7 +3714,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
not Config::includeHiddenNodes() and
(
hiddenNode(this.getNodeEx().asNode()) and
not this.isSource() and
not this.isSource(_) and
not this instanceof PathNodeSink
or
this.getNodeEx() instanceof TNodeImplicitRead
@@ -3678,12 +3722,12 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
}
string getSourceGroup() {
this.isSource() and
this.isSource(_) and
Config::sourceGrouping(this.getNodeEx().asNode(), result)
}
predicate isFlowSource() {
this.isSource() and not exists(this.getSourceGroup())
this.isSource(_) and not exists(this.getSourceGroup())
or
this instanceof PathNodeSourceGroup
}
@@ -3743,7 +3787,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
private predicate directReach(PathNodeImpl n) {
n instanceof PathNodeSink or
n instanceof PathNodeSinkGroup or
directReach(n.getANonHiddenSuccessor())
directReach(n.getANonHiddenSuccessor(_))
}
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
@@ -3751,7 +3795,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) {
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
n1.getANonHiddenSuccessor(_) = n2 and directReach(n2)
}
private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2)
@@ -3796,10 +3840,10 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
final FlowState getState() { result = super.getState() }
/** Gets a successor of this node, if any. */
final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() }
final PathNode getASuccessor() { result = super.getANonHiddenSuccessor(_) }
/** Holds if this node is a source. */
final predicate isSource() { super.isSource() }
final predicate isSource() { super.isSource(_) }
/** Holds if this node is a grouping of source nodes. */
final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group) }
@@ -3814,9 +3858,11 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
module PathGraph implements PathGraphSig<PathNode> {
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
query predicate edges(PathNode a, PathNode b, string key, string val) {
a.getASuccessor() = b and
key = "provenance" and
val = ""
exists(string label |
a.(PathNodeImpl).getANonHiddenSuccessor(label) = b and
key = "provenance" and
val = label
)
}
/** Holds if `n` is a node in the graph of data flow path explanations. */
@@ -3845,8 +3891,9 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
SummaryCtx sc;
DataFlowType t;
AccessPath ap;
string summaryLabel;
PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, t, ap) }
PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, t, ap, summaryLabel) }
override NodeEx getNodeEx() { result = node }
@@ -3863,29 +3910,56 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
AccessPath getAp() { result = ap }
private PathNodeMid getSuccMid() {
string getSummaryLabel() { result = summaryLabel }
private PathNodeMid getSuccMid(string label) {
pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(),
result.getSummaryCtx(), result.getType(), result.getAp())
result.getSummaryCtx(), result.getType(), result.getAp(), _, label)
}
override PathNodeImpl getASuccessorImpl() {
private predicate isSourceWithLabel(string labelprefix) {
exists(string label |
this.isSource(label) and
label != "" and
labelprefix = "Src:" + label + " "
)
}
override PathNodeImpl getASuccessorImpl(string label) {
// an intermediate step to another intermediate node
result = this.getSuccMid()
exists(string l2 | result = this.getSuccMid(l2) |
not this.isSourceWithLabel(_) and label = l2
or
exists(string l1 |
this.isSourceWithLabel(l1) and
label = l1 + l2
)
)
or
// a final step to a sink
result = this.getSuccMid().projectToSink()
exists(string l2, string l3 | result = this.getSuccMid(l2).projectToSink(l3) |
not this.isSourceWithLabel(_) and
if l3 != "" then label = l2 + " Sink:" + l3 else label = l2
or
exists(string l1 |
this.isSourceWithLabel(l1) and
if l3 != "" then label = l1 + l2 + " Sink:" + l3 else label = l1 + l2
)
)
}
override predicate isSource() {
override predicate isSource(string label) {
sourceNode(node, state) and
sourceLabel(node, label) and
sourceCallCtx(cc) and
sc instanceof SummaryCtxNone and
t = node.getDataFlowType() and
ap = TAccessPathNil()
}
predicate isAtSink() {
predicate isAtSink(string label) {
sinkNode(node, state) and
sinkLabel(node, label) and
ap instanceof AccessPathNil and
if hasSinkCallCtx()
then
@@ -3904,8 +3978,8 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
else any()
}
PathNodeSink projectToSink() {
this.isAtSink() and
PathNodeSink projectToSink(string label) {
this.isAtSink(label) and
result.getNodeEx() = node and
result.getState() = state
}
@@ -3926,9 +4000,13 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
override FlowState getState() { result = state }
override PathNodeImpl getASuccessorImpl() { result = TPathNodeSinkGroup(this.getSinkGroup()) }
override PathNodeImpl getASuccessorImpl(string label) {
result = TPathNodeSinkGroup(this.getSinkGroup()) and label = ""
}
override predicate isSource() { sourceNode(node, state) }
override predicate isSource(string label) {
sourceNode(node, state) and sourceLabel(node, label)
}
string getSinkGroup() { Config::sinkGrouping(node.asNode(), result) }
}
@@ -3942,9 +4020,11 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
override FlowState getState() { none() }
override PathNodeImpl getASuccessorImpl() { result.getSourceGroup() = sourceGroup }
override PathNodeImpl getASuccessorImpl(string label) {
result.getSourceGroup() = sourceGroup and label = ""
}
override predicate isSource() { none() }
override predicate isSource(string label) { none() }
override string toString() { result = sourceGroup }
@@ -3960,9 +4040,9 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
override FlowState getState() { none() }
override PathNodeImpl getASuccessorImpl() { none() }
override PathNodeImpl getASuccessorImpl(string label) { none() }
override predicate isSource() { none() }
override predicate isSource(string label) { none() }
override string toString() { result = sinkGroup }
@@ -3971,7 +4051,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
private predicate pathNode(
PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc,
DataFlowType t, AccessPath ap, LocalCallContext localCC
DataFlowType t, AccessPath ap, string summaryLabel, LocalCallContext localCC
) {
midnode = mid.getNodeEx() and
state = mid.getState() and
@@ -3981,16 +4061,17 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
midnode.getEnclosingCallable()) and
t = mid.getType() and
ap = mid.getAp()
ap = mid.getAp() and
summaryLabel = mid.getSummaryLabel()
}
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t,
AccessPath ap
AccessPath ap, string summaryLabel, string label
) {
exists(DataFlowType t0, boolean isStoreStep |
pathStep0(mid, pragma[only_bind_into](node), pragma[only_bind_into](state), cc, sc, t0, ap,
isStoreStep) and
isStoreStep, summaryLabel, label) and
Stage5::revFlow(pragma[only_bind_into](node), pragma[only_bind_into](state), ap.getApprox()) and
strengthenType(node, t0, t) and
not inBarrier(node, state) and
@@ -4005,19 +4086,21 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic]
private predicate pathStep0(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t,
AccessPath ap, boolean isStoreStep
AccessPath ap, boolean isStoreStep, string summaryLabel, string label
) {
exists(NodeEx midnode, FlowState state0, LocalCallContext localCC |
pathNode(mid, midnode, state0, cc, sc, t, ap, localCC) and
localFlowBigStep(midnode, state0, node, state, true, _, localCC) and
isStoreStep = false
exists(NodeEx midnode, FlowState state0, string sl, LocalCallContext localCC |
pathNode(mid, midnode, state0, cc, sc, t, ap, sl, localCC) and
localFlowBigStep(midnode, state0, node, state, true, _, localCC, label) and
isStoreStep = false and
summaryLabel = mergeLabels(sl, label)
)
or
exists(NodeEx midnode, FlowState state0, LocalCallContext localCC |
pathNode(mid, midnode, state0, cc, sc, _, ap, localCC) and
localFlowBigStep(midnode, state0, node, state, false, t, localCC) and
exists(NodeEx midnode, FlowState state0, string sl, LocalCallContext localCC |
pathNode(mid, midnode, state0, cc, sc, _, ap, sl, localCC) and
localFlowBigStep(midnode, state0, node, state, false, t, localCC, label) and
ap instanceof AccessPathNil and
isStoreStep = false
isStoreStep = false and
summaryLabel = mergeLabels(sl, label)
)
or
jumpStepEx(mid.getNodeExOutgoing(), node) and
@@ -4026,16 +4109,19 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
sc instanceof SummaryCtxNone and
t = mid.getType() and
ap = mid.getAp() and
isStoreStep = false
isStoreStep = false and
summaryLabel = "" and
label = ""
or
additionalJumpStep(mid.getNodeExOutgoing(), node) and
additionalJumpStep(mid.getNodeExOutgoing(), node, label) and
state = mid.getState() and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
t = node.getDataFlowType() and
ap = TAccessPathNil() and
isStoreStep = false
isStoreStep = false and
summaryLabel = ""
or
additionalJumpStateStep(mid.getNodeExOutgoing(), mid.getState(), node, state) and
cc instanceof CallContextAny and
@@ -4043,36 +4129,47 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
mid.getAp() instanceof AccessPathNil and
t = node.getDataFlowType() and
ap = TAccessPathNil() and
isStoreStep = false
isStoreStep = false and
summaryLabel = "" and
label = ""
or
exists(Content c, DataFlowType t0, AccessPath ap0 |
pathStoreStep(mid, node, state, t0, ap0, c, t, cc) and
ap.isCons(c, t0, ap0) and
sc = mid.getSummaryCtx() and
isStoreStep = true
isStoreStep = true and
summaryLabel = mid.getSummaryLabel() and
label = ""
)
or
exists(Content c, AccessPath ap0 |
pathReadStep(mid, node, state, ap0, c, cc) and
ap0.isCons(c, t, ap) and
sc = mid.getSummaryCtx() and
isStoreStep = false
isStoreStep = false and
summaryLabel = mid.getSummaryLabel() and
label = ""
)
or
pathIntoCallable(mid, node, state, _, cc, sc, _) and
t = mid.getType() and
ap = mid.getAp() and
isStoreStep = false
isStoreStep = false and
summaryLabel = "" and
label = ""
or
pathOutOfCallable(mid, node, state, cc) and
t = mid.getType() and
ap = mid.getAp() and
sc instanceof SummaryCtxNone and
isStoreStep = false
isStoreStep = false and
summaryLabel = "" and
label = ""
or
pathThroughCallable(mid, node, state, cc, t, ap) and
pathThroughCallable(mid, node, state, cc, t, ap, label) and
sc = mid.getSummaryCtx() and
isStoreStep = false
isStoreStep = false and
summaryLabel = mid.getSummaryLabel()
}
pragma[nomagic]
@@ -4178,7 +4275,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
DataFlowType t, AccessPath ap, AccessPathApprox apa
) {
exists(ArgNodeEx arg, ArgumentPosition apos |
pathNode(mid, arg, state, cc, _, t, ap, _) and
pathNode(mid, arg, state, cc, _, t, ap, _, _) and
not outBarrier(arg, state) and
arg.asNode().(ArgNode).argumentOf(call, apos) and
apa = ap.getApprox() and
@@ -4244,10 +4341,10 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic]
private predicate paramFlowsThrough(
ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, DataFlowType t,
AccessPath ap, AccessPathApprox apa
AccessPath ap, AccessPathApprox apa, string summaryLabel
) {
exists(RetNodeEx ret |
pathNode(_, ret, state, cc, sc, t, ap, _) and
pathNode(_, ret, state, cc, sc, t, ap, summaryLabel, _) and
kind = ret.getKind() and
apa = ap.getApprox() and
parameterFlowThroughAllowed(sc.getParamNode(), kind) and
@@ -4258,11 +4355,11 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic]
private predicate pathThroughCallable0(
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc,
DataFlowType t, AccessPath ap, AccessPathApprox apa
DataFlowType t, AccessPath ap, AccessPathApprox apa, string label
) {
exists(CallContext innercc, SummaryCtx sc |
pathIntoCallable(mid, _, _, cc, innercc, sc, call) and
paramFlowsThrough(kind, state, innercc, sc, t, ap, apa)
paramFlowsThrough(kind, state, innercc, sc, t, ap, apa, label)
)
}
@@ -4272,10 +4369,11 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
*/
pragma[noinline]
private predicate pathThroughCallable(
PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, AccessPath ap
PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, DataFlowType t, AccessPath ap,
string label
) {
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa |
pathThroughCallable0(call, mid, kind, state, cc, t, ap, apa) and
pathThroughCallable0(call, mid, kind, state, cc, t, ap, apa, label) and
out = getAnOutNodeFlow(kind, call, apa)
)
}
@@ -4291,10 +4389,10 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
ReturnKindExt kind, NodeEx out, FlowState sout, DataFlowType t, AccessPath apout
) {
pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](t),
pragma[only_bind_into](apout)) and
pragma[only_bind_into](apout), _) and
pathIntoCallable(arg, par, _, _, innercc, sc, _) and
paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc,
pragma[only_bind_into](t), pragma[only_bind_into](apout), _)
pragma[only_bind_into](t), pragma[only_bind_into](apout), _, _)
}
/**
@@ -4320,25 +4418,25 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
) {
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
subpaths02(arg, par, sc, innercc, kind, out, sout, t, apout) and
pathNode(ret, retnode, sout, innercc, sc, t, apout, _) and
pathNode(ret, retnode, sout, innercc, sc, t, apout, _, _) and
kind = retnode.getKind()
)
}
private PathNodeImpl localStep(PathNodeImpl n) {
n.getASuccessorImpl() = result and
n.getASuccessorImpl(_) = result and
exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() |
localFlowBigStep(n1, _, n2, _, _, _, _) or
localFlowBigStep(n1, _, n2, _, _, _, _, _) or
storeEx(n1, _, n2, _, _) or
readSetEx(n1, _, n2)
)
}
private PathNodeImpl summaryCtxStep(PathNodeImpl n) {
n.getASuccessorImpl() = result and
n.getASuccessorImpl(_) = result and
exists(SummaryCtxSome sc |
pathNode(n, _, _, _, pragma[only_bind_into](sc), _, _, _) and
pathNode(result, _, _, _, pragma[only_bind_into](sc), _, _, _)
pathNode(n, _, _, _, pragma[only_bind_into](sc), _, _, _, _) and
pathNode(result, _, _, _, pragma[only_bind_into](sc), _, _, _, _)
)
}
@@ -4354,7 +4452,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
pragma[nomagic]
private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) {
succ = pred.getASuccessorImpl() and
succ = pred.getASuccessorImpl(_) and
succNode = succ.getNodeEx()
}
@@ -4371,12 +4469,12 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
ParamNodeEx p, NodeEx o, FlowState sout, DataFlowType t, AccessPath apout,
PathNodeMid out0
|
pragma[only_bind_into](arg).getASuccessorImpl() = pragma[only_bind_into](out0) and
pragma[only_bind_into](arg).getASuccessorImpl(_) = pragma[only_bind_into](out0) and
subpaths03(pragma[only_bind_into](arg), p, ret, o, sout, t, apout) and
hasSuccessor(pragma[only_bind_into](arg), par, p) and
pathNode(out0, o, sout, _, _, t, apout, _)
pathNode(out0, o, sout, _, _, t, apout, _, _)
|
out = out0 or out = out0.projectToSink()
out = out0 or out = out0.projectToSink(_)
)
}
@@ -4428,7 +4526,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
or
exists(PathNodeImpl mid |
retReach(mid) and
n.getANonHiddenSuccessor() = mid and
n.getANonHiddenSuccessor(_) = mid and
not subpaths(_, mid, _, _)
)
}
@@ -4454,7 +4552,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
deprecated predicate hasFlowPath = flowPath/2;
private predicate flowsTo(PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink) {
flowsource.isSource() and
flowsource.isSource(_) and
flowsource.getNodeEx().asNode() = source and
(flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and
flowsink.getNodeEx().asNode() = sink
@@ -4597,7 +4695,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
exists(NodeEx node1, NodeEx node2 |
jumpStepEx(node1, node2)
or
additionalJumpStep(node1, node2)
additionalJumpStep(node1, node2, _)
or
additionalJumpStateStep(node1, _, node2, _)
or
@@ -5031,7 +5129,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
) {
not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and
(
localFlowStepEx(mid.getNodeEx(), node) and
localFlowStepEx(mid.getNodeEx(), node, _) and
state = mid.getState() and
cc = mid.getCallContext() and
sc1 = mid.getSummaryCtx1() and
@@ -5041,7 +5139,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
t = mid.getType() and
ap = mid.getAp()
or
additionalLocalFlowStep(mid.getNodeEx(), node) and
additionalLocalFlowStep(mid.getNodeEx(), node, _) and
state = mid.getState() and
cc = mid.getCallContext() and
sc1 = mid.getSummaryCtx1() and
@@ -5075,7 +5173,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
ap = mid.getAp() and
isStoreStep = false
or
additionalJumpStep(mid.getNodeEx(), node) and
additionalJumpStep(mid.getNodeEx(), node, _) and
state = mid.getState() and
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
@@ -5347,7 +5445,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1,
TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, PartialAccessPath ap, boolean isStoreStep
) {
localFlowStepEx(node, mid.getNodeEx()) and
localFlowStepEx(node, mid.getNodeEx(), _) and
state = mid.getState() and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
@@ -5355,7 +5453,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
ap = mid.getAp() and
isStoreStep = false
or
additionalLocalFlowStep(node, mid.getNodeEx()) and
additionalLocalFlowStep(node, mid.getNodeEx(), _) and
state = mid.getState() and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
@@ -5380,7 +5478,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
ap = mid.getAp() and
isStoreStep = false
or
additionalJumpStep(node, mid.getNodeEx()) and
additionalJumpStep(node, mid.getNodeEx(), _) and
state = mid.getState() and
sc1 = TRevSummaryCtx1None() and
sc2 = TRevSummaryCtx2None() and

View File

@@ -105,12 +105,14 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
storeContents.getAStoreContent() = loadContents.getAReadContent()
}
predicate simpleLocalSmallStep = simpleLocalFlowStepExt/2;
predicate simpleLocalSmallStep(Node node1, Node node2) {
simpleLocalFlowStepExt(node1, node2, _)
}
predicate levelStepNoCall(Node n1, LocalSourceNode n2) { none() }
predicate levelStepCall(Node n1, LocalSourceNode n2) {
argumentValueFlowsThrough(n1, TReadStepTypesNone(), n2)
argumentValueFlowsThrough(n1, TReadStepTypesNone(), n2, _)
}
// TODO: support setters
@@ -119,7 +121,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
private predicate loadStep0(Node n1, Node n2, Content f) {
readSet(n1, f, n2)
or
argumentValueFlowsThrough(n1, TReadStepTypesSome(_, f, _), n2)
argumentValueFlowsThrough(n1, TReadStepTypesSome(_, f, _), n2, _)
}
predicate loadStep(Node n1, LocalSourceNode n2, Content f) { loadStep0(n1, n2, f) }
@@ -293,7 +295,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
exists(Node mid, DataFlowType t0 |
revLambdaFlow(lambdaCall, kind, mid, t0, toReturn, toJump, lastCall)
|
simpleLocalFlowStep(node, mid) and
simpleLocalFlowStep(node, mid, _) and
t = t0
or
exists(boolean preservesValue |
@@ -870,7 +872,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
// local flow
exists(Node mid |
parameterValueFlowCand(p, mid, read) and
simpleLocalFlowStep(mid, node) and
simpleLocalFlowStep(mid, node, _) and
validParameterAliasStep(mid, node)
)
or
@@ -970,8 +972,8 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
* If a read step was taken, then `read` captures the `Content`, the
* container type, and the content type.
*/
predicate parameterValueFlow(ParamNode p, Node node, ReadStepTypesOption read) {
parameterValueFlow0(p, node, read) and
predicate parameterValueFlow(ParamNode p, Node node, ReadStepTypesOption read, string model) {
parameterValueFlow0(p, node, read, model) and
if node instanceof CastingNode
then
// normal flow through
@@ -983,60 +985,75 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
else any()
}
bindingset[model1, model2]
pragma[inline_late]
private string mergeModels(string model1, string model2) {
if model1 = "" then result = model2 else result = model1
}
pragma[nomagic]
private predicate parameterValueFlow0(ParamNode p, Node node, ReadStepTypesOption read) {
private predicate parameterValueFlow0(
ParamNode p, Node node, ReadStepTypesOption read, string model
) {
p = node and
Cand::cand(p, _) and
read = TReadStepTypesNone()
read = TReadStepTypesNone() and
model = ""
or
// local flow
exists(Node mid |
parameterValueFlow(p, mid, read) and
simpleLocalFlowStep(mid, node) and
validParameterAliasStep(mid, node)
exists(Node mid, string model1, string model2 |
parameterValueFlow(p, mid, read, model1) and
simpleLocalFlowStep(mid, node, model2) and
validParameterAliasStep(mid, node) and
model = mergeModels(model1, model2)
)
or
// read
exists(Node mid |
parameterValueFlow(p, mid, TReadStepTypesNone()) and
parameterValueFlow(p, mid, TReadStepTypesNone(), model) and
readStepWithTypes(mid, read.getContainerType(), read.getContent(), node,
read.getContentType()) and
Cand::parameterValueFlowReturnCand(p, _, true) and
compatibleTypes(getNodeDataFlowType(p), read.getContainerType())
)
or
parameterValueFlow0_0(TReadStepTypesNone(), p, node, read)
parameterValueFlow0_0(TReadStepTypesNone(), p, node, read, model)
}
pragma[nomagic]
private predicate parameterValueFlow0_0(
ReadStepTypesOption mustBeNone, ParamNode p, Node node, ReadStepTypesOption read
ReadStepTypesOption mustBeNone, ParamNode p, Node node, ReadStepTypesOption read,
string model
) {
// flow through: no prior read
exists(ArgNode arg |
parameterValueFlowArg(p, arg, mustBeNone) and
argumentValueFlowsThrough(arg, read, node)
exists(ArgNode arg, string model1, string model2 |
parameterValueFlowArg(p, arg, mustBeNone, model1) and
argumentValueFlowsThrough(arg, read, node, model2) and
model = mergeModels(model1, model2)
)
or
// flow through: no read inside method
exists(ArgNode arg |
parameterValueFlowArg(p, arg, read) and
argumentValueFlowsThrough(arg, mustBeNone, node)
exists(ArgNode arg, string model1, string model2 |
parameterValueFlowArg(p, arg, read, model1) and
argumentValueFlowsThrough(arg, mustBeNone, node, model2) and
model = mergeModels(model1, model2)
)
}
pragma[nomagic]
private predicate parameterValueFlowArg(ParamNode p, ArgNode arg, ReadStepTypesOption read) {
parameterValueFlow(p, arg, read) and
private predicate parameterValueFlowArg(
ParamNode p, ArgNode arg, ReadStepTypesOption read, string model
) {
parameterValueFlow(p, arg, read, model) and
Cand::argumentValueFlowsThroughCand(arg, _, _)
}
pragma[nomagic]
private predicate argumentValueFlowsThrough0(
DataFlowCall call, ArgNode arg, ReturnKind kind, ReadStepTypesOption read
DataFlowCall call, ArgNode arg, ReturnKind kind, ReadStepTypesOption read, string model
) {
exists(ParamNode param | viableParamArg(call, param, arg) |
parameterValueFlowReturn(param, kind, read)
parameterValueFlowReturn(param, kind, read, model)
)
}
@@ -1049,9 +1066,11 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
* container type, and the content type.
*/
cached
predicate argumentValueFlowsThrough(ArgNode arg, ReadStepTypesOption read, Node out) {
predicate argumentValueFlowsThrough(
ArgNode arg, ReadStepTypesOption read, Node out, string model
) {
exists(DataFlowCall call, ReturnKind kind |
argumentValueFlowsThrough0(call, arg, kind, read) and
argumentValueFlowsThrough0(call, arg, kind, read, model) and
out = getAnOutNode(call, kind)
|
// normal flow through
@@ -1072,7 +1091,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
* This predicate is exposed for testing only.
*/
predicate getterStep(ArgNode arg, ContentSet c, Node out) {
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out)
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out, _)
}
/**
@@ -1084,10 +1103,10 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
* container type, and the content type.
*/
private predicate parameterValueFlowReturn(
ParamNode p, ReturnKind kind, ReadStepTypesOption read
ParamNode p, ReturnKind kind, ReadStepTypesOption read, string model
) {
exists(ReturnNode ret |
parameterValueFlow(p, ret, read) and
parameterValueFlow(p, ret, read, model) and
kind = ret.getKind()
)
}
@@ -1103,7 +1122,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
* node `n`, in the same callable, using only value-preserving steps.
*/
private predicate parameterValueFlowsToPreUpdate(ParamNode p, PostUpdateNode n) {
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone(), _)
}
cached
@@ -1121,7 +1140,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
n2 = node2.(PostUpdateNode).getPreUpdateNode()
|
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1, _) // TODO
or
readSet(n2, c, n1) and
contentType = getNodeDataFlowType(n1) and
@@ -1152,7 +1171,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
* interface.
*/
private predicate reverseStepThroughInputOutputAlias(
PostUpdateNode fromNode, PostUpdateNode toNode
PostUpdateNode fromNode, PostUpdateNode toNode, string model
) {
exists(Node fromPre, Node toPre |
fromPre = fromNode.getPreUpdateNode() and
@@ -1163,17 +1182,17 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
// from function input to output?
fromPre = getAnOutNode(c, _) and
toPre.(ArgNode).argumentOf(c, _) and
simpleLocalFlowStep(toPre.(ArgNode), fromPre)
simpleLocalFlowStep(toPre.(ArgNode), fromPre, model)
)
or
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre)
argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre, model)
)
}
cached
predicate simpleLocalFlowStepExt(Node node1, Node node2) {
simpleLocalFlowStep(node1, node2) or
reverseStepThroughInputOutputAlias(node1, node2)
predicate simpleLocalFlowStepExt(Node node1, Node node2, string model) {
simpleLocalFlowStep(node1, node2, model) or
reverseStepThroughInputOutputAlias(node1, node2, model)
}
cached

View File

@@ -86,16 +86,16 @@ module MakeConsistency<
this instanceof ParameterNode or
this instanceof ReturnNode or
this = getAnOutNode(_, _) or
simpleLocalFlowStep(this, _) or
simpleLocalFlowStep(_, this) or
simpleLocalFlowStep(this, _, _) or
simpleLocalFlowStep(_, this, _) or
jumpStep(this, _) or
jumpStep(_, this) or
storeStep(this, _, _) or
storeStep(_, _, this) or
readStep(this, _, _) or
readStep(_, _, this) or
defaultAdditionalTaintStep(this, _) or
defaultAdditionalTaintStep(_, this)
defaultAdditionalTaintStep(this, _, _) or
defaultAdditionalTaintStep(_, this, _)
}
}
@@ -161,7 +161,7 @@ module MakeConsistency<
}
query predicate localFlowIsLocal(Node n1, Node n2, string msg) {
simpleLocalFlowStep(n1, n2) and
simpleLocalFlowStep(n1, n2, _) and
nodeGetEnclosingCallable(n1) != nodeGetEnclosingCallable(n2) and
msg = "Local flow step does not preserve enclosing callable."
}
@@ -247,7 +247,7 @@ module MakeConsistency<
query predicate postWithInFlow(PostUpdateNode n, string msg) {
not clearsContent(n, _) and
simpleLocalFlowStep(_, n) and
simpleLocalFlowStep(_, n, _) and
not Input::postWithInFlowExclude(n) and
msg = "PostUpdateNode should not be the target of local flow."
}
@@ -296,7 +296,7 @@ module MakeConsistency<
}
query predicate identityLocalStep(Node n, string msg) {
simpleLocalFlowStep(n, n) and
simpleLocalFlowStep(n, n, _) and
not Input::identityLocalStepExclude(n) and
msg = "Node steps to itself"
}

View File

@@ -210,9 +210,14 @@ module Make<
* Holds if data may flow from `input` to `output` through this callable.
*
* `preservesValue` indicates whether this is a value-preserving step or a taint-step.
*
* If `model` is non-empty then it indicates the provenance of the model
* defining this flow.
*/
pragma[nomagic]
abstract predicate propagatesFlow(string input, string output, boolean preservesValue);
abstract predicate propagatesFlow(
string input, string output, boolean preservesValue, string model
);
/**
* Holds if there exists a generated summary that applies to this callable.
@@ -398,9 +403,9 @@ module Make<
private predicate summarySpec(string spec) {
exists(SummarizedCallable c |
c.propagatesFlow(spec, _, _)
c.propagatesFlow(spec, _, _, _)
or
c.propagatesFlow(_, spec, _)
c.propagatesFlow(_, spec, _, _)
)
}
@@ -555,7 +560,7 @@ module Make<
*
* ```ql
* private class CAdapter extends SummarizedCallable instanceof C {
* override predicate propagatesFlow(string input, string output, boolean preservesValue) {
* override predicate propagatesFlow(string input, string output, boolean preservesValue, string model) {
* none()
* }
*
@@ -575,6 +580,9 @@ module Make<
* `preservesValue` indicates whether this is a value-preserving step
* or a taint-step.
*
* If `model` is non-empty then it indicates the provenance of the model
* defining this flow.
*
* Input specifications are restricted to stacks that end with
* `SummaryComponent::argument(_)`, preceded by zero or more
* `SummaryComponent::return(_)` or `SummaryComponent::content(_)` components.
@@ -591,7 +599,8 @@ module Make<
*/
pragma[nomagic]
abstract predicate propagatesFlow(
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue,
string model
);
/**
@@ -604,19 +613,19 @@ module Make<
pragma[nomagic]
private predicate summary(
SummarizedCallableImpl c, SummaryComponentStack input, SummaryComponentStack output,
boolean preservesValue
boolean preservesValue, string model
) {
c.propagatesFlow(input, output, preservesValue)
c.propagatesFlow(input, output, preservesValue, model)
or
// observe side effects of callbacks on input arguments
c.propagatesFlow(output, input, preservesValue) and
c.propagatesFlow(output, input, preservesValue, model) and
preservesValue = true and
isCallbackParameter(input) and
isContentOfArgument(output, _)
or
// flow from the receiver of a callback into the instance-parameter
exists(SummaryComponentStack s, SummaryComponentStack callbackRef |
c.propagatesFlow(s, _, _) or c.propagatesFlow(_, s, _)
c.propagatesFlow(s, _, _, model) or c.propagatesFlow(_, s, _, model)
|
callbackRef = s.drop(_) and
(isCallbackParameter(callbackRef) or callbackRef.head() = TReturnSummaryComponent(_)) and
@@ -626,7 +635,7 @@ module Make<
)
or
exists(SummaryComponentStack arg, SummaryComponentStack return |
derivedFluentFlow(c, input, arg, return, preservesValue)
derivedFluentFlow(c, input, arg, return, preservesValue, model)
|
arg.length() = 1 and
output = return
@@ -638,13 +647,17 @@ module Make<
)
or
// Chain together summaries where values get passed into callbacks along the way
exists(SummaryComponentStack mid, boolean preservesValue1, boolean preservesValue2 |
c.propagatesFlow(input, mid, preservesValue1) and
c.propagatesFlow(mid, output, preservesValue2) and
exists(
SummaryComponentStack mid, boolean preservesValue1, boolean preservesValue2, string model1,
string model2
|
c.propagatesFlow(input, mid, preservesValue1, model1) and
c.propagatesFlow(mid, output, preservesValue2, model2) and
mid.drop(mid.length() - 2) =
SummaryComponentStack::push(TParameterSummaryComponent(_),
SummaryComponentStack::singleton(TArgumentSummaryComponent(_))) and
preservesValue = preservesValue1.booleanAnd(preservesValue2)
preservesValue = preservesValue1.booleanAnd(preservesValue2) and
model = mergeModels(model1, model2)
)
}
@@ -665,22 +678,33 @@ module Make<
pragma[nomagic]
private predicate derivedFluentFlow(
SummarizedCallable c, SummaryComponentStack input, SummaryComponentStack arg,
SummaryComponentStack return, boolean preservesValue
SummaryComponentStack return, boolean preservesValue, string model
) {
exists(ParameterPosition pos |
summary(c, input, arg, preservesValue) and
exists(ParameterPosition pos, string model1, string model2 |
summary(c, input, arg, preservesValue, model1) and
isContentOfArgument(arg, pos) and
summary(c, SummaryComponentStack::argument(pos), return, true) and
return.bottom() = TReturnSummaryComponent(_)
summary(c, SummaryComponentStack::argument(pos), return, true, model2) and
return.bottom() = TReturnSummaryComponent(_) and
model = mergeModels(model1, model2)
)
}
bindingset[model1, model2]
pragma[inline_late]
private string mergeModels(string model1, string model2) {
model1 = "" and result = model2
or
model2 = "" and result = model1
or
model1 != "" and model2 != "" and result = model1 + "+" + model2
}
pragma[nomagic]
private predicate derivedFluentFlowPush(
SummarizedCallable c, SummaryComponentStack input, SummaryComponentStack arg,
SummaryComponent head, SummaryComponentStack tail, int i
) {
derivedFluentFlow(c, input, arg, tail, _) and
derivedFluentFlow(c, input, arg, tail, _, _) and
head = arg.drop(i).head() and
i = arg.length() - 2
or
@@ -702,7 +726,7 @@ module Make<
}
private predicate outputState(SummarizedCallable c, SummaryComponentStack s) {
summary(c, _, s, _)
summary(c, _, s, _, _)
or
exists(SummaryComponentStack out |
outputState(c, out) and
@@ -715,7 +739,7 @@ module Make<
}
private predicate inputState(SummarizedCallable c, SummaryComponentStack s) {
summary(c, s, _, _)
summary(c, s, _, _, _)
or
exists(SummaryComponentStack inp | inputState(c, inp) and s = inp.tail())
or
@@ -742,7 +766,7 @@ module Make<
*
* ```ql
* propagatesFlow(
* SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
* SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue, string model
* )
* ```
*
@@ -952,7 +976,7 @@ module Make<
*/
predicate summaryAllowParameterReturnInSelf(SummarizedCallable c, ParameterPosition ppos) {
exists(SummaryComponentStack inputContents, SummaryComponentStack outputContents |
summary(c, inputContents, outputContents, _) and
summary(c, inputContents, outputContents, _, _) and
inputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(ppos)) and
outputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(ppos))
)
@@ -1077,25 +1101,28 @@ module Make<
* Holds if there is a local step from `pred` to `succ`, which is synthesized
* from a flow summary.
*/
predicate summaryLocalStep(SummaryNode pred, SummaryNode succ, boolean preservesValue) {
predicate summaryLocalStep(
SummaryNode pred, SummaryNode succ, boolean preservesValue, string model
) {
exists(
SummarizedCallable c, SummaryComponentStack inputContents,
SummaryComponentStack outputContents
|
summary(c, inputContents, outputContents, preservesValue) and
summary(c, inputContents, outputContents, preservesValue, model) and
pred = summaryNodeInputState(pragma[only_bind_into](c), inputContents) and
succ = summaryNodeOutputState(pragma[only_bind_into](c), outputContents)
|
preservesValue = true
or
preservesValue = false and not summary(c, inputContents, outputContents, true)
preservesValue = false and not summary(c, inputContents, outputContents, true, _)
)
or
exists(SummarizedCallable c, SummaryComponentStack s |
pred = summaryNodeInputState(c, s.tail()) and
succ = summaryNodeInputState(c, s) and
s.head() = [SummaryComponent::withContent(_), SummaryComponent::withoutContent(_)] and
preservesValue = true
preservesValue = true and
model = ""
)
}
@@ -1202,7 +1229,7 @@ module Make<
or
exists(SummaryNode mid, boolean clearsOrExpectsMid |
paramReachesLocal(p, mid, clearsOrExpectsMid) and
summaryLocalStep(mid, n, true) and
summaryLocalStep(mid, n, true, _) and
if
summaryClearsContent(n, _) or
summaryExpectsContent(n, _)
@@ -1260,7 +1287,7 @@ module Make<
*/
predicate summaryThroughStepValue(ArgNode arg, Node out, SummarizedCallable sc) {
exists(ReturnKind rk, SummaryNode ret, DataFlowCall call |
summaryLocalStep(summaryArgParam(call, arg, sc), ret, true) and
summaryLocalStep(summaryArgParam(call, arg, sc), ret, true, _) and
summaryReturnNode(ret, pragma[only_bind_into](rk)) and
out = getAnOutNode(call, pragma[only_bind_into](rk))
)
@@ -1275,7 +1302,7 @@ module Make<
*/
predicate summaryThroughStepTaint(ArgNode arg, Node out, SummarizedCallable sc) {
exists(SummaryNode ret |
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), ret, false)
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), ret, false, _)
)
}
@@ -1289,7 +1316,7 @@ module Make<
predicate summaryGetterStep(ArgNode arg, ContentSet c, Node out, SummarizedCallable sc) {
exists(SummaryNode mid, SummaryNode ret |
summaryReadStep(summaryArgParamRetOut(arg, ret, out, sc), c, mid) and
summaryLocalStep(mid, ret, _)
summaryLocalStep(mid, ret, _, _)
)
}
@@ -1302,7 +1329,7 @@ module Make<
*/
predicate summarySetterStep(ArgNode arg, ContentSet c, Node out, SummarizedCallable sc) {
exists(SummaryNode mid, SummaryNode ret |
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), mid, _) and
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), mid, _, _) and
summaryStoreStep(mid, c, ret)
)
}
@@ -1425,10 +1452,11 @@ module Make<
private class SummarizedCallableImplAdapter extends SummarizedCallableImpl instanceof SummarizedCallable
{
override predicate propagatesFlow(
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue,
string model
) {
exists(AccessPath inSpec, AccessPath outSpec |
SummarizedCallable.super.propagatesFlow(inSpec, outSpec, preservesValue) and
SummarizedCallable.super.propagatesFlow(inSpec, outSpec, preservesValue, model) and
interpretSpec(inSpec, input) and
interpretSpec(outSpec, output)
)
@@ -1470,13 +1498,17 @@ module Make<
* Holds if an external source specification exists for `n` with output specification
* `output` and kind `kind`.
*/
predicate sourceElement(Element n, string output, string kind, Provenance provenance);
predicate sourceElement(
Element n, string output, string kind, Provenance provenance, string model
);
/**
* Holds if an external sink specification exists for `n` with input specification
* `input` and kind `kind`.
*/
predicate sinkElement(Element n, string input, string kind, Provenance provenance);
predicate sinkElement(
Element n, string input, string kind, Provenance provenance, string model
);
class SourceOrSinkElement extends Element;
@@ -1530,8 +1562,8 @@ module Make<
private import SourceSinkInterpretationInput
private predicate sourceSinkSpec(string spec) {
sourceElement(_, spec, _, _) or
sinkElement(_, spec, _, _)
sourceElement(_, spec, _, _, _) or
sinkElement(_, spec, _, _, _)
}
private module AccessPath = AccessPathSyntax::AccessPath<sourceSinkSpec/1>;
@@ -1560,10 +1592,10 @@ module Make<
}
private predicate sourceElementRef(
InterpretNode ref, SourceSinkAccessPath output, string kind
InterpretNode ref, SourceSinkAccessPath output, string kind, string model
) {
exists(SourceOrSinkElement e |
sourceElement(e, output, kind, _) and
sourceElement(e, output, kind, _, model) and
if outputNeedsReferenceExt(output.getToken(0))
then e = ref.getCallTarget()
else e = ref.asElement()
@@ -1575,9 +1607,11 @@ module Make<
inputNeedsReference(c)
}
private predicate sinkElementRef(InterpretNode ref, SourceSinkAccessPath input, string kind) {
private predicate sinkElementRef(
InterpretNode ref, SourceSinkAccessPath input, string kind, string model
) {
exists(SourceOrSinkElement e |
sinkElement(e, input, kind, _) and
sinkElement(e, input, kind, _, model) and
if inputNeedsReferenceExt(input.getToken(0))
then e = ref.getCallTarget()
else e = ref.asElement()
@@ -1588,7 +1622,7 @@ module Make<
private predicate interpretOutput(
SourceSinkAccessPath output, int n, InterpretNode ref, InterpretNode node
) {
sourceElementRef(ref, output, _) and
sourceElementRef(ref, output, _, _) and
n = 0 and
(
if output = ""
@@ -1638,7 +1672,7 @@ module Make<
private predicate interpretInput(
SourceSinkAccessPath input, int n, InterpretNode ref, InterpretNode node
) {
sinkElementRef(ref, input, _) and
sinkElementRef(ref, input, _, _) and
n = 0 and
(
if input = ""
@@ -1675,9 +1709,9 @@ module Make<
* Holds if `node` is specified as a source with the given kind in a MaD flow
* model.
*/
predicate isSourceNode(InterpretNode node, string kind) {
predicate isSourceNode(InterpretNode node, string kind, string model) {
exists(InterpretNode ref, SourceSinkAccessPath output |
sourceElementRef(ref, output, kind) and
sourceElementRef(ref, output, kind, model) and
interpretOutput(output, output.getNumToken(), ref, node)
)
}
@@ -1686,9 +1720,9 @@ module Make<
* Holds if `node` is specified as a sink with the given kind in a MaD flow
* model.
*/
predicate isSinkNode(InterpretNode node, string kind) {
predicate isSinkNode(InterpretNode node, string kind, string model) {
exists(InterpretNode ref, SourceSinkAccessPath input |
sinkElementRef(ref, input, kind) and
sinkElementRef(ref, input, kind, model) and
interpretInput(input, input.getNumToken(), ref, node)
)
}
@@ -1711,7 +1745,7 @@ module Make<
*/
query predicate source(string csv) {
exists(RelevantSource s, string output, string kind, Provenance provenance |
sourceElement(s, output, kind, provenance) and
sourceElement(s, output, kind, provenance, _) and
csv =
s.getCallableCsv() // Callable information
+ output + ";" // output
@@ -1728,7 +1762,7 @@ module Make<
*/
query predicate sink(string csv) {
exists(RelevantSink s, string input, string kind, Provenance provenance |
sinkElement(s, input, kind, provenance) and
sinkElement(s, input, kind, provenance, _) and
csv =
s.getCallableCsv() // Callable information
+ input + ";" // input
@@ -1883,7 +1917,7 @@ module Make<
private predicate edgesComponent(NodeOrCall a, NodeOrCall b, string value) {
exists(boolean preservesValue |
PrivateSteps::summaryLocalStep(a.asNode(), b.asNode(), preservesValue) and
PrivateSteps::summaryLocalStep(a.asNode(), b.asNode(), preservesValue, _) and
if preservesValue = true then value = "value" else value = "taint"
)
or