mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
C#/C++/Java: Unbreak partial data flow support
Partial data flow had a semantic merge conflict with this branch. The problem is that partial data flow doesn't (and shouldn't) cause the initial pruning steps to run, but the length-2 access paths depend on the `consCand` information that comes from that initial pruning. The solution is to restore the old `AccessPath` class, now called `PartialAccessPath` for use only by partial data flow. With this change, partial data flow will in some cases allow more field flow than non-partial data flow.
This commit is contained in:
@@ -2048,11 +2048,64 @@ private module FlowExploration {
|
||||
result = distSrcExt(TCallable(c, config)) - 1
|
||||
}
|
||||
|
||||
private newtype TPartialAccessPath =
|
||||
TPartialNil(DataFlowType t) or
|
||||
TPartialCons(Content f, int len) { len in [1 .. 5] }
|
||||
|
||||
/**
|
||||
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
||||
* element of the list and its length are tracked. If data flows from a source to
|
||||
* a given node with a given `AccessPath`, this indicates the sequence of
|
||||
* dereference operations needed to get from the value in the node to the
|
||||
* tracked object. The final type indicates the type of the tracked object.
|
||||
*/
|
||||
private class PartialAccessPath extends TPartialAccessPath {
|
||||
abstract string toString();
|
||||
|
||||
Content getHead() { this = TPartialCons(result, _) }
|
||||
|
||||
int len() {
|
||||
this = TPartialNil(_) and result = 0
|
||||
or
|
||||
this = TPartialCons(_, result)
|
||||
}
|
||||
|
||||
DataFlowType getType() {
|
||||
this = TPartialNil(result)
|
||||
or
|
||||
exists(Content head | this = TPartialCons(head, _) | result = head.getContainerType())
|
||||
}
|
||||
|
||||
abstract AccessPathFront getFront();
|
||||
}
|
||||
|
||||
private class PartialAccessPathNil extends PartialAccessPath, TPartialNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TPartialNil(t) | result = ppReprType(t))
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
exists(DataFlowType t | this = TPartialNil(t) | result = TFrontNil(t))
|
||||
}
|
||||
}
|
||||
|
||||
private class PartialAccessPathCons extends PartialAccessPath, TPartialCons {
|
||||
override string toString() {
|
||||
exists(Content f, int len | this = TPartialCons(f, len) |
|
||||
result = f.toString() + ", ... (" + len.toString() + ")"
|
||||
)
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
exists(Content f | this = TPartialCons(f, _) | result = TFrontHead(f))
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TPartialPathNode =
|
||||
TPartialPathNodeMk(Node node, CallContext cc, AccessPath ap, Configuration config) {
|
||||
TPartialPathNodeMk(Node node, CallContext cc, PartialAccessPath ap, Configuration config) {
|
||||
config.isSource(node) and
|
||||
cc instanceof CallContextAny and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
not fullBarrier(node, config) and
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
@@ -2062,7 +2115,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathNodeMk0(
|
||||
Node node, CallContext cc, AccessPath ap, Configuration config
|
||||
Node node, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PartialPathNode mid |
|
||||
partialPathStep(mid, node, cc, ap, config) and
|
||||
@@ -2138,7 +2191,7 @@ private module FlowExploration {
|
||||
|
||||
CallContext cc;
|
||||
|
||||
AccessPath ap;
|
||||
PartialAccessPath ap;
|
||||
|
||||
Configuration config;
|
||||
|
||||
@@ -2148,7 +2201,7 @@ private module FlowExploration {
|
||||
|
||||
CallContext getCallContext() { result = cc }
|
||||
|
||||
AccessPath getAp() { result = ap }
|
||||
PartialAccessPath getAp() { result = ap }
|
||||
|
||||
override Configuration getConfiguration() { result = config }
|
||||
|
||||
@@ -2161,7 +2214,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathStep(
|
||||
PartialPathNodePriv mid, Node node, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, Node node, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
localFlowStep(mid.getNode(), node, config) and
|
||||
cc = mid.getCallContext() and
|
||||
@@ -2170,8 +2223,8 @@ private module FlowExploration {
|
||||
or
|
||||
additionalLocalFlowStep(mid.getNode(), node, config) and
|
||||
cc = mid.getCallContext() and
|
||||
mid.getAp() instanceof AccessPathNil and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
mid.getAp() instanceof PartialAccessPathNil and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
jumpStep(mid.getNode(), node, config) and
|
||||
@@ -2181,15 +2234,15 @@ private module FlowExploration {
|
||||
or
|
||||
additionalJumpStep(mid.getNode(), node, config) and
|
||||
cc instanceof CallContextAny and
|
||||
mid.getAp() instanceof AccessPathNil and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
mid.getAp() instanceof PartialAccessPathNil and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
partialPathStoreStep(mid, _, _, node, ap) and
|
||||
cc = mid.getCallContext() and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
exists(AccessPath ap0, Content f |
|
||||
exists(PartialAccessPath ap0, Content f |
|
||||
partialPathReadStep(mid, ap0, f, node, cc, config) and
|
||||
apConsFwd(ap, f, ap0, config)
|
||||
)
|
||||
@@ -2210,7 +2263,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[inline]
|
||||
private predicate partialPathStoreStep(
|
||||
PartialPathNodePriv mid, AccessPath ap1, Content f, Node node, AccessPath ap2
|
||||
PartialPathNodePriv mid, PartialAccessPath ap1, Content f, Node node, PartialAccessPath ap2
|
||||
) {
|
||||
ap1 = mid.getAp() and
|
||||
store(mid.getNode(), f, node) and
|
||||
@@ -2220,7 +2273,9 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate apConsFwd(AccessPath ap1, Content f, AccessPath ap2, Configuration config) {
|
||||
private predicate apConsFwd(
|
||||
PartialAccessPath ap1, Content f, PartialAccessPath ap2, Configuration config
|
||||
) {
|
||||
exists(PartialPathNodePriv mid |
|
||||
partialPathStoreStep(mid, ap1, f, _, ap2) and
|
||||
config = mid.getConfiguration()
|
||||
@@ -2229,7 +2284,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathReadStep(
|
||||
PartialPathNodePriv mid, AccessPath ap, Content f, Node node, CallContext cc,
|
||||
PartialPathNodePriv mid, PartialAccessPath ap, Content f, Node node, CallContext cc,
|
||||
Configuration config
|
||||
) {
|
||||
ap = mid.getAp() and
|
||||
@@ -2240,7 +2295,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfCallable0(
|
||||
PartialPathNodePriv mid, ReturnPosition pos, CallContext innercc, AccessPath ap,
|
||||
PartialPathNodePriv mid, ReturnPosition pos, CallContext innercc, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
pos = getReturnPosition(mid.getNode()) and
|
||||
@@ -2252,8 +2307,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate partialPathOutOfCallable1(
|
||||
PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, AccessPath ap,
|
||||
Configuration config
|
||||
PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc |
|
||||
partialPathOutOfCallable0(mid, pos, innercc, ap, config) and
|
||||
@@ -2266,7 +2321,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ReturnKind kind, DataFlowCall call |
|
||||
partialPathOutOfCallable1(mid, call, kind, cc, ap, config)
|
||||
@@ -2276,7 +2331,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfArgument(
|
||||
PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, AccessPath ap,
|
||||
PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(
|
||||
@@ -2302,7 +2357,7 @@ private module FlowExploration {
|
||||
pragma[noinline]
|
||||
private predicate partialPathIntoArg(
|
||||
PartialPathNodePriv mid, int i, CallContext cc, DataFlowCall call, boolean emptyAp,
|
||||
AccessPath ap, Configuration config
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ArgumentNode arg |
|
||||
arg = mid.getNode() and
|
||||
@@ -2311,16 +2366,16 @@ private module FlowExploration {
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
|
|
||||
ap instanceof AccessPathNil and emptyAp = true
|
||||
ap instanceof PartialAccessPathNil and emptyAp = true
|
||||
or
|
||||
ap instanceof AccessPathCons and emptyAp = false
|
||||
ap instanceof PartialAccessPathCons and emptyAp = false
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathIntoCallable0(
|
||||
PartialPathNodePriv mid, DataFlowCallable callable, int i, CallContext outercc,
|
||||
DataFlowCall call, boolean emptyAp, AccessPath ap, Configuration config
|
||||
DataFlowCall call, boolean emptyAp, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
partialPathIntoArg(mid, i, outercc, call, emptyAp, ap, config) and
|
||||
callable = resolveCall(call, outercc)
|
||||
@@ -2328,7 +2383,7 @@ private module FlowExploration {
|
||||
|
||||
private predicate partialPathIntoCallable(
|
||||
PartialPathNodePriv mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
|
||||
DataFlowCall call, AccessPath ap, Configuration config
|
||||
DataFlowCall call, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable, boolean emptyAp |
|
||||
partialPathIntoCallable0(mid, callable, i, outercc, call, emptyAp, ap, config) and
|
||||
@@ -2342,7 +2397,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate paramFlowsThroughInPartialPath(
|
||||
ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config
|
||||
ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil,
|
||||
Configuration config
|
||||
) {
|
||||
exists(PartialPathNodePriv mid, ReturnNode ret |
|
||||
mid.getNode() = ret and
|
||||
@@ -2362,9 +2418,9 @@ private module FlowExploration {
|
||||
pragma[noinline]
|
||||
private predicate partialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc,
|
||||
AccessPathNil apnil, Configuration config
|
||||
PartialAccessPathNil apnil, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, CallContext innercc, AccessPathNil midapnil |
|
||||
exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil |
|
||||
partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and
|
||||
paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and
|
||||
not parameterValueFlowsThrough(p, kind, innercc)
|
||||
@@ -2372,7 +2428,8 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathThroughCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPathNil apnil, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil,
|
||||
Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and
|
||||
@@ -2382,8 +2439,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate valuePartialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, AccessPath ap,
|
||||
Configuration config
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, CallContext innercc |
|
||||
partialPathIntoCallable(mid, p, cc, innercc, call, ap, config) and
|
||||
@@ -2392,7 +2449,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate valuePartialPathThroughCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
valuePartialPathThroughCallable0(call, mid, kind, cc, ap, config) and
|
||||
|
||||
@@ -2048,11 +2048,64 @@ private module FlowExploration {
|
||||
result = distSrcExt(TCallable(c, config)) - 1
|
||||
}
|
||||
|
||||
private newtype TPartialAccessPath =
|
||||
TPartialNil(DataFlowType t) or
|
||||
TPartialCons(Content f, int len) { len in [1 .. 5] }
|
||||
|
||||
/**
|
||||
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
||||
* element of the list and its length are tracked. If data flows from a source to
|
||||
* a given node with a given `AccessPath`, this indicates the sequence of
|
||||
* dereference operations needed to get from the value in the node to the
|
||||
* tracked object. The final type indicates the type of the tracked object.
|
||||
*/
|
||||
private class PartialAccessPath extends TPartialAccessPath {
|
||||
abstract string toString();
|
||||
|
||||
Content getHead() { this = TPartialCons(result, _) }
|
||||
|
||||
int len() {
|
||||
this = TPartialNil(_) and result = 0
|
||||
or
|
||||
this = TPartialCons(_, result)
|
||||
}
|
||||
|
||||
DataFlowType getType() {
|
||||
this = TPartialNil(result)
|
||||
or
|
||||
exists(Content head | this = TPartialCons(head, _) | result = head.getContainerType())
|
||||
}
|
||||
|
||||
abstract AccessPathFront getFront();
|
||||
}
|
||||
|
||||
private class PartialAccessPathNil extends PartialAccessPath, TPartialNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TPartialNil(t) | result = ppReprType(t))
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
exists(DataFlowType t | this = TPartialNil(t) | result = TFrontNil(t))
|
||||
}
|
||||
}
|
||||
|
||||
private class PartialAccessPathCons extends PartialAccessPath, TPartialCons {
|
||||
override string toString() {
|
||||
exists(Content f, int len | this = TPartialCons(f, len) |
|
||||
result = f.toString() + ", ... (" + len.toString() + ")"
|
||||
)
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
exists(Content f | this = TPartialCons(f, _) | result = TFrontHead(f))
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TPartialPathNode =
|
||||
TPartialPathNodeMk(Node node, CallContext cc, AccessPath ap, Configuration config) {
|
||||
TPartialPathNodeMk(Node node, CallContext cc, PartialAccessPath ap, Configuration config) {
|
||||
config.isSource(node) and
|
||||
cc instanceof CallContextAny and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
not fullBarrier(node, config) and
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
@@ -2062,7 +2115,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathNodeMk0(
|
||||
Node node, CallContext cc, AccessPath ap, Configuration config
|
||||
Node node, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PartialPathNode mid |
|
||||
partialPathStep(mid, node, cc, ap, config) and
|
||||
@@ -2138,7 +2191,7 @@ private module FlowExploration {
|
||||
|
||||
CallContext cc;
|
||||
|
||||
AccessPath ap;
|
||||
PartialAccessPath ap;
|
||||
|
||||
Configuration config;
|
||||
|
||||
@@ -2148,7 +2201,7 @@ private module FlowExploration {
|
||||
|
||||
CallContext getCallContext() { result = cc }
|
||||
|
||||
AccessPath getAp() { result = ap }
|
||||
PartialAccessPath getAp() { result = ap }
|
||||
|
||||
override Configuration getConfiguration() { result = config }
|
||||
|
||||
@@ -2161,7 +2214,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathStep(
|
||||
PartialPathNodePriv mid, Node node, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, Node node, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
localFlowStep(mid.getNode(), node, config) and
|
||||
cc = mid.getCallContext() and
|
||||
@@ -2170,8 +2223,8 @@ private module FlowExploration {
|
||||
or
|
||||
additionalLocalFlowStep(mid.getNode(), node, config) and
|
||||
cc = mid.getCallContext() and
|
||||
mid.getAp() instanceof AccessPathNil and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
mid.getAp() instanceof PartialAccessPathNil and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
jumpStep(mid.getNode(), node, config) and
|
||||
@@ -2181,15 +2234,15 @@ private module FlowExploration {
|
||||
or
|
||||
additionalJumpStep(mid.getNode(), node, config) and
|
||||
cc instanceof CallContextAny and
|
||||
mid.getAp() instanceof AccessPathNil and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
mid.getAp() instanceof PartialAccessPathNil and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
partialPathStoreStep(mid, _, _, node, ap) and
|
||||
cc = mid.getCallContext() and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
exists(AccessPath ap0, Content f |
|
||||
exists(PartialAccessPath ap0, Content f |
|
||||
partialPathReadStep(mid, ap0, f, node, cc, config) and
|
||||
apConsFwd(ap, f, ap0, config)
|
||||
)
|
||||
@@ -2210,7 +2263,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[inline]
|
||||
private predicate partialPathStoreStep(
|
||||
PartialPathNodePriv mid, AccessPath ap1, Content f, Node node, AccessPath ap2
|
||||
PartialPathNodePriv mid, PartialAccessPath ap1, Content f, Node node, PartialAccessPath ap2
|
||||
) {
|
||||
ap1 = mid.getAp() and
|
||||
store(mid.getNode(), f, node) and
|
||||
@@ -2220,7 +2273,9 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate apConsFwd(AccessPath ap1, Content f, AccessPath ap2, Configuration config) {
|
||||
private predicate apConsFwd(
|
||||
PartialAccessPath ap1, Content f, PartialAccessPath ap2, Configuration config
|
||||
) {
|
||||
exists(PartialPathNodePriv mid |
|
||||
partialPathStoreStep(mid, ap1, f, _, ap2) and
|
||||
config = mid.getConfiguration()
|
||||
@@ -2229,7 +2284,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathReadStep(
|
||||
PartialPathNodePriv mid, AccessPath ap, Content f, Node node, CallContext cc,
|
||||
PartialPathNodePriv mid, PartialAccessPath ap, Content f, Node node, CallContext cc,
|
||||
Configuration config
|
||||
) {
|
||||
ap = mid.getAp() and
|
||||
@@ -2240,7 +2295,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfCallable0(
|
||||
PartialPathNodePriv mid, ReturnPosition pos, CallContext innercc, AccessPath ap,
|
||||
PartialPathNodePriv mid, ReturnPosition pos, CallContext innercc, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
pos = getReturnPosition(mid.getNode()) and
|
||||
@@ -2252,8 +2307,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate partialPathOutOfCallable1(
|
||||
PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, AccessPath ap,
|
||||
Configuration config
|
||||
PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc |
|
||||
partialPathOutOfCallable0(mid, pos, innercc, ap, config) and
|
||||
@@ -2266,7 +2321,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ReturnKind kind, DataFlowCall call |
|
||||
partialPathOutOfCallable1(mid, call, kind, cc, ap, config)
|
||||
@@ -2276,7 +2331,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfArgument(
|
||||
PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, AccessPath ap,
|
||||
PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(
|
||||
@@ -2302,7 +2357,7 @@ private module FlowExploration {
|
||||
pragma[noinline]
|
||||
private predicate partialPathIntoArg(
|
||||
PartialPathNodePriv mid, int i, CallContext cc, DataFlowCall call, boolean emptyAp,
|
||||
AccessPath ap, Configuration config
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ArgumentNode arg |
|
||||
arg = mid.getNode() and
|
||||
@@ -2311,16 +2366,16 @@ private module FlowExploration {
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
|
|
||||
ap instanceof AccessPathNil and emptyAp = true
|
||||
ap instanceof PartialAccessPathNil and emptyAp = true
|
||||
or
|
||||
ap instanceof AccessPathCons and emptyAp = false
|
||||
ap instanceof PartialAccessPathCons and emptyAp = false
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathIntoCallable0(
|
||||
PartialPathNodePriv mid, DataFlowCallable callable, int i, CallContext outercc,
|
||||
DataFlowCall call, boolean emptyAp, AccessPath ap, Configuration config
|
||||
DataFlowCall call, boolean emptyAp, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
partialPathIntoArg(mid, i, outercc, call, emptyAp, ap, config) and
|
||||
callable = resolveCall(call, outercc)
|
||||
@@ -2328,7 +2383,7 @@ private module FlowExploration {
|
||||
|
||||
private predicate partialPathIntoCallable(
|
||||
PartialPathNodePriv mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
|
||||
DataFlowCall call, AccessPath ap, Configuration config
|
||||
DataFlowCall call, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable, boolean emptyAp |
|
||||
partialPathIntoCallable0(mid, callable, i, outercc, call, emptyAp, ap, config) and
|
||||
@@ -2342,7 +2397,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate paramFlowsThroughInPartialPath(
|
||||
ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config
|
||||
ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil,
|
||||
Configuration config
|
||||
) {
|
||||
exists(PartialPathNodePriv mid, ReturnNode ret |
|
||||
mid.getNode() = ret and
|
||||
@@ -2362,9 +2418,9 @@ private module FlowExploration {
|
||||
pragma[noinline]
|
||||
private predicate partialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc,
|
||||
AccessPathNil apnil, Configuration config
|
||||
PartialAccessPathNil apnil, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, CallContext innercc, AccessPathNil midapnil |
|
||||
exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil |
|
||||
partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and
|
||||
paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and
|
||||
not parameterValueFlowsThrough(p, kind, innercc)
|
||||
@@ -2372,7 +2428,8 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathThroughCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPathNil apnil, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil,
|
||||
Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and
|
||||
@@ -2382,8 +2439,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate valuePartialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, AccessPath ap,
|
||||
Configuration config
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, CallContext innercc |
|
||||
partialPathIntoCallable(mid, p, cc, innercc, call, ap, config) and
|
||||
@@ -2392,7 +2449,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate valuePartialPathThroughCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
valuePartialPathThroughCallable0(call, mid, kind, cc, ap, config) and
|
||||
|
||||
@@ -2048,11 +2048,64 @@ private module FlowExploration {
|
||||
result = distSrcExt(TCallable(c, config)) - 1
|
||||
}
|
||||
|
||||
private newtype TPartialAccessPath =
|
||||
TPartialNil(DataFlowType t) or
|
||||
TPartialCons(Content f, int len) { len in [1 .. 5] }
|
||||
|
||||
/**
|
||||
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
||||
* element of the list and its length are tracked. If data flows from a source to
|
||||
* a given node with a given `AccessPath`, this indicates the sequence of
|
||||
* dereference operations needed to get from the value in the node to the
|
||||
* tracked object. The final type indicates the type of the tracked object.
|
||||
*/
|
||||
private class PartialAccessPath extends TPartialAccessPath {
|
||||
abstract string toString();
|
||||
|
||||
Content getHead() { this = TPartialCons(result, _) }
|
||||
|
||||
int len() {
|
||||
this = TPartialNil(_) and result = 0
|
||||
or
|
||||
this = TPartialCons(_, result)
|
||||
}
|
||||
|
||||
DataFlowType getType() {
|
||||
this = TPartialNil(result)
|
||||
or
|
||||
exists(Content head | this = TPartialCons(head, _) | result = head.getContainerType())
|
||||
}
|
||||
|
||||
abstract AccessPathFront getFront();
|
||||
}
|
||||
|
||||
private class PartialAccessPathNil extends PartialAccessPath, TPartialNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TPartialNil(t) | result = ppReprType(t))
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
exists(DataFlowType t | this = TPartialNil(t) | result = TFrontNil(t))
|
||||
}
|
||||
}
|
||||
|
||||
private class PartialAccessPathCons extends PartialAccessPath, TPartialCons {
|
||||
override string toString() {
|
||||
exists(Content f, int len | this = TPartialCons(f, len) |
|
||||
result = f.toString() + ", ... (" + len.toString() + ")"
|
||||
)
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
exists(Content f | this = TPartialCons(f, _) | result = TFrontHead(f))
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TPartialPathNode =
|
||||
TPartialPathNodeMk(Node node, CallContext cc, AccessPath ap, Configuration config) {
|
||||
TPartialPathNodeMk(Node node, CallContext cc, PartialAccessPath ap, Configuration config) {
|
||||
config.isSource(node) and
|
||||
cc instanceof CallContextAny and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
not fullBarrier(node, config) and
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
@@ -2062,7 +2115,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathNodeMk0(
|
||||
Node node, CallContext cc, AccessPath ap, Configuration config
|
||||
Node node, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PartialPathNode mid |
|
||||
partialPathStep(mid, node, cc, ap, config) and
|
||||
@@ -2138,7 +2191,7 @@ private module FlowExploration {
|
||||
|
||||
CallContext cc;
|
||||
|
||||
AccessPath ap;
|
||||
PartialAccessPath ap;
|
||||
|
||||
Configuration config;
|
||||
|
||||
@@ -2148,7 +2201,7 @@ private module FlowExploration {
|
||||
|
||||
CallContext getCallContext() { result = cc }
|
||||
|
||||
AccessPath getAp() { result = ap }
|
||||
PartialAccessPath getAp() { result = ap }
|
||||
|
||||
override Configuration getConfiguration() { result = config }
|
||||
|
||||
@@ -2161,7 +2214,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathStep(
|
||||
PartialPathNodePriv mid, Node node, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, Node node, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
localFlowStep(mid.getNode(), node, config) and
|
||||
cc = mid.getCallContext() and
|
||||
@@ -2170,8 +2223,8 @@ private module FlowExploration {
|
||||
or
|
||||
additionalLocalFlowStep(mid.getNode(), node, config) and
|
||||
cc = mid.getCallContext() and
|
||||
mid.getAp() instanceof AccessPathNil and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
mid.getAp() instanceof PartialAccessPathNil and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
jumpStep(mid.getNode(), node, config) and
|
||||
@@ -2181,15 +2234,15 @@ private module FlowExploration {
|
||||
or
|
||||
additionalJumpStep(mid.getNode(), node, config) and
|
||||
cc instanceof CallContextAny and
|
||||
mid.getAp() instanceof AccessPathNil and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
mid.getAp() instanceof PartialAccessPathNil and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
partialPathStoreStep(mid, _, _, node, ap) and
|
||||
cc = mid.getCallContext() and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
exists(AccessPath ap0, Content f |
|
||||
exists(PartialAccessPath ap0, Content f |
|
||||
partialPathReadStep(mid, ap0, f, node, cc, config) and
|
||||
apConsFwd(ap, f, ap0, config)
|
||||
)
|
||||
@@ -2210,7 +2263,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[inline]
|
||||
private predicate partialPathStoreStep(
|
||||
PartialPathNodePriv mid, AccessPath ap1, Content f, Node node, AccessPath ap2
|
||||
PartialPathNodePriv mid, PartialAccessPath ap1, Content f, Node node, PartialAccessPath ap2
|
||||
) {
|
||||
ap1 = mid.getAp() and
|
||||
store(mid.getNode(), f, node) and
|
||||
@@ -2220,7 +2273,9 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate apConsFwd(AccessPath ap1, Content f, AccessPath ap2, Configuration config) {
|
||||
private predicate apConsFwd(
|
||||
PartialAccessPath ap1, Content f, PartialAccessPath ap2, Configuration config
|
||||
) {
|
||||
exists(PartialPathNodePriv mid |
|
||||
partialPathStoreStep(mid, ap1, f, _, ap2) and
|
||||
config = mid.getConfiguration()
|
||||
@@ -2229,7 +2284,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathReadStep(
|
||||
PartialPathNodePriv mid, AccessPath ap, Content f, Node node, CallContext cc,
|
||||
PartialPathNodePriv mid, PartialAccessPath ap, Content f, Node node, CallContext cc,
|
||||
Configuration config
|
||||
) {
|
||||
ap = mid.getAp() and
|
||||
@@ -2240,7 +2295,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfCallable0(
|
||||
PartialPathNodePriv mid, ReturnPosition pos, CallContext innercc, AccessPath ap,
|
||||
PartialPathNodePriv mid, ReturnPosition pos, CallContext innercc, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
pos = getReturnPosition(mid.getNode()) and
|
||||
@@ -2252,8 +2307,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate partialPathOutOfCallable1(
|
||||
PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, AccessPath ap,
|
||||
Configuration config
|
||||
PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc |
|
||||
partialPathOutOfCallable0(mid, pos, innercc, ap, config) and
|
||||
@@ -2266,7 +2321,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ReturnKind kind, DataFlowCall call |
|
||||
partialPathOutOfCallable1(mid, call, kind, cc, ap, config)
|
||||
@@ -2276,7 +2331,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfArgument(
|
||||
PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, AccessPath ap,
|
||||
PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(
|
||||
@@ -2302,7 +2357,7 @@ private module FlowExploration {
|
||||
pragma[noinline]
|
||||
private predicate partialPathIntoArg(
|
||||
PartialPathNodePriv mid, int i, CallContext cc, DataFlowCall call, boolean emptyAp,
|
||||
AccessPath ap, Configuration config
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ArgumentNode arg |
|
||||
arg = mid.getNode() and
|
||||
@@ -2311,16 +2366,16 @@ private module FlowExploration {
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
|
|
||||
ap instanceof AccessPathNil and emptyAp = true
|
||||
ap instanceof PartialAccessPathNil and emptyAp = true
|
||||
or
|
||||
ap instanceof AccessPathCons and emptyAp = false
|
||||
ap instanceof PartialAccessPathCons and emptyAp = false
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathIntoCallable0(
|
||||
PartialPathNodePriv mid, DataFlowCallable callable, int i, CallContext outercc,
|
||||
DataFlowCall call, boolean emptyAp, AccessPath ap, Configuration config
|
||||
DataFlowCall call, boolean emptyAp, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
partialPathIntoArg(mid, i, outercc, call, emptyAp, ap, config) and
|
||||
callable = resolveCall(call, outercc)
|
||||
@@ -2328,7 +2383,7 @@ private module FlowExploration {
|
||||
|
||||
private predicate partialPathIntoCallable(
|
||||
PartialPathNodePriv mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
|
||||
DataFlowCall call, AccessPath ap, Configuration config
|
||||
DataFlowCall call, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable, boolean emptyAp |
|
||||
partialPathIntoCallable0(mid, callable, i, outercc, call, emptyAp, ap, config) and
|
||||
@@ -2342,7 +2397,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate paramFlowsThroughInPartialPath(
|
||||
ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config
|
||||
ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil,
|
||||
Configuration config
|
||||
) {
|
||||
exists(PartialPathNodePriv mid, ReturnNode ret |
|
||||
mid.getNode() = ret and
|
||||
@@ -2362,9 +2418,9 @@ private module FlowExploration {
|
||||
pragma[noinline]
|
||||
private predicate partialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc,
|
||||
AccessPathNil apnil, Configuration config
|
||||
PartialAccessPathNil apnil, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, CallContext innercc, AccessPathNil midapnil |
|
||||
exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil |
|
||||
partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and
|
||||
paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and
|
||||
not parameterValueFlowsThrough(p, kind, innercc)
|
||||
@@ -2372,7 +2428,8 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathThroughCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPathNil apnil, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil,
|
||||
Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and
|
||||
@@ -2382,8 +2439,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate valuePartialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, AccessPath ap,
|
||||
Configuration config
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, CallContext innercc |
|
||||
partialPathIntoCallable(mid, p, cc, innercc, call, ap, config) and
|
||||
@@ -2392,7 +2449,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate valuePartialPathThroughCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
valuePartialPathThroughCallable0(call, mid, kind, cc, ap, config) and
|
||||
|
||||
@@ -2048,11 +2048,64 @@ private module FlowExploration {
|
||||
result = distSrcExt(TCallable(c, config)) - 1
|
||||
}
|
||||
|
||||
private newtype TPartialAccessPath =
|
||||
TPartialNil(DataFlowType t) or
|
||||
TPartialCons(Content f, int len) { len in [1 .. 5] }
|
||||
|
||||
/**
|
||||
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
||||
* element of the list and its length are tracked. If data flows from a source to
|
||||
* a given node with a given `AccessPath`, this indicates the sequence of
|
||||
* dereference operations needed to get from the value in the node to the
|
||||
* tracked object. The final type indicates the type of the tracked object.
|
||||
*/
|
||||
private class PartialAccessPath extends TPartialAccessPath {
|
||||
abstract string toString();
|
||||
|
||||
Content getHead() { this = TPartialCons(result, _) }
|
||||
|
||||
int len() {
|
||||
this = TPartialNil(_) and result = 0
|
||||
or
|
||||
this = TPartialCons(_, result)
|
||||
}
|
||||
|
||||
DataFlowType getType() {
|
||||
this = TPartialNil(result)
|
||||
or
|
||||
exists(Content head | this = TPartialCons(head, _) | result = head.getContainerType())
|
||||
}
|
||||
|
||||
abstract AccessPathFront getFront();
|
||||
}
|
||||
|
||||
private class PartialAccessPathNil extends PartialAccessPath, TPartialNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TPartialNil(t) | result = ppReprType(t))
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
exists(DataFlowType t | this = TPartialNil(t) | result = TFrontNil(t))
|
||||
}
|
||||
}
|
||||
|
||||
private class PartialAccessPathCons extends PartialAccessPath, TPartialCons {
|
||||
override string toString() {
|
||||
exists(Content f, int len | this = TPartialCons(f, len) |
|
||||
result = f.toString() + ", ... (" + len.toString() + ")"
|
||||
)
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
exists(Content f | this = TPartialCons(f, _) | result = TFrontHead(f))
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TPartialPathNode =
|
||||
TPartialPathNodeMk(Node node, CallContext cc, AccessPath ap, Configuration config) {
|
||||
TPartialPathNodeMk(Node node, CallContext cc, PartialAccessPath ap, Configuration config) {
|
||||
config.isSource(node) and
|
||||
cc instanceof CallContextAny and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
not fullBarrier(node, config) and
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
@@ -2062,7 +2115,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathNodeMk0(
|
||||
Node node, CallContext cc, AccessPath ap, Configuration config
|
||||
Node node, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PartialPathNode mid |
|
||||
partialPathStep(mid, node, cc, ap, config) and
|
||||
@@ -2138,7 +2191,7 @@ private module FlowExploration {
|
||||
|
||||
CallContext cc;
|
||||
|
||||
AccessPath ap;
|
||||
PartialAccessPath ap;
|
||||
|
||||
Configuration config;
|
||||
|
||||
@@ -2148,7 +2201,7 @@ private module FlowExploration {
|
||||
|
||||
CallContext getCallContext() { result = cc }
|
||||
|
||||
AccessPath getAp() { result = ap }
|
||||
PartialAccessPath getAp() { result = ap }
|
||||
|
||||
override Configuration getConfiguration() { result = config }
|
||||
|
||||
@@ -2161,7 +2214,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathStep(
|
||||
PartialPathNodePriv mid, Node node, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, Node node, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
localFlowStep(mid.getNode(), node, config) and
|
||||
cc = mid.getCallContext() and
|
||||
@@ -2170,8 +2223,8 @@ private module FlowExploration {
|
||||
or
|
||||
additionalLocalFlowStep(mid.getNode(), node, config) and
|
||||
cc = mid.getCallContext() and
|
||||
mid.getAp() instanceof AccessPathNil and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
mid.getAp() instanceof PartialAccessPathNil and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
jumpStep(mid.getNode(), node, config) and
|
||||
@@ -2181,15 +2234,15 @@ private module FlowExploration {
|
||||
or
|
||||
additionalJumpStep(mid.getNode(), node, config) and
|
||||
cc instanceof CallContextAny and
|
||||
mid.getAp() instanceof AccessPathNil and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
mid.getAp() instanceof PartialAccessPathNil and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
partialPathStoreStep(mid, _, _, node, ap) and
|
||||
cc = mid.getCallContext() and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
exists(AccessPath ap0, Content f |
|
||||
exists(PartialAccessPath ap0, Content f |
|
||||
partialPathReadStep(mid, ap0, f, node, cc, config) and
|
||||
apConsFwd(ap, f, ap0, config)
|
||||
)
|
||||
@@ -2210,7 +2263,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[inline]
|
||||
private predicate partialPathStoreStep(
|
||||
PartialPathNodePriv mid, AccessPath ap1, Content f, Node node, AccessPath ap2
|
||||
PartialPathNodePriv mid, PartialAccessPath ap1, Content f, Node node, PartialAccessPath ap2
|
||||
) {
|
||||
ap1 = mid.getAp() and
|
||||
store(mid.getNode(), f, node) and
|
||||
@@ -2220,7 +2273,9 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate apConsFwd(AccessPath ap1, Content f, AccessPath ap2, Configuration config) {
|
||||
private predicate apConsFwd(
|
||||
PartialAccessPath ap1, Content f, PartialAccessPath ap2, Configuration config
|
||||
) {
|
||||
exists(PartialPathNodePriv mid |
|
||||
partialPathStoreStep(mid, ap1, f, _, ap2) and
|
||||
config = mid.getConfiguration()
|
||||
@@ -2229,7 +2284,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathReadStep(
|
||||
PartialPathNodePriv mid, AccessPath ap, Content f, Node node, CallContext cc,
|
||||
PartialPathNodePriv mid, PartialAccessPath ap, Content f, Node node, CallContext cc,
|
||||
Configuration config
|
||||
) {
|
||||
ap = mid.getAp() and
|
||||
@@ -2240,7 +2295,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfCallable0(
|
||||
PartialPathNodePriv mid, ReturnPosition pos, CallContext innercc, AccessPath ap,
|
||||
PartialPathNodePriv mid, ReturnPosition pos, CallContext innercc, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
pos = getReturnPosition(mid.getNode()) and
|
||||
@@ -2252,8 +2307,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate partialPathOutOfCallable1(
|
||||
PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, AccessPath ap,
|
||||
Configuration config
|
||||
PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc |
|
||||
partialPathOutOfCallable0(mid, pos, innercc, ap, config) and
|
||||
@@ -2266,7 +2321,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ReturnKind kind, DataFlowCall call |
|
||||
partialPathOutOfCallable1(mid, call, kind, cc, ap, config)
|
||||
@@ -2276,7 +2331,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfArgument(
|
||||
PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, AccessPath ap,
|
||||
PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(
|
||||
@@ -2302,7 +2357,7 @@ private module FlowExploration {
|
||||
pragma[noinline]
|
||||
private predicate partialPathIntoArg(
|
||||
PartialPathNodePriv mid, int i, CallContext cc, DataFlowCall call, boolean emptyAp,
|
||||
AccessPath ap, Configuration config
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ArgumentNode arg |
|
||||
arg = mid.getNode() and
|
||||
@@ -2311,16 +2366,16 @@ private module FlowExploration {
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
|
|
||||
ap instanceof AccessPathNil and emptyAp = true
|
||||
ap instanceof PartialAccessPathNil and emptyAp = true
|
||||
or
|
||||
ap instanceof AccessPathCons and emptyAp = false
|
||||
ap instanceof PartialAccessPathCons and emptyAp = false
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathIntoCallable0(
|
||||
PartialPathNodePriv mid, DataFlowCallable callable, int i, CallContext outercc,
|
||||
DataFlowCall call, boolean emptyAp, AccessPath ap, Configuration config
|
||||
DataFlowCall call, boolean emptyAp, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
partialPathIntoArg(mid, i, outercc, call, emptyAp, ap, config) and
|
||||
callable = resolveCall(call, outercc)
|
||||
@@ -2328,7 +2383,7 @@ private module FlowExploration {
|
||||
|
||||
private predicate partialPathIntoCallable(
|
||||
PartialPathNodePriv mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
|
||||
DataFlowCall call, AccessPath ap, Configuration config
|
||||
DataFlowCall call, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable, boolean emptyAp |
|
||||
partialPathIntoCallable0(mid, callable, i, outercc, call, emptyAp, ap, config) and
|
||||
@@ -2342,7 +2397,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate paramFlowsThroughInPartialPath(
|
||||
ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config
|
||||
ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil,
|
||||
Configuration config
|
||||
) {
|
||||
exists(PartialPathNodePriv mid, ReturnNode ret |
|
||||
mid.getNode() = ret and
|
||||
@@ -2362,9 +2418,9 @@ private module FlowExploration {
|
||||
pragma[noinline]
|
||||
private predicate partialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc,
|
||||
AccessPathNil apnil, Configuration config
|
||||
PartialAccessPathNil apnil, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, CallContext innercc, AccessPathNil midapnil |
|
||||
exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil |
|
||||
partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and
|
||||
paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and
|
||||
not parameterValueFlowsThrough(p, kind, innercc)
|
||||
@@ -2372,7 +2428,8 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathThroughCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPathNil apnil, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil,
|
||||
Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and
|
||||
@@ -2382,8 +2439,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate valuePartialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, AccessPath ap,
|
||||
Configuration config
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, CallContext innercc |
|
||||
partialPathIntoCallable(mid, p, cc, innercc, call, ap, config) and
|
||||
@@ -2392,7 +2449,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate valuePartialPathThroughCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
valuePartialPathThroughCallable0(call, mid, kind, cc, ap, config) and
|
||||
|
||||
@@ -2048,11 +2048,64 @@ private module FlowExploration {
|
||||
result = distSrcExt(TCallable(c, config)) - 1
|
||||
}
|
||||
|
||||
private newtype TPartialAccessPath =
|
||||
TPartialNil(DataFlowType t) or
|
||||
TPartialCons(Content f, int len) { len in [1 .. 5] }
|
||||
|
||||
/**
|
||||
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
||||
* element of the list and its length are tracked. If data flows from a source to
|
||||
* a given node with a given `AccessPath`, this indicates the sequence of
|
||||
* dereference operations needed to get from the value in the node to the
|
||||
* tracked object. The final type indicates the type of the tracked object.
|
||||
*/
|
||||
private class PartialAccessPath extends TPartialAccessPath {
|
||||
abstract string toString();
|
||||
|
||||
Content getHead() { this = TPartialCons(result, _) }
|
||||
|
||||
int len() {
|
||||
this = TPartialNil(_) and result = 0
|
||||
or
|
||||
this = TPartialCons(_, result)
|
||||
}
|
||||
|
||||
DataFlowType getType() {
|
||||
this = TPartialNil(result)
|
||||
or
|
||||
exists(Content head | this = TPartialCons(head, _) | result = head.getContainerType())
|
||||
}
|
||||
|
||||
abstract AccessPathFront getFront();
|
||||
}
|
||||
|
||||
private class PartialAccessPathNil extends PartialAccessPath, TPartialNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TPartialNil(t) | result = ppReprType(t))
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
exists(DataFlowType t | this = TPartialNil(t) | result = TFrontNil(t))
|
||||
}
|
||||
}
|
||||
|
||||
private class PartialAccessPathCons extends PartialAccessPath, TPartialCons {
|
||||
override string toString() {
|
||||
exists(Content f, int len | this = TPartialCons(f, len) |
|
||||
result = f.toString() + ", ... (" + len.toString() + ")"
|
||||
)
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
exists(Content f | this = TPartialCons(f, _) | result = TFrontHead(f))
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TPartialPathNode =
|
||||
TPartialPathNodeMk(Node node, CallContext cc, AccessPath ap, Configuration config) {
|
||||
TPartialPathNodeMk(Node node, CallContext cc, PartialAccessPath ap, Configuration config) {
|
||||
config.isSource(node) and
|
||||
cc instanceof CallContextAny and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
not fullBarrier(node, config) and
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
@@ -2062,7 +2115,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathNodeMk0(
|
||||
Node node, CallContext cc, AccessPath ap, Configuration config
|
||||
Node node, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PartialPathNode mid |
|
||||
partialPathStep(mid, node, cc, ap, config) and
|
||||
@@ -2138,7 +2191,7 @@ private module FlowExploration {
|
||||
|
||||
CallContext cc;
|
||||
|
||||
AccessPath ap;
|
||||
PartialAccessPath ap;
|
||||
|
||||
Configuration config;
|
||||
|
||||
@@ -2148,7 +2201,7 @@ private module FlowExploration {
|
||||
|
||||
CallContext getCallContext() { result = cc }
|
||||
|
||||
AccessPath getAp() { result = ap }
|
||||
PartialAccessPath getAp() { result = ap }
|
||||
|
||||
override Configuration getConfiguration() { result = config }
|
||||
|
||||
@@ -2161,7 +2214,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathStep(
|
||||
PartialPathNodePriv mid, Node node, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, Node node, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
localFlowStep(mid.getNode(), node, config) and
|
||||
cc = mid.getCallContext() and
|
||||
@@ -2170,8 +2223,8 @@ private module FlowExploration {
|
||||
or
|
||||
additionalLocalFlowStep(mid.getNode(), node, config) and
|
||||
cc = mid.getCallContext() and
|
||||
mid.getAp() instanceof AccessPathNil and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
mid.getAp() instanceof PartialAccessPathNil and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
jumpStep(mid.getNode(), node, config) and
|
||||
@@ -2181,15 +2234,15 @@ private module FlowExploration {
|
||||
or
|
||||
additionalJumpStep(mid.getNode(), node, config) and
|
||||
cc instanceof CallContextAny and
|
||||
mid.getAp() instanceof AccessPathNil and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
mid.getAp() instanceof PartialAccessPathNil and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
partialPathStoreStep(mid, _, _, node, ap) and
|
||||
cc = mid.getCallContext() and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
exists(AccessPath ap0, Content f |
|
||||
exists(PartialAccessPath ap0, Content f |
|
||||
partialPathReadStep(mid, ap0, f, node, cc, config) and
|
||||
apConsFwd(ap, f, ap0, config)
|
||||
)
|
||||
@@ -2210,7 +2263,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[inline]
|
||||
private predicate partialPathStoreStep(
|
||||
PartialPathNodePriv mid, AccessPath ap1, Content f, Node node, AccessPath ap2
|
||||
PartialPathNodePriv mid, PartialAccessPath ap1, Content f, Node node, PartialAccessPath ap2
|
||||
) {
|
||||
ap1 = mid.getAp() and
|
||||
store(mid.getNode(), f, node) and
|
||||
@@ -2220,7 +2273,9 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate apConsFwd(AccessPath ap1, Content f, AccessPath ap2, Configuration config) {
|
||||
private predicate apConsFwd(
|
||||
PartialAccessPath ap1, Content f, PartialAccessPath ap2, Configuration config
|
||||
) {
|
||||
exists(PartialPathNodePriv mid |
|
||||
partialPathStoreStep(mid, ap1, f, _, ap2) and
|
||||
config = mid.getConfiguration()
|
||||
@@ -2229,7 +2284,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathReadStep(
|
||||
PartialPathNodePriv mid, AccessPath ap, Content f, Node node, CallContext cc,
|
||||
PartialPathNodePriv mid, PartialAccessPath ap, Content f, Node node, CallContext cc,
|
||||
Configuration config
|
||||
) {
|
||||
ap = mid.getAp() and
|
||||
@@ -2240,7 +2295,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfCallable0(
|
||||
PartialPathNodePriv mid, ReturnPosition pos, CallContext innercc, AccessPath ap,
|
||||
PartialPathNodePriv mid, ReturnPosition pos, CallContext innercc, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
pos = getReturnPosition(mid.getNode()) and
|
||||
@@ -2252,8 +2307,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate partialPathOutOfCallable1(
|
||||
PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, AccessPath ap,
|
||||
Configuration config
|
||||
PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc |
|
||||
partialPathOutOfCallable0(mid, pos, innercc, ap, config) and
|
||||
@@ -2266,7 +2321,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ReturnKind kind, DataFlowCall call |
|
||||
partialPathOutOfCallable1(mid, call, kind, cc, ap, config)
|
||||
@@ -2276,7 +2331,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfArgument(
|
||||
PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, AccessPath ap,
|
||||
PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(
|
||||
@@ -2302,7 +2357,7 @@ private module FlowExploration {
|
||||
pragma[noinline]
|
||||
private predicate partialPathIntoArg(
|
||||
PartialPathNodePriv mid, int i, CallContext cc, DataFlowCall call, boolean emptyAp,
|
||||
AccessPath ap, Configuration config
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ArgumentNode arg |
|
||||
arg = mid.getNode() and
|
||||
@@ -2311,16 +2366,16 @@ private module FlowExploration {
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
|
|
||||
ap instanceof AccessPathNil and emptyAp = true
|
||||
ap instanceof PartialAccessPathNil and emptyAp = true
|
||||
or
|
||||
ap instanceof AccessPathCons and emptyAp = false
|
||||
ap instanceof PartialAccessPathCons and emptyAp = false
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathIntoCallable0(
|
||||
PartialPathNodePriv mid, DataFlowCallable callable, int i, CallContext outercc,
|
||||
DataFlowCall call, boolean emptyAp, AccessPath ap, Configuration config
|
||||
DataFlowCall call, boolean emptyAp, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
partialPathIntoArg(mid, i, outercc, call, emptyAp, ap, config) and
|
||||
callable = resolveCall(call, outercc)
|
||||
@@ -2328,7 +2383,7 @@ private module FlowExploration {
|
||||
|
||||
private predicate partialPathIntoCallable(
|
||||
PartialPathNodePriv mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
|
||||
DataFlowCall call, AccessPath ap, Configuration config
|
||||
DataFlowCall call, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable, boolean emptyAp |
|
||||
partialPathIntoCallable0(mid, callable, i, outercc, call, emptyAp, ap, config) and
|
||||
@@ -2342,7 +2397,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate paramFlowsThroughInPartialPath(
|
||||
ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config
|
||||
ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil,
|
||||
Configuration config
|
||||
) {
|
||||
exists(PartialPathNodePriv mid, ReturnNode ret |
|
||||
mid.getNode() = ret and
|
||||
@@ -2362,9 +2418,9 @@ private module FlowExploration {
|
||||
pragma[noinline]
|
||||
private predicate partialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc,
|
||||
AccessPathNil apnil, Configuration config
|
||||
PartialAccessPathNil apnil, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, CallContext innercc, AccessPathNil midapnil |
|
||||
exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil |
|
||||
partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and
|
||||
paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and
|
||||
not parameterValueFlowsThrough(p, kind, innercc)
|
||||
@@ -2372,7 +2428,8 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathThroughCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPathNil apnil, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil,
|
||||
Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and
|
||||
@@ -2382,8 +2439,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate valuePartialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, AccessPath ap,
|
||||
Configuration config
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, CallContext innercc |
|
||||
partialPathIntoCallable(mid, p, cc, innercc, call, ap, config) and
|
||||
@@ -2392,7 +2449,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate valuePartialPathThroughCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
valuePartialPathThroughCallable0(call, mid, kind, cc, ap, config) and
|
||||
|
||||
@@ -2048,11 +2048,64 @@ private module FlowExploration {
|
||||
result = distSrcExt(TCallable(c, config)) - 1
|
||||
}
|
||||
|
||||
private newtype TPartialAccessPath =
|
||||
TPartialNil(DataFlowType t) or
|
||||
TPartialCons(Content f, int len) { len in [1 .. 5] }
|
||||
|
||||
/**
|
||||
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
||||
* element of the list and its length are tracked. If data flows from a source to
|
||||
* a given node with a given `AccessPath`, this indicates the sequence of
|
||||
* dereference operations needed to get from the value in the node to the
|
||||
* tracked object. The final type indicates the type of the tracked object.
|
||||
*/
|
||||
private class PartialAccessPath extends TPartialAccessPath {
|
||||
abstract string toString();
|
||||
|
||||
Content getHead() { this = TPartialCons(result, _) }
|
||||
|
||||
int len() {
|
||||
this = TPartialNil(_) and result = 0
|
||||
or
|
||||
this = TPartialCons(_, result)
|
||||
}
|
||||
|
||||
DataFlowType getType() {
|
||||
this = TPartialNil(result)
|
||||
or
|
||||
exists(Content head | this = TPartialCons(head, _) | result = head.getContainerType())
|
||||
}
|
||||
|
||||
abstract AccessPathFront getFront();
|
||||
}
|
||||
|
||||
private class PartialAccessPathNil extends PartialAccessPath, TPartialNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TPartialNil(t) | result = ppReprType(t))
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
exists(DataFlowType t | this = TPartialNil(t) | result = TFrontNil(t))
|
||||
}
|
||||
}
|
||||
|
||||
private class PartialAccessPathCons extends PartialAccessPath, TPartialCons {
|
||||
override string toString() {
|
||||
exists(Content f, int len | this = TPartialCons(f, len) |
|
||||
result = f.toString() + ", ... (" + len.toString() + ")"
|
||||
)
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
exists(Content f | this = TPartialCons(f, _) | result = TFrontHead(f))
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TPartialPathNode =
|
||||
TPartialPathNodeMk(Node node, CallContext cc, AccessPath ap, Configuration config) {
|
||||
TPartialPathNodeMk(Node node, CallContext cc, PartialAccessPath ap, Configuration config) {
|
||||
config.isSource(node) and
|
||||
cc instanceof CallContextAny and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
not fullBarrier(node, config) and
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
@@ -2062,7 +2115,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathNodeMk0(
|
||||
Node node, CallContext cc, AccessPath ap, Configuration config
|
||||
Node node, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PartialPathNode mid |
|
||||
partialPathStep(mid, node, cc, ap, config) and
|
||||
@@ -2138,7 +2191,7 @@ private module FlowExploration {
|
||||
|
||||
CallContext cc;
|
||||
|
||||
AccessPath ap;
|
||||
PartialAccessPath ap;
|
||||
|
||||
Configuration config;
|
||||
|
||||
@@ -2148,7 +2201,7 @@ private module FlowExploration {
|
||||
|
||||
CallContext getCallContext() { result = cc }
|
||||
|
||||
AccessPath getAp() { result = ap }
|
||||
PartialAccessPath getAp() { result = ap }
|
||||
|
||||
override Configuration getConfiguration() { result = config }
|
||||
|
||||
@@ -2161,7 +2214,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathStep(
|
||||
PartialPathNodePriv mid, Node node, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, Node node, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
localFlowStep(mid.getNode(), node, config) and
|
||||
cc = mid.getCallContext() and
|
||||
@@ -2170,8 +2223,8 @@ private module FlowExploration {
|
||||
or
|
||||
additionalLocalFlowStep(mid.getNode(), node, config) and
|
||||
cc = mid.getCallContext() and
|
||||
mid.getAp() instanceof AccessPathNil and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
mid.getAp() instanceof PartialAccessPathNil and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
jumpStep(mid.getNode(), node, config) and
|
||||
@@ -2181,15 +2234,15 @@ private module FlowExploration {
|
||||
or
|
||||
additionalJumpStep(mid.getNode(), node, config) and
|
||||
cc instanceof CallContextAny and
|
||||
mid.getAp() instanceof AccessPathNil and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
mid.getAp() instanceof PartialAccessPathNil and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
partialPathStoreStep(mid, _, _, node, ap) and
|
||||
cc = mid.getCallContext() and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
exists(AccessPath ap0, Content f |
|
||||
exists(PartialAccessPath ap0, Content f |
|
||||
partialPathReadStep(mid, ap0, f, node, cc, config) and
|
||||
apConsFwd(ap, f, ap0, config)
|
||||
)
|
||||
@@ -2210,7 +2263,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[inline]
|
||||
private predicate partialPathStoreStep(
|
||||
PartialPathNodePriv mid, AccessPath ap1, Content f, Node node, AccessPath ap2
|
||||
PartialPathNodePriv mid, PartialAccessPath ap1, Content f, Node node, PartialAccessPath ap2
|
||||
) {
|
||||
ap1 = mid.getAp() and
|
||||
store(mid.getNode(), f, node) and
|
||||
@@ -2220,7 +2273,9 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate apConsFwd(AccessPath ap1, Content f, AccessPath ap2, Configuration config) {
|
||||
private predicate apConsFwd(
|
||||
PartialAccessPath ap1, Content f, PartialAccessPath ap2, Configuration config
|
||||
) {
|
||||
exists(PartialPathNodePriv mid |
|
||||
partialPathStoreStep(mid, ap1, f, _, ap2) and
|
||||
config = mid.getConfiguration()
|
||||
@@ -2229,7 +2284,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathReadStep(
|
||||
PartialPathNodePriv mid, AccessPath ap, Content f, Node node, CallContext cc,
|
||||
PartialPathNodePriv mid, PartialAccessPath ap, Content f, Node node, CallContext cc,
|
||||
Configuration config
|
||||
) {
|
||||
ap = mid.getAp() and
|
||||
@@ -2240,7 +2295,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfCallable0(
|
||||
PartialPathNodePriv mid, ReturnPosition pos, CallContext innercc, AccessPath ap,
|
||||
PartialPathNodePriv mid, ReturnPosition pos, CallContext innercc, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
pos = getReturnPosition(mid.getNode()) and
|
||||
@@ -2252,8 +2307,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate partialPathOutOfCallable1(
|
||||
PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, AccessPath ap,
|
||||
Configuration config
|
||||
PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc |
|
||||
partialPathOutOfCallable0(mid, pos, innercc, ap, config) and
|
||||
@@ -2266,7 +2321,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ReturnKind kind, DataFlowCall call |
|
||||
partialPathOutOfCallable1(mid, call, kind, cc, ap, config)
|
||||
@@ -2276,7 +2331,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfArgument(
|
||||
PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, AccessPath ap,
|
||||
PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(
|
||||
@@ -2302,7 +2357,7 @@ private module FlowExploration {
|
||||
pragma[noinline]
|
||||
private predicate partialPathIntoArg(
|
||||
PartialPathNodePriv mid, int i, CallContext cc, DataFlowCall call, boolean emptyAp,
|
||||
AccessPath ap, Configuration config
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ArgumentNode arg |
|
||||
arg = mid.getNode() and
|
||||
@@ -2311,16 +2366,16 @@ private module FlowExploration {
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
|
|
||||
ap instanceof AccessPathNil and emptyAp = true
|
||||
ap instanceof PartialAccessPathNil and emptyAp = true
|
||||
or
|
||||
ap instanceof AccessPathCons and emptyAp = false
|
||||
ap instanceof PartialAccessPathCons and emptyAp = false
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathIntoCallable0(
|
||||
PartialPathNodePriv mid, DataFlowCallable callable, int i, CallContext outercc,
|
||||
DataFlowCall call, boolean emptyAp, AccessPath ap, Configuration config
|
||||
DataFlowCall call, boolean emptyAp, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
partialPathIntoArg(mid, i, outercc, call, emptyAp, ap, config) and
|
||||
callable = resolveCall(call, outercc)
|
||||
@@ -2328,7 +2383,7 @@ private module FlowExploration {
|
||||
|
||||
private predicate partialPathIntoCallable(
|
||||
PartialPathNodePriv mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
|
||||
DataFlowCall call, AccessPath ap, Configuration config
|
||||
DataFlowCall call, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable, boolean emptyAp |
|
||||
partialPathIntoCallable0(mid, callable, i, outercc, call, emptyAp, ap, config) and
|
||||
@@ -2342,7 +2397,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate paramFlowsThroughInPartialPath(
|
||||
ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config
|
||||
ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil,
|
||||
Configuration config
|
||||
) {
|
||||
exists(PartialPathNodePriv mid, ReturnNode ret |
|
||||
mid.getNode() = ret and
|
||||
@@ -2362,9 +2418,9 @@ private module FlowExploration {
|
||||
pragma[noinline]
|
||||
private predicate partialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc,
|
||||
AccessPathNil apnil, Configuration config
|
||||
PartialAccessPathNil apnil, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, CallContext innercc, AccessPathNil midapnil |
|
||||
exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil |
|
||||
partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and
|
||||
paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and
|
||||
not parameterValueFlowsThrough(p, kind, innercc)
|
||||
@@ -2372,7 +2428,8 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathThroughCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPathNil apnil, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil,
|
||||
Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and
|
||||
@@ -2382,8 +2439,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate valuePartialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, AccessPath ap,
|
||||
Configuration config
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, CallContext innercc |
|
||||
partialPathIntoCallable(mid, p, cc, innercc, call, ap, config) and
|
||||
@@ -2392,7 +2449,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate valuePartialPathThroughCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
valuePartialPathThroughCallable0(call, mid, kind, cc, ap, config) and
|
||||
|
||||
@@ -2048,11 +2048,64 @@ private module FlowExploration {
|
||||
result = distSrcExt(TCallable(c, config)) - 1
|
||||
}
|
||||
|
||||
private newtype TPartialAccessPath =
|
||||
TPartialNil(DataFlowType t) or
|
||||
TPartialCons(Content f, int len) { len in [1 .. 5] }
|
||||
|
||||
/**
|
||||
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
||||
* element of the list and its length are tracked. If data flows from a source to
|
||||
* a given node with a given `AccessPath`, this indicates the sequence of
|
||||
* dereference operations needed to get from the value in the node to the
|
||||
* tracked object. The final type indicates the type of the tracked object.
|
||||
*/
|
||||
private class PartialAccessPath extends TPartialAccessPath {
|
||||
abstract string toString();
|
||||
|
||||
Content getHead() { this = TPartialCons(result, _) }
|
||||
|
||||
int len() {
|
||||
this = TPartialNil(_) and result = 0
|
||||
or
|
||||
this = TPartialCons(_, result)
|
||||
}
|
||||
|
||||
DataFlowType getType() {
|
||||
this = TPartialNil(result)
|
||||
or
|
||||
exists(Content head | this = TPartialCons(head, _) | result = head.getContainerType())
|
||||
}
|
||||
|
||||
abstract AccessPathFront getFront();
|
||||
}
|
||||
|
||||
private class PartialAccessPathNil extends PartialAccessPath, TPartialNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TPartialNil(t) | result = ppReprType(t))
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
exists(DataFlowType t | this = TPartialNil(t) | result = TFrontNil(t))
|
||||
}
|
||||
}
|
||||
|
||||
private class PartialAccessPathCons extends PartialAccessPath, TPartialCons {
|
||||
override string toString() {
|
||||
exists(Content f, int len | this = TPartialCons(f, len) |
|
||||
result = f.toString() + ", ... (" + len.toString() + ")"
|
||||
)
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
exists(Content f | this = TPartialCons(f, _) | result = TFrontHead(f))
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TPartialPathNode =
|
||||
TPartialPathNodeMk(Node node, CallContext cc, AccessPath ap, Configuration config) {
|
||||
TPartialPathNodeMk(Node node, CallContext cc, PartialAccessPath ap, Configuration config) {
|
||||
config.isSource(node) and
|
||||
cc instanceof CallContextAny and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
not fullBarrier(node, config) and
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
@@ -2062,7 +2115,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathNodeMk0(
|
||||
Node node, CallContext cc, AccessPath ap, Configuration config
|
||||
Node node, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PartialPathNode mid |
|
||||
partialPathStep(mid, node, cc, ap, config) and
|
||||
@@ -2138,7 +2191,7 @@ private module FlowExploration {
|
||||
|
||||
CallContext cc;
|
||||
|
||||
AccessPath ap;
|
||||
PartialAccessPath ap;
|
||||
|
||||
Configuration config;
|
||||
|
||||
@@ -2148,7 +2201,7 @@ private module FlowExploration {
|
||||
|
||||
CallContext getCallContext() { result = cc }
|
||||
|
||||
AccessPath getAp() { result = ap }
|
||||
PartialAccessPath getAp() { result = ap }
|
||||
|
||||
override Configuration getConfiguration() { result = config }
|
||||
|
||||
@@ -2161,7 +2214,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathStep(
|
||||
PartialPathNodePriv mid, Node node, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, Node node, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
localFlowStep(mid.getNode(), node, config) and
|
||||
cc = mid.getCallContext() and
|
||||
@@ -2170,8 +2223,8 @@ private module FlowExploration {
|
||||
or
|
||||
additionalLocalFlowStep(mid.getNode(), node, config) and
|
||||
cc = mid.getCallContext() and
|
||||
mid.getAp() instanceof AccessPathNil and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
mid.getAp() instanceof PartialAccessPathNil and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
jumpStep(mid.getNode(), node, config) and
|
||||
@@ -2181,15 +2234,15 @@ private module FlowExploration {
|
||||
or
|
||||
additionalJumpStep(mid.getNode(), node, config) and
|
||||
cc instanceof CallContextAny and
|
||||
mid.getAp() instanceof AccessPathNil and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
mid.getAp() instanceof PartialAccessPathNil and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
partialPathStoreStep(mid, _, _, node, ap) and
|
||||
cc = mid.getCallContext() and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
exists(AccessPath ap0, Content f |
|
||||
exists(PartialAccessPath ap0, Content f |
|
||||
partialPathReadStep(mid, ap0, f, node, cc, config) and
|
||||
apConsFwd(ap, f, ap0, config)
|
||||
)
|
||||
@@ -2210,7 +2263,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[inline]
|
||||
private predicate partialPathStoreStep(
|
||||
PartialPathNodePriv mid, AccessPath ap1, Content f, Node node, AccessPath ap2
|
||||
PartialPathNodePriv mid, PartialAccessPath ap1, Content f, Node node, PartialAccessPath ap2
|
||||
) {
|
||||
ap1 = mid.getAp() and
|
||||
store(mid.getNode(), f, node) and
|
||||
@@ -2220,7 +2273,9 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate apConsFwd(AccessPath ap1, Content f, AccessPath ap2, Configuration config) {
|
||||
private predicate apConsFwd(
|
||||
PartialAccessPath ap1, Content f, PartialAccessPath ap2, Configuration config
|
||||
) {
|
||||
exists(PartialPathNodePriv mid |
|
||||
partialPathStoreStep(mid, ap1, f, _, ap2) and
|
||||
config = mid.getConfiguration()
|
||||
@@ -2229,7 +2284,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathReadStep(
|
||||
PartialPathNodePriv mid, AccessPath ap, Content f, Node node, CallContext cc,
|
||||
PartialPathNodePriv mid, PartialAccessPath ap, Content f, Node node, CallContext cc,
|
||||
Configuration config
|
||||
) {
|
||||
ap = mid.getAp() and
|
||||
@@ -2240,7 +2295,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfCallable0(
|
||||
PartialPathNodePriv mid, ReturnPosition pos, CallContext innercc, AccessPath ap,
|
||||
PartialPathNodePriv mid, ReturnPosition pos, CallContext innercc, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
pos = getReturnPosition(mid.getNode()) and
|
||||
@@ -2252,8 +2307,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate partialPathOutOfCallable1(
|
||||
PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, AccessPath ap,
|
||||
Configuration config
|
||||
PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc |
|
||||
partialPathOutOfCallable0(mid, pos, innercc, ap, config) and
|
||||
@@ -2266,7 +2321,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ReturnKind kind, DataFlowCall call |
|
||||
partialPathOutOfCallable1(mid, call, kind, cc, ap, config)
|
||||
@@ -2276,7 +2331,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfArgument(
|
||||
PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, AccessPath ap,
|
||||
PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(
|
||||
@@ -2302,7 +2357,7 @@ private module FlowExploration {
|
||||
pragma[noinline]
|
||||
private predicate partialPathIntoArg(
|
||||
PartialPathNodePriv mid, int i, CallContext cc, DataFlowCall call, boolean emptyAp,
|
||||
AccessPath ap, Configuration config
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ArgumentNode arg |
|
||||
arg = mid.getNode() and
|
||||
@@ -2311,16 +2366,16 @@ private module FlowExploration {
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
|
|
||||
ap instanceof AccessPathNil and emptyAp = true
|
||||
ap instanceof PartialAccessPathNil and emptyAp = true
|
||||
or
|
||||
ap instanceof AccessPathCons and emptyAp = false
|
||||
ap instanceof PartialAccessPathCons and emptyAp = false
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathIntoCallable0(
|
||||
PartialPathNodePriv mid, DataFlowCallable callable, int i, CallContext outercc,
|
||||
DataFlowCall call, boolean emptyAp, AccessPath ap, Configuration config
|
||||
DataFlowCall call, boolean emptyAp, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
partialPathIntoArg(mid, i, outercc, call, emptyAp, ap, config) and
|
||||
callable = resolveCall(call, outercc)
|
||||
@@ -2328,7 +2383,7 @@ private module FlowExploration {
|
||||
|
||||
private predicate partialPathIntoCallable(
|
||||
PartialPathNodePriv mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
|
||||
DataFlowCall call, AccessPath ap, Configuration config
|
||||
DataFlowCall call, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable, boolean emptyAp |
|
||||
partialPathIntoCallable0(mid, callable, i, outercc, call, emptyAp, ap, config) and
|
||||
@@ -2342,7 +2397,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate paramFlowsThroughInPartialPath(
|
||||
ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config
|
||||
ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil,
|
||||
Configuration config
|
||||
) {
|
||||
exists(PartialPathNodePriv mid, ReturnNode ret |
|
||||
mid.getNode() = ret and
|
||||
@@ -2362,9 +2418,9 @@ private module FlowExploration {
|
||||
pragma[noinline]
|
||||
private predicate partialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc,
|
||||
AccessPathNil apnil, Configuration config
|
||||
PartialAccessPathNil apnil, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, CallContext innercc, AccessPathNil midapnil |
|
||||
exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil |
|
||||
partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and
|
||||
paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and
|
||||
not parameterValueFlowsThrough(p, kind, innercc)
|
||||
@@ -2372,7 +2428,8 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathThroughCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPathNil apnil, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil,
|
||||
Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and
|
||||
@@ -2382,8 +2439,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate valuePartialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, AccessPath ap,
|
||||
Configuration config
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, CallContext innercc |
|
||||
partialPathIntoCallable(mid, p, cc, innercc, call, ap, config) and
|
||||
@@ -2392,7 +2449,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate valuePartialPathThroughCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
valuePartialPathThroughCallable0(call, mid, kind, cc, ap, config) and
|
||||
|
||||
@@ -2048,11 +2048,64 @@ private module FlowExploration {
|
||||
result = distSrcExt(TCallable(c, config)) - 1
|
||||
}
|
||||
|
||||
private newtype TPartialAccessPath =
|
||||
TPartialNil(DataFlowType t) or
|
||||
TPartialCons(Content f, int len) { len in [1 .. 5] }
|
||||
|
||||
/**
|
||||
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
||||
* element of the list and its length are tracked. If data flows from a source to
|
||||
* a given node with a given `AccessPath`, this indicates the sequence of
|
||||
* dereference operations needed to get from the value in the node to the
|
||||
* tracked object. The final type indicates the type of the tracked object.
|
||||
*/
|
||||
private class PartialAccessPath extends TPartialAccessPath {
|
||||
abstract string toString();
|
||||
|
||||
Content getHead() { this = TPartialCons(result, _) }
|
||||
|
||||
int len() {
|
||||
this = TPartialNil(_) and result = 0
|
||||
or
|
||||
this = TPartialCons(_, result)
|
||||
}
|
||||
|
||||
DataFlowType getType() {
|
||||
this = TPartialNil(result)
|
||||
or
|
||||
exists(Content head | this = TPartialCons(head, _) | result = head.getContainerType())
|
||||
}
|
||||
|
||||
abstract AccessPathFront getFront();
|
||||
}
|
||||
|
||||
private class PartialAccessPathNil extends PartialAccessPath, TPartialNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TPartialNil(t) | result = ppReprType(t))
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
exists(DataFlowType t | this = TPartialNil(t) | result = TFrontNil(t))
|
||||
}
|
||||
}
|
||||
|
||||
private class PartialAccessPathCons extends PartialAccessPath, TPartialCons {
|
||||
override string toString() {
|
||||
exists(Content f, int len | this = TPartialCons(f, len) |
|
||||
result = f.toString() + ", ... (" + len.toString() + ")"
|
||||
)
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
exists(Content f | this = TPartialCons(f, _) | result = TFrontHead(f))
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TPartialPathNode =
|
||||
TPartialPathNodeMk(Node node, CallContext cc, AccessPath ap, Configuration config) {
|
||||
TPartialPathNodeMk(Node node, CallContext cc, PartialAccessPath ap, Configuration config) {
|
||||
config.isSource(node) and
|
||||
cc instanceof CallContextAny and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
not fullBarrier(node, config) and
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
@@ -2062,7 +2115,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathNodeMk0(
|
||||
Node node, CallContext cc, AccessPath ap, Configuration config
|
||||
Node node, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PartialPathNode mid |
|
||||
partialPathStep(mid, node, cc, ap, config) and
|
||||
@@ -2138,7 +2191,7 @@ private module FlowExploration {
|
||||
|
||||
CallContext cc;
|
||||
|
||||
AccessPath ap;
|
||||
PartialAccessPath ap;
|
||||
|
||||
Configuration config;
|
||||
|
||||
@@ -2148,7 +2201,7 @@ private module FlowExploration {
|
||||
|
||||
CallContext getCallContext() { result = cc }
|
||||
|
||||
AccessPath getAp() { result = ap }
|
||||
PartialAccessPath getAp() { result = ap }
|
||||
|
||||
override Configuration getConfiguration() { result = config }
|
||||
|
||||
@@ -2161,7 +2214,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathStep(
|
||||
PartialPathNodePriv mid, Node node, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, Node node, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
localFlowStep(mid.getNode(), node, config) and
|
||||
cc = mid.getCallContext() and
|
||||
@@ -2170,8 +2223,8 @@ private module FlowExploration {
|
||||
or
|
||||
additionalLocalFlowStep(mid.getNode(), node, config) and
|
||||
cc = mid.getCallContext() and
|
||||
mid.getAp() instanceof AccessPathNil and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
mid.getAp() instanceof PartialAccessPathNil and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
jumpStep(mid.getNode(), node, config) and
|
||||
@@ -2181,15 +2234,15 @@ private module FlowExploration {
|
||||
or
|
||||
additionalJumpStep(mid.getNode(), node, config) and
|
||||
cc instanceof CallContextAny and
|
||||
mid.getAp() instanceof AccessPathNil and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
mid.getAp() instanceof PartialAccessPathNil and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
partialPathStoreStep(mid, _, _, node, ap) and
|
||||
cc = mid.getCallContext() and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
exists(AccessPath ap0, Content f |
|
||||
exists(PartialAccessPath ap0, Content f |
|
||||
partialPathReadStep(mid, ap0, f, node, cc, config) and
|
||||
apConsFwd(ap, f, ap0, config)
|
||||
)
|
||||
@@ -2210,7 +2263,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[inline]
|
||||
private predicate partialPathStoreStep(
|
||||
PartialPathNodePriv mid, AccessPath ap1, Content f, Node node, AccessPath ap2
|
||||
PartialPathNodePriv mid, PartialAccessPath ap1, Content f, Node node, PartialAccessPath ap2
|
||||
) {
|
||||
ap1 = mid.getAp() and
|
||||
store(mid.getNode(), f, node) and
|
||||
@@ -2220,7 +2273,9 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate apConsFwd(AccessPath ap1, Content f, AccessPath ap2, Configuration config) {
|
||||
private predicate apConsFwd(
|
||||
PartialAccessPath ap1, Content f, PartialAccessPath ap2, Configuration config
|
||||
) {
|
||||
exists(PartialPathNodePriv mid |
|
||||
partialPathStoreStep(mid, ap1, f, _, ap2) and
|
||||
config = mid.getConfiguration()
|
||||
@@ -2229,7 +2284,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathReadStep(
|
||||
PartialPathNodePriv mid, AccessPath ap, Content f, Node node, CallContext cc,
|
||||
PartialPathNodePriv mid, PartialAccessPath ap, Content f, Node node, CallContext cc,
|
||||
Configuration config
|
||||
) {
|
||||
ap = mid.getAp() and
|
||||
@@ -2240,7 +2295,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfCallable0(
|
||||
PartialPathNodePriv mid, ReturnPosition pos, CallContext innercc, AccessPath ap,
|
||||
PartialPathNodePriv mid, ReturnPosition pos, CallContext innercc, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
pos = getReturnPosition(mid.getNode()) and
|
||||
@@ -2252,8 +2307,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate partialPathOutOfCallable1(
|
||||
PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, AccessPath ap,
|
||||
Configuration config
|
||||
PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc |
|
||||
partialPathOutOfCallable0(mid, pos, innercc, ap, config) and
|
||||
@@ -2266,7 +2321,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ReturnKind kind, DataFlowCall call |
|
||||
partialPathOutOfCallable1(mid, call, kind, cc, ap, config)
|
||||
@@ -2276,7 +2331,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfArgument(
|
||||
PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, AccessPath ap,
|
||||
PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(
|
||||
@@ -2302,7 +2357,7 @@ private module FlowExploration {
|
||||
pragma[noinline]
|
||||
private predicate partialPathIntoArg(
|
||||
PartialPathNodePriv mid, int i, CallContext cc, DataFlowCall call, boolean emptyAp,
|
||||
AccessPath ap, Configuration config
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ArgumentNode arg |
|
||||
arg = mid.getNode() and
|
||||
@@ -2311,16 +2366,16 @@ private module FlowExploration {
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
|
|
||||
ap instanceof AccessPathNil and emptyAp = true
|
||||
ap instanceof PartialAccessPathNil and emptyAp = true
|
||||
or
|
||||
ap instanceof AccessPathCons and emptyAp = false
|
||||
ap instanceof PartialAccessPathCons and emptyAp = false
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathIntoCallable0(
|
||||
PartialPathNodePriv mid, DataFlowCallable callable, int i, CallContext outercc,
|
||||
DataFlowCall call, boolean emptyAp, AccessPath ap, Configuration config
|
||||
DataFlowCall call, boolean emptyAp, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
partialPathIntoArg(mid, i, outercc, call, emptyAp, ap, config) and
|
||||
callable = resolveCall(call, outercc)
|
||||
@@ -2328,7 +2383,7 @@ private module FlowExploration {
|
||||
|
||||
private predicate partialPathIntoCallable(
|
||||
PartialPathNodePriv mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
|
||||
DataFlowCall call, AccessPath ap, Configuration config
|
||||
DataFlowCall call, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable, boolean emptyAp |
|
||||
partialPathIntoCallable0(mid, callable, i, outercc, call, emptyAp, ap, config) and
|
||||
@@ -2342,7 +2397,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate paramFlowsThroughInPartialPath(
|
||||
ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config
|
||||
ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil,
|
||||
Configuration config
|
||||
) {
|
||||
exists(PartialPathNodePriv mid, ReturnNode ret |
|
||||
mid.getNode() = ret and
|
||||
@@ -2362,9 +2418,9 @@ private module FlowExploration {
|
||||
pragma[noinline]
|
||||
private predicate partialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc,
|
||||
AccessPathNil apnil, Configuration config
|
||||
PartialAccessPathNil apnil, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, CallContext innercc, AccessPathNil midapnil |
|
||||
exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil |
|
||||
partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and
|
||||
paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and
|
||||
not parameterValueFlowsThrough(p, kind, innercc)
|
||||
@@ -2372,7 +2428,8 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathThroughCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPathNil apnil, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil,
|
||||
Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and
|
||||
@@ -2382,8 +2439,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate valuePartialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, AccessPath ap,
|
||||
Configuration config
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, CallContext innercc |
|
||||
partialPathIntoCallable(mid, p, cc, innercc, call, ap, config) and
|
||||
@@ -2392,7 +2449,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate valuePartialPathThroughCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
valuePartialPathThroughCallable0(call, mid, kind, cc, ap, config) and
|
||||
|
||||
@@ -2048,11 +2048,64 @@ private module FlowExploration {
|
||||
result = distSrcExt(TCallable(c, config)) - 1
|
||||
}
|
||||
|
||||
private newtype TPartialAccessPath =
|
||||
TPartialNil(DataFlowType t) or
|
||||
TPartialCons(Content f, int len) { len in [1 .. 5] }
|
||||
|
||||
/**
|
||||
* Conceptually a list of `Content`s followed by a `Type`, but only the first
|
||||
* element of the list and its length are tracked. If data flows from a source to
|
||||
* a given node with a given `AccessPath`, this indicates the sequence of
|
||||
* dereference operations needed to get from the value in the node to the
|
||||
* tracked object. The final type indicates the type of the tracked object.
|
||||
*/
|
||||
private class PartialAccessPath extends TPartialAccessPath {
|
||||
abstract string toString();
|
||||
|
||||
Content getHead() { this = TPartialCons(result, _) }
|
||||
|
||||
int len() {
|
||||
this = TPartialNil(_) and result = 0
|
||||
or
|
||||
this = TPartialCons(_, result)
|
||||
}
|
||||
|
||||
DataFlowType getType() {
|
||||
this = TPartialNil(result)
|
||||
or
|
||||
exists(Content head | this = TPartialCons(head, _) | result = head.getContainerType())
|
||||
}
|
||||
|
||||
abstract AccessPathFront getFront();
|
||||
}
|
||||
|
||||
private class PartialAccessPathNil extends PartialAccessPath, TPartialNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TPartialNil(t) | result = ppReprType(t))
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
exists(DataFlowType t | this = TPartialNil(t) | result = TFrontNil(t))
|
||||
}
|
||||
}
|
||||
|
||||
private class PartialAccessPathCons extends PartialAccessPath, TPartialCons {
|
||||
override string toString() {
|
||||
exists(Content f, int len | this = TPartialCons(f, len) |
|
||||
result = f.toString() + ", ... (" + len.toString() + ")"
|
||||
)
|
||||
}
|
||||
|
||||
override AccessPathFront getFront() {
|
||||
exists(Content f | this = TPartialCons(f, _) | result = TFrontHead(f))
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TPartialPathNode =
|
||||
TPartialPathNodeMk(Node node, CallContext cc, AccessPath ap, Configuration config) {
|
||||
TPartialPathNodeMk(Node node, CallContext cc, PartialAccessPath ap, Configuration config) {
|
||||
config.isSource(node) and
|
||||
cc instanceof CallContextAny and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
not fullBarrier(node, config) and
|
||||
exists(config.explorationLimit())
|
||||
or
|
||||
@@ -2062,7 +2115,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathNodeMk0(
|
||||
Node node, CallContext cc, AccessPath ap, Configuration config
|
||||
Node node, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PartialPathNode mid |
|
||||
partialPathStep(mid, node, cc, ap, config) and
|
||||
@@ -2138,7 +2191,7 @@ private module FlowExploration {
|
||||
|
||||
CallContext cc;
|
||||
|
||||
AccessPath ap;
|
||||
PartialAccessPath ap;
|
||||
|
||||
Configuration config;
|
||||
|
||||
@@ -2148,7 +2201,7 @@ private module FlowExploration {
|
||||
|
||||
CallContext getCallContext() { result = cc }
|
||||
|
||||
AccessPath getAp() { result = ap }
|
||||
PartialAccessPath getAp() { result = ap }
|
||||
|
||||
override Configuration getConfiguration() { result = config }
|
||||
|
||||
@@ -2161,7 +2214,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathStep(
|
||||
PartialPathNodePriv mid, Node node, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, Node node, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
localFlowStep(mid.getNode(), node, config) and
|
||||
cc = mid.getCallContext() and
|
||||
@@ -2170,8 +2223,8 @@ private module FlowExploration {
|
||||
or
|
||||
additionalLocalFlowStep(mid.getNode(), node, config) and
|
||||
cc = mid.getCallContext() and
|
||||
mid.getAp() instanceof AccessPathNil and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
mid.getAp() instanceof PartialAccessPathNil and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
jumpStep(mid.getNode(), node, config) and
|
||||
@@ -2181,15 +2234,15 @@ private module FlowExploration {
|
||||
or
|
||||
additionalJumpStep(mid.getNode(), node, config) and
|
||||
cc instanceof CallContextAny and
|
||||
mid.getAp() instanceof AccessPathNil and
|
||||
ap = TNil(getErasedRepr(node.getType())) and
|
||||
mid.getAp() instanceof PartialAccessPathNil and
|
||||
ap = TPartialNil(getErasedRepr(node.getType())) and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
partialPathStoreStep(mid, _, _, node, ap) and
|
||||
cc = mid.getCallContext() and
|
||||
config = mid.getConfiguration()
|
||||
or
|
||||
exists(AccessPath ap0, Content f |
|
||||
exists(PartialAccessPath ap0, Content f |
|
||||
partialPathReadStep(mid, ap0, f, node, cc, config) and
|
||||
apConsFwd(ap, f, ap0, config)
|
||||
)
|
||||
@@ -2210,7 +2263,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[inline]
|
||||
private predicate partialPathStoreStep(
|
||||
PartialPathNodePriv mid, AccessPath ap1, Content f, Node node, AccessPath ap2
|
||||
PartialPathNodePriv mid, PartialAccessPath ap1, Content f, Node node, PartialAccessPath ap2
|
||||
) {
|
||||
ap1 = mid.getAp() and
|
||||
store(mid.getNode(), f, node) and
|
||||
@@ -2220,7 +2273,9 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate apConsFwd(AccessPath ap1, Content f, AccessPath ap2, Configuration config) {
|
||||
private predicate apConsFwd(
|
||||
PartialAccessPath ap1, Content f, PartialAccessPath ap2, Configuration config
|
||||
) {
|
||||
exists(PartialPathNodePriv mid |
|
||||
partialPathStoreStep(mid, ap1, f, _, ap2) and
|
||||
config = mid.getConfiguration()
|
||||
@@ -2229,7 +2284,7 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathReadStep(
|
||||
PartialPathNodePriv mid, AccessPath ap, Content f, Node node, CallContext cc,
|
||||
PartialPathNodePriv mid, PartialAccessPath ap, Content f, Node node, CallContext cc,
|
||||
Configuration config
|
||||
) {
|
||||
ap = mid.getAp() and
|
||||
@@ -2240,7 +2295,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfCallable0(
|
||||
PartialPathNodePriv mid, ReturnPosition pos, CallContext innercc, AccessPath ap,
|
||||
PartialPathNodePriv mid, ReturnPosition pos, CallContext innercc, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
pos = getReturnPosition(mid.getNode()) and
|
||||
@@ -2252,8 +2307,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate partialPathOutOfCallable1(
|
||||
PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, AccessPath ap,
|
||||
Configuration config
|
||||
PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc |
|
||||
partialPathOutOfCallable0(mid, pos, innercc, ap, config) and
|
||||
@@ -2266,7 +2321,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ReturnKind kind, DataFlowCall call |
|
||||
partialPathOutOfCallable1(mid, call, kind, cc, ap, config)
|
||||
@@ -2276,7 +2331,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathOutOfArgument(
|
||||
PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, AccessPath ap,
|
||||
PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(
|
||||
@@ -2302,7 +2357,7 @@ private module FlowExploration {
|
||||
pragma[noinline]
|
||||
private predicate partialPathIntoArg(
|
||||
PartialPathNodePriv mid, int i, CallContext cc, DataFlowCall call, boolean emptyAp,
|
||||
AccessPath ap, Configuration config
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ArgumentNode arg |
|
||||
arg = mid.getNode() and
|
||||
@@ -2311,16 +2366,16 @@ private module FlowExploration {
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
|
|
||||
ap instanceof AccessPathNil and emptyAp = true
|
||||
ap instanceof PartialAccessPathNil and emptyAp = true
|
||||
or
|
||||
ap instanceof AccessPathCons and emptyAp = false
|
||||
ap instanceof PartialAccessPathCons and emptyAp = false
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathIntoCallable0(
|
||||
PartialPathNodePriv mid, DataFlowCallable callable, int i, CallContext outercc,
|
||||
DataFlowCall call, boolean emptyAp, AccessPath ap, Configuration config
|
||||
DataFlowCall call, boolean emptyAp, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
partialPathIntoArg(mid, i, outercc, call, emptyAp, ap, config) and
|
||||
callable = resolveCall(call, outercc)
|
||||
@@ -2328,7 +2383,7 @@ private module FlowExploration {
|
||||
|
||||
private predicate partialPathIntoCallable(
|
||||
PartialPathNodePriv mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
|
||||
DataFlowCall call, AccessPath ap, Configuration config
|
||||
DataFlowCall call, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable, boolean emptyAp |
|
||||
partialPathIntoCallable0(mid, callable, i, outercc, call, emptyAp, ap, config) and
|
||||
@@ -2342,7 +2397,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate paramFlowsThroughInPartialPath(
|
||||
ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config
|
||||
ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil,
|
||||
Configuration config
|
||||
) {
|
||||
exists(PartialPathNodePriv mid, ReturnNode ret |
|
||||
mid.getNode() = ret and
|
||||
@@ -2362,9 +2418,9 @@ private module FlowExploration {
|
||||
pragma[noinline]
|
||||
private predicate partialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc,
|
||||
AccessPathNil apnil, Configuration config
|
||||
PartialAccessPathNil apnil, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, CallContext innercc, AccessPathNil midapnil |
|
||||
exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil |
|
||||
partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and
|
||||
paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and
|
||||
not parameterValueFlowsThrough(p, kind, innercc)
|
||||
@@ -2372,7 +2428,8 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate partialPathThroughCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPathNil apnil, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil,
|
||||
Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and
|
||||
@@ -2382,8 +2439,8 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate valuePartialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, AccessPath ap,
|
||||
Configuration config
|
||||
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ParameterNode p, CallContext innercc |
|
||||
partialPathIntoCallable(mid, p, cc, innercc, call, ap, config) and
|
||||
@@ -2392,7 +2449,7 @@ private module FlowExploration {
|
||||
}
|
||||
|
||||
private predicate valuePartialPathThroughCallable(
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPath ap, Configuration config
|
||||
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
valuePartialPathThroughCallable0(call, mid, kind, cc, ap, config) and
|
||||
|
||||
Reference in New Issue
Block a user