Merge pull request #1797 from jbj/dataflow-TTwo

C++/C#/Java: data flow AccessPath up to length 2
This commit is contained in:
Tom Hvitved
2019-09-09 10:28:48 +02:00
committed by GitHub
30 changed files with 3201 additions and 1304 deletions

View File

@@ -1217,7 +1217,8 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
private newtype TAccessPath =
TNil(DataFlowType t) or
TCons(Content f, int len) { len in [1 .. 5] }
TConsNil(Content f, DataFlowType t) { consCand(f, TFrontNil(t), _) } or
TConsCons(Content f1, Content f2, int len) { consCand(f1, TFrontHead(f2), _) and len in [2 .. 5] }
/**
* Conceptually a list of `Content`s followed by a `Type`, but only the first
@@ -1226,52 +1227,93 @@ private newtype TAccessPath =
* 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 AccessPath extends TAccessPath {
abstract private class AccessPath extends TAccessPath {
abstract string toString();
Content getHead() { this = TCons(result, _) }
Content getHead() {
this = TConsNil(result, _)
or
this = TConsCons(result, _, _)
}
int len() {
this = TNil(_) and result = 0
or
this = TCons(_, result)
this = TConsNil(_, _) and result = 1
or
this = TConsCons(_, _, result)
}
DataFlowType getType() {
this = TNil(result)
or
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
result = this.getHead().getContainerType()
}
abstract AccessPathFront getFront();
/**
* Holds if this access path has `head` at the front and may be followed by `tail`.
*/
abstract predicate pop(Content head, AccessPath tail);
}
private class AccessPathNil extends AccessPath, TNil {
override string toString() { exists(DataFlowType t | this = TNil(t) | result = ppReprType(t)) }
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
}
override AccessPathFront getFront() {
exists(DataFlowType t | this = TNil(t) | result = TFrontNil(t))
}
override predicate pop(Content head, AccessPath tail) { none() }
}
private class AccessPathCons extends AccessPath, TCons {
abstract private class AccessPathCons extends AccessPath { }
private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, int len | this = TCons(f, len) |
result = f.toString() + ", ... (" + len.toString() + ")"
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
)
}
override AccessPathFront getFront() {
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
exists(Content f | this = TConsNil(f, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(DataFlowType t | this = TConsNil(head, t) and tail = TNil(t))
}
}
private class AccessPathConsCons extends AccessPathCons, TConsCons {
override string toString() {
exists(Content f1, Content f2, int len | this = TConsCons(f1, f2, len) |
if len = 2
then result = f1.toString() + ", " + f2.toString()
else result = f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")"
)
}
override AccessPathFront getFront() {
exists(Content f | this = TConsCons(f, _, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(int len, Content next | this = TConsCons(head, next, len) |
tail = TConsCons(next, _, len - 1)
or
len = 2 and
tail = TConsNil(next, _)
)
}
}
/** Holds if `ap0` corresponds to the cons of `f` and `ap`. */
private predicate pop(AccessPath ap0, Content f, AccessPath ap) {
ap0.getFront().headUsesContent(f) and
consCand(f, ap.getFront(), _) and
ap0.len() = 1 + ap.len()
}
private predicate pop(AccessPath ap0, Content f, AccessPath ap) { ap0.pop(f, ap) }
/** Holds if `ap0` corresponds to the cons of `f` and `ap` and `apf` is the front of `ap`. */
pragma[noinline]
@@ -2002,11 +2044,66 @@ 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 = concat(" : " + 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) |
if len = 1
then result = f.toString()
else 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
@@ -2016,7 +2113,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
@@ -2090,7 +2187,7 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
AccessPath ap;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2099,7 +2196,7 @@ private module FlowExploration {
CallContext getCallContext() { result = cc }
AccessPath getAp() { result = ap }
PartialAccessPath getAp() { result = ap }
override Configuration getConfiguration() { result = config }
@@ -2112,7 +2209,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
@@ -2121,8 +2218,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
@@ -2132,15 +2229,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)
)
@@ -2161,7 +2258,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
@@ -2171,7 +2268,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()
@@ -2180,7 +2279,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
@@ -2191,7 +2290,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
@@ -2203,8 +2302,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
@@ -2217,7 +2316,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)
@@ -2227,7 +2326,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(
@@ -2253,7 +2352,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
@@ -2262,16 +2361,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)
@@ -2279,7 +2378,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
@@ -2293,7 +2392,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
@@ -2313,9 +2413,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)
@@ -2323,7 +2423,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
@@ -2333,8 +2434,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
@@ -2343,7 +2444,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

View File

@@ -1217,7 +1217,8 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
private newtype TAccessPath =
TNil(DataFlowType t) or
TCons(Content f, int len) { len in [1 .. 5] }
TConsNil(Content f, DataFlowType t) { consCand(f, TFrontNil(t), _) } or
TConsCons(Content f1, Content f2, int len) { consCand(f1, TFrontHead(f2), _) and len in [2 .. 5] }
/**
* Conceptually a list of `Content`s followed by a `Type`, but only the first
@@ -1226,52 +1227,93 @@ private newtype TAccessPath =
* 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 AccessPath extends TAccessPath {
abstract private class AccessPath extends TAccessPath {
abstract string toString();
Content getHead() { this = TCons(result, _) }
Content getHead() {
this = TConsNil(result, _)
or
this = TConsCons(result, _, _)
}
int len() {
this = TNil(_) and result = 0
or
this = TCons(_, result)
this = TConsNil(_, _) and result = 1
or
this = TConsCons(_, _, result)
}
DataFlowType getType() {
this = TNil(result)
or
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
result = this.getHead().getContainerType()
}
abstract AccessPathFront getFront();
/**
* Holds if this access path has `head` at the front and may be followed by `tail`.
*/
abstract predicate pop(Content head, AccessPath tail);
}
private class AccessPathNil extends AccessPath, TNil {
override string toString() { exists(DataFlowType t | this = TNil(t) | result = ppReprType(t)) }
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
}
override AccessPathFront getFront() {
exists(DataFlowType t | this = TNil(t) | result = TFrontNil(t))
}
override predicate pop(Content head, AccessPath tail) { none() }
}
private class AccessPathCons extends AccessPath, TCons {
abstract private class AccessPathCons extends AccessPath { }
private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, int len | this = TCons(f, len) |
result = f.toString() + ", ... (" + len.toString() + ")"
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
)
}
override AccessPathFront getFront() {
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
exists(Content f | this = TConsNil(f, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(DataFlowType t | this = TConsNil(head, t) and tail = TNil(t))
}
}
private class AccessPathConsCons extends AccessPathCons, TConsCons {
override string toString() {
exists(Content f1, Content f2, int len | this = TConsCons(f1, f2, len) |
if len = 2
then result = f1.toString() + ", " + f2.toString()
else result = f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")"
)
}
override AccessPathFront getFront() {
exists(Content f | this = TConsCons(f, _, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(int len, Content next | this = TConsCons(head, next, len) |
tail = TConsCons(next, _, len - 1)
or
len = 2 and
tail = TConsNil(next, _)
)
}
}
/** Holds if `ap0` corresponds to the cons of `f` and `ap`. */
private predicate pop(AccessPath ap0, Content f, AccessPath ap) {
ap0.getFront().headUsesContent(f) and
consCand(f, ap.getFront(), _) and
ap0.len() = 1 + ap.len()
}
private predicate pop(AccessPath ap0, Content f, AccessPath ap) { ap0.pop(f, ap) }
/** Holds if `ap0` corresponds to the cons of `f` and `ap` and `apf` is the front of `ap`. */
pragma[noinline]
@@ -2002,11 +2044,66 @@ 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 = concat(" : " + 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) |
if len = 1
then result = f.toString()
else 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
@@ -2016,7 +2113,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
@@ -2090,7 +2187,7 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
AccessPath ap;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2099,7 +2196,7 @@ private module FlowExploration {
CallContext getCallContext() { result = cc }
AccessPath getAp() { result = ap }
PartialAccessPath getAp() { result = ap }
override Configuration getConfiguration() { result = config }
@@ -2112,7 +2209,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
@@ -2121,8 +2218,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
@@ -2132,15 +2229,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)
)
@@ -2161,7 +2258,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
@@ -2171,7 +2268,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()
@@ -2180,7 +2279,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
@@ -2191,7 +2290,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
@@ -2203,8 +2302,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
@@ -2217,7 +2316,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)
@@ -2227,7 +2326,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(
@@ -2253,7 +2352,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
@@ -2262,16 +2361,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)
@@ -2279,7 +2378,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
@@ -2293,7 +2392,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
@@ -2313,9 +2413,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)
@@ -2323,7 +2423,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
@@ -2333,8 +2434,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
@@ -2343,7 +2444,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

View File

@@ -1217,7 +1217,8 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
private newtype TAccessPath =
TNil(DataFlowType t) or
TCons(Content f, int len) { len in [1 .. 5] }
TConsNil(Content f, DataFlowType t) { consCand(f, TFrontNil(t), _) } or
TConsCons(Content f1, Content f2, int len) { consCand(f1, TFrontHead(f2), _) and len in [2 .. 5] }
/**
* Conceptually a list of `Content`s followed by a `Type`, but only the first
@@ -1226,52 +1227,93 @@ private newtype TAccessPath =
* 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 AccessPath extends TAccessPath {
abstract private class AccessPath extends TAccessPath {
abstract string toString();
Content getHead() { this = TCons(result, _) }
Content getHead() {
this = TConsNil(result, _)
or
this = TConsCons(result, _, _)
}
int len() {
this = TNil(_) and result = 0
or
this = TCons(_, result)
this = TConsNil(_, _) and result = 1
or
this = TConsCons(_, _, result)
}
DataFlowType getType() {
this = TNil(result)
or
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
result = this.getHead().getContainerType()
}
abstract AccessPathFront getFront();
/**
* Holds if this access path has `head` at the front and may be followed by `tail`.
*/
abstract predicate pop(Content head, AccessPath tail);
}
private class AccessPathNil extends AccessPath, TNil {
override string toString() { exists(DataFlowType t | this = TNil(t) | result = ppReprType(t)) }
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
}
override AccessPathFront getFront() {
exists(DataFlowType t | this = TNil(t) | result = TFrontNil(t))
}
override predicate pop(Content head, AccessPath tail) { none() }
}
private class AccessPathCons extends AccessPath, TCons {
abstract private class AccessPathCons extends AccessPath { }
private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, int len | this = TCons(f, len) |
result = f.toString() + ", ... (" + len.toString() + ")"
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
)
}
override AccessPathFront getFront() {
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
exists(Content f | this = TConsNil(f, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(DataFlowType t | this = TConsNil(head, t) and tail = TNil(t))
}
}
private class AccessPathConsCons extends AccessPathCons, TConsCons {
override string toString() {
exists(Content f1, Content f2, int len | this = TConsCons(f1, f2, len) |
if len = 2
then result = f1.toString() + ", " + f2.toString()
else result = f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")"
)
}
override AccessPathFront getFront() {
exists(Content f | this = TConsCons(f, _, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(int len, Content next | this = TConsCons(head, next, len) |
tail = TConsCons(next, _, len - 1)
or
len = 2 and
tail = TConsNil(next, _)
)
}
}
/** Holds if `ap0` corresponds to the cons of `f` and `ap`. */
private predicate pop(AccessPath ap0, Content f, AccessPath ap) {
ap0.getFront().headUsesContent(f) and
consCand(f, ap.getFront(), _) and
ap0.len() = 1 + ap.len()
}
private predicate pop(AccessPath ap0, Content f, AccessPath ap) { ap0.pop(f, ap) }
/** Holds if `ap0` corresponds to the cons of `f` and `ap` and `apf` is the front of `ap`. */
pragma[noinline]
@@ -2002,11 +2044,66 @@ 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 = concat(" : " + 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) |
if len = 1
then result = f.toString()
else 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
@@ -2016,7 +2113,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
@@ -2090,7 +2187,7 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
AccessPath ap;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2099,7 +2196,7 @@ private module FlowExploration {
CallContext getCallContext() { result = cc }
AccessPath getAp() { result = ap }
PartialAccessPath getAp() { result = ap }
override Configuration getConfiguration() { result = config }
@@ -2112,7 +2209,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
@@ -2121,8 +2218,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
@@ -2132,15 +2229,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)
)
@@ -2161,7 +2258,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
@@ -2171,7 +2268,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()
@@ -2180,7 +2279,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
@@ -2191,7 +2290,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
@@ -2203,8 +2302,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
@@ -2217,7 +2316,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)
@@ -2227,7 +2326,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(
@@ -2253,7 +2352,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
@@ -2262,16 +2361,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)
@@ -2279,7 +2378,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
@@ -2293,7 +2392,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
@@ -2313,9 +2413,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)
@@ -2323,7 +2423,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
@@ -2333,8 +2434,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
@@ -2343,7 +2444,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

View File

@@ -1217,7 +1217,8 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
private newtype TAccessPath =
TNil(DataFlowType t) or
TCons(Content f, int len) { len in [1 .. 5] }
TConsNil(Content f, DataFlowType t) { consCand(f, TFrontNil(t), _) } or
TConsCons(Content f1, Content f2, int len) { consCand(f1, TFrontHead(f2), _) and len in [2 .. 5] }
/**
* Conceptually a list of `Content`s followed by a `Type`, but only the first
@@ -1226,52 +1227,93 @@ private newtype TAccessPath =
* 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 AccessPath extends TAccessPath {
abstract private class AccessPath extends TAccessPath {
abstract string toString();
Content getHead() { this = TCons(result, _) }
Content getHead() {
this = TConsNil(result, _)
or
this = TConsCons(result, _, _)
}
int len() {
this = TNil(_) and result = 0
or
this = TCons(_, result)
this = TConsNil(_, _) and result = 1
or
this = TConsCons(_, _, result)
}
DataFlowType getType() {
this = TNil(result)
or
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
result = this.getHead().getContainerType()
}
abstract AccessPathFront getFront();
/**
* Holds if this access path has `head` at the front and may be followed by `tail`.
*/
abstract predicate pop(Content head, AccessPath tail);
}
private class AccessPathNil extends AccessPath, TNil {
override string toString() { exists(DataFlowType t | this = TNil(t) | result = ppReprType(t)) }
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
}
override AccessPathFront getFront() {
exists(DataFlowType t | this = TNil(t) | result = TFrontNil(t))
}
override predicate pop(Content head, AccessPath tail) { none() }
}
private class AccessPathCons extends AccessPath, TCons {
abstract private class AccessPathCons extends AccessPath { }
private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, int len | this = TCons(f, len) |
result = f.toString() + ", ... (" + len.toString() + ")"
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
)
}
override AccessPathFront getFront() {
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
exists(Content f | this = TConsNil(f, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(DataFlowType t | this = TConsNil(head, t) and tail = TNil(t))
}
}
private class AccessPathConsCons extends AccessPathCons, TConsCons {
override string toString() {
exists(Content f1, Content f2, int len | this = TConsCons(f1, f2, len) |
if len = 2
then result = f1.toString() + ", " + f2.toString()
else result = f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")"
)
}
override AccessPathFront getFront() {
exists(Content f | this = TConsCons(f, _, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(int len, Content next | this = TConsCons(head, next, len) |
tail = TConsCons(next, _, len - 1)
or
len = 2 and
tail = TConsNil(next, _)
)
}
}
/** Holds if `ap0` corresponds to the cons of `f` and `ap`. */
private predicate pop(AccessPath ap0, Content f, AccessPath ap) {
ap0.getFront().headUsesContent(f) and
consCand(f, ap.getFront(), _) and
ap0.len() = 1 + ap.len()
}
private predicate pop(AccessPath ap0, Content f, AccessPath ap) { ap0.pop(f, ap) }
/** Holds if `ap0` corresponds to the cons of `f` and `ap` and `apf` is the front of `ap`. */
pragma[noinline]
@@ -2002,11 +2044,66 @@ 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 = concat(" : " + 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) |
if len = 1
then result = f.toString()
else 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
@@ -2016,7 +2113,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
@@ -2090,7 +2187,7 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
AccessPath ap;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2099,7 +2196,7 @@ private module FlowExploration {
CallContext getCallContext() { result = cc }
AccessPath getAp() { result = ap }
PartialAccessPath getAp() { result = ap }
override Configuration getConfiguration() { result = config }
@@ -2112,7 +2209,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
@@ -2121,8 +2218,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
@@ -2132,15 +2229,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)
)
@@ -2161,7 +2258,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
@@ -2171,7 +2268,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()
@@ -2180,7 +2279,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
@@ -2191,7 +2290,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
@@ -2203,8 +2302,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
@@ -2217,7 +2316,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)
@@ -2227,7 +2326,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(
@@ -2253,7 +2352,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
@@ -2262,16 +2361,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)
@@ -2279,7 +2378,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
@@ -2293,7 +2392,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
@@ -2313,9 +2413,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)
@@ -2323,7 +2423,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
@@ -2333,8 +2434,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
@@ -2343,7 +2444,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

View File

@@ -1217,7 +1217,8 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
private newtype TAccessPath =
TNil(DataFlowType t) or
TCons(Content f, int len) { len in [1 .. 5] }
TConsNil(Content f, DataFlowType t) { consCand(f, TFrontNil(t), _) } or
TConsCons(Content f1, Content f2, int len) { consCand(f1, TFrontHead(f2), _) and len in [2 .. 5] }
/**
* Conceptually a list of `Content`s followed by a `Type`, but only the first
@@ -1226,52 +1227,93 @@ private newtype TAccessPath =
* 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 AccessPath extends TAccessPath {
abstract private class AccessPath extends TAccessPath {
abstract string toString();
Content getHead() { this = TCons(result, _) }
Content getHead() {
this = TConsNil(result, _)
or
this = TConsCons(result, _, _)
}
int len() {
this = TNil(_) and result = 0
or
this = TCons(_, result)
this = TConsNil(_, _) and result = 1
or
this = TConsCons(_, _, result)
}
DataFlowType getType() {
this = TNil(result)
or
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
result = this.getHead().getContainerType()
}
abstract AccessPathFront getFront();
/**
* Holds if this access path has `head` at the front and may be followed by `tail`.
*/
abstract predicate pop(Content head, AccessPath tail);
}
private class AccessPathNil extends AccessPath, TNil {
override string toString() { exists(DataFlowType t | this = TNil(t) | result = ppReprType(t)) }
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
}
override AccessPathFront getFront() {
exists(DataFlowType t | this = TNil(t) | result = TFrontNil(t))
}
override predicate pop(Content head, AccessPath tail) { none() }
}
private class AccessPathCons extends AccessPath, TCons {
abstract private class AccessPathCons extends AccessPath { }
private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, int len | this = TCons(f, len) |
result = f.toString() + ", ... (" + len.toString() + ")"
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
)
}
override AccessPathFront getFront() {
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
exists(Content f | this = TConsNil(f, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(DataFlowType t | this = TConsNil(head, t) and tail = TNil(t))
}
}
private class AccessPathConsCons extends AccessPathCons, TConsCons {
override string toString() {
exists(Content f1, Content f2, int len | this = TConsCons(f1, f2, len) |
if len = 2
then result = f1.toString() + ", " + f2.toString()
else result = f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")"
)
}
override AccessPathFront getFront() {
exists(Content f | this = TConsCons(f, _, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(int len, Content next | this = TConsCons(head, next, len) |
tail = TConsCons(next, _, len - 1)
or
len = 2 and
tail = TConsNil(next, _)
)
}
}
/** Holds if `ap0` corresponds to the cons of `f` and `ap`. */
private predicate pop(AccessPath ap0, Content f, AccessPath ap) {
ap0.getFront().headUsesContent(f) and
consCand(f, ap.getFront(), _) and
ap0.len() = 1 + ap.len()
}
private predicate pop(AccessPath ap0, Content f, AccessPath ap) { ap0.pop(f, ap) }
/** Holds if `ap0` corresponds to the cons of `f` and `ap` and `apf` is the front of `ap`. */
pragma[noinline]
@@ -2002,11 +2044,66 @@ 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 = concat(" : " + 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) |
if len = 1
then result = f.toString()
else 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
@@ -2016,7 +2113,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
@@ -2090,7 +2187,7 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
AccessPath ap;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2099,7 +2196,7 @@ private module FlowExploration {
CallContext getCallContext() { result = cc }
AccessPath getAp() { result = ap }
PartialAccessPath getAp() { result = ap }
override Configuration getConfiguration() { result = config }
@@ -2112,7 +2209,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
@@ -2121,8 +2218,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
@@ -2132,15 +2229,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)
)
@@ -2161,7 +2258,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
@@ -2171,7 +2268,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()
@@ -2180,7 +2279,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
@@ -2191,7 +2290,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
@@ -2203,8 +2302,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
@@ -2217,7 +2316,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)
@@ -2227,7 +2326,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(
@@ -2253,7 +2352,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
@@ -2262,16 +2361,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)
@@ -2279,7 +2378,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
@@ -2293,7 +2392,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
@@ -2313,9 +2413,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)
@@ -2323,7 +2423,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
@@ -2333,8 +2434,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
@@ -2343,7 +2444,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

View File

@@ -219,7 +219,7 @@ Type getErasedRepr(Type t) {
}
/** Gets a string representation of a type returned by `getErasedRepr`. */
string ppReprType(Type t) { result = t.toString() }
string ppReprType(Type t) { none() } // stub implementation
/**
* Holds if `t1` and `t2` are compatible, that is, whether data can flow from

View File

@@ -1217,7 +1217,8 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
private newtype TAccessPath =
TNil(DataFlowType t) or
TCons(Content f, int len) { len in [1 .. 5] }
TConsNil(Content f, DataFlowType t) { consCand(f, TFrontNil(t), _) } or
TConsCons(Content f1, Content f2, int len) { consCand(f1, TFrontHead(f2), _) and len in [2 .. 5] }
/**
* Conceptually a list of `Content`s followed by a `Type`, but only the first
@@ -1226,52 +1227,93 @@ private newtype TAccessPath =
* 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 AccessPath extends TAccessPath {
abstract private class AccessPath extends TAccessPath {
abstract string toString();
Content getHead() { this = TCons(result, _) }
Content getHead() {
this = TConsNil(result, _)
or
this = TConsCons(result, _, _)
}
int len() {
this = TNil(_) and result = 0
or
this = TCons(_, result)
this = TConsNil(_, _) and result = 1
or
this = TConsCons(_, _, result)
}
DataFlowType getType() {
this = TNil(result)
or
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
result = this.getHead().getContainerType()
}
abstract AccessPathFront getFront();
/**
* Holds if this access path has `head` at the front and may be followed by `tail`.
*/
abstract predicate pop(Content head, AccessPath tail);
}
private class AccessPathNil extends AccessPath, TNil {
override string toString() { exists(DataFlowType t | this = TNil(t) | result = ppReprType(t)) }
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
}
override AccessPathFront getFront() {
exists(DataFlowType t | this = TNil(t) | result = TFrontNil(t))
}
override predicate pop(Content head, AccessPath tail) { none() }
}
private class AccessPathCons extends AccessPath, TCons {
abstract private class AccessPathCons extends AccessPath { }
private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, int len | this = TCons(f, len) |
result = f.toString() + ", ... (" + len.toString() + ")"
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
)
}
override AccessPathFront getFront() {
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
exists(Content f | this = TConsNil(f, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(DataFlowType t | this = TConsNil(head, t) and tail = TNil(t))
}
}
private class AccessPathConsCons extends AccessPathCons, TConsCons {
override string toString() {
exists(Content f1, Content f2, int len | this = TConsCons(f1, f2, len) |
if len = 2
then result = f1.toString() + ", " + f2.toString()
else result = f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")"
)
}
override AccessPathFront getFront() {
exists(Content f | this = TConsCons(f, _, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(int len, Content next | this = TConsCons(head, next, len) |
tail = TConsCons(next, _, len - 1)
or
len = 2 and
tail = TConsNil(next, _)
)
}
}
/** Holds if `ap0` corresponds to the cons of `f` and `ap`. */
private predicate pop(AccessPath ap0, Content f, AccessPath ap) {
ap0.getFront().headUsesContent(f) and
consCand(f, ap.getFront(), _) and
ap0.len() = 1 + ap.len()
}
private predicate pop(AccessPath ap0, Content f, AccessPath ap) { ap0.pop(f, ap) }
/** Holds if `ap0` corresponds to the cons of `f` and `ap` and `apf` is the front of `ap`. */
pragma[noinline]
@@ -2002,11 +2044,66 @@ 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 = concat(" : " + 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) |
if len = 1
then result = f.toString()
else 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
@@ -2016,7 +2113,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
@@ -2090,7 +2187,7 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
AccessPath ap;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2099,7 +2196,7 @@ private module FlowExploration {
CallContext getCallContext() { result = cc }
AccessPath getAp() { result = ap }
PartialAccessPath getAp() { result = ap }
override Configuration getConfiguration() { result = config }
@@ -2112,7 +2209,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
@@ -2121,8 +2218,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
@@ -2132,15 +2229,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)
)
@@ -2161,7 +2258,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
@@ -2171,7 +2268,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()
@@ -2180,7 +2279,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
@@ -2191,7 +2290,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
@@ -2203,8 +2302,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
@@ -2217,7 +2316,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)
@@ -2227,7 +2326,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(
@@ -2253,7 +2352,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
@@ -2262,16 +2361,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)
@@ -2279,7 +2378,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
@@ -2293,7 +2392,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
@@ -2313,9 +2413,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)
@@ -2323,7 +2423,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
@@ -2333,8 +2434,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
@@ -2343,7 +2444,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

View File

@@ -1217,7 +1217,8 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
private newtype TAccessPath =
TNil(DataFlowType t) or
TCons(Content f, int len) { len in [1 .. 5] }
TConsNil(Content f, DataFlowType t) { consCand(f, TFrontNil(t), _) } or
TConsCons(Content f1, Content f2, int len) { consCand(f1, TFrontHead(f2), _) and len in [2 .. 5] }
/**
* Conceptually a list of `Content`s followed by a `Type`, but only the first
@@ -1226,52 +1227,93 @@ private newtype TAccessPath =
* 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 AccessPath extends TAccessPath {
abstract private class AccessPath extends TAccessPath {
abstract string toString();
Content getHead() { this = TCons(result, _) }
Content getHead() {
this = TConsNil(result, _)
or
this = TConsCons(result, _, _)
}
int len() {
this = TNil(_) and result = 0
or
this = TCons(_, result)
this = TConsNil(_, _) and result = 1
or
this = TConsCons(_, _, result)
}
DataFlowType getType() {
this = TNil(result)
or
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
result = this.getHead().getContainerType()
}
abstract AccessPathFront getFront();
/**
* Holds if this access path has `head` at the front and may be followed by `tail`.
*/
abstract predicate pop(Content head, AccessPath tail);
}
private class AccessPathNil extends AccessPath, TNil {
override string toString() { exists(DataFlowType t | this = TNil(t) | result = ppReprType(t)) }
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
}
override AccessPathFront getFront() {
exists(DataFlowType t | this = TNil(t) | result = TFrontNil(t))
}
override predicate pop(Content head, AccessPath tail) { none() }
}
private class AccessPathCons extends AccessPath, TCons {
abstract private class AccessPathCons extends AccessPath { }
private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, int len | this = TCons(f, len) |
result = f.toString() + ", ... (" + len.toString() + ")"
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
)
}
override AccessPathFront getFront() {
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
exists(Content f | this = TConsNil(f, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(DataFlowType t | this = TConsNil(head, t) and tail = TNil(t))
}
}
private class AccessPathConsCons extends AccessPathCons, TConsCons {
override string toString() {
exists(Content f1, Content f2, int len | this = TConsCons(f1, f2, len) |
if len = 2
then result = f1.toString() + ", " + f2.toString()
else result = f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")"
)
}
override AccessPathFront getFront() {
exists(Content f | this = TConsCons(f, _, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(int len, Content next | this = TConsCons(head, next, len) |
tail = TConsCons(next, _, len - 1)
or
len = 2 and
tail = TConsNil(next, _)
)
}
}
/** Holds if `ap0` corresponds to the cons of `f` and `ap`. */
private predicate pop(AccessPath ap0, Content f, AccessPath ap) {
ap0.getFront().headUsesContent(f) and
consCand(f, ap.getFront(), _) and
ap0.len() = 1 + ap.len()
}
private predicate pop(AccessPath ap0, Content f, AccessPath ap) { ap0.pop(f, ap) }
/** Holds if `ap0` corresponds to the cons of `f` and `ap` and `apf` is the front of `ap`. */
pragma[noinline]
@@ -2002,11 +2044,66 @@ 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 = concat(" : " + 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) |
if len = 1
then result = f.toString()
else 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
@@ -2016,7 +2113,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
@@ -2090,7 +2187,7 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
AccessPath ap;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2099,7 +2196,7 @@ private module FlowExploration {
CallContext getCallContext() { result = cc }
AccessPath getAp() { result = ap }
PartialAccessPath getAp() { result = ap }
override Configuration getConfiguration() { result = config }
@@ -2112,7 +2209,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
@@ -2121,8 +2218,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
@@ -2132,15 +2229,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)
)
@@ -2161,7 +2258,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
@@ -2171,7 +2268,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()
@@ -2180,7 +2279,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
@@ -2191,7 +2290,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
@@ -2203,8 +2302,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
@@ -2217,7 +2316,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)
@@ -2227,7 +2326,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(
@@ -2253,7 +2352,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
@@ -2262,16 +2361,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)
@@ -2279,7 +2378,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
@@ -2293,7 +2392,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
@@ -2313,9 +2413,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)
@@ -2323,7 +2423,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
@@ -2333,8 +2434,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
@@ -2343,7 +2444,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

View File

@@ -1217,7 +1217,8 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
private newtype TAccessPath =
TNil(DataFlowType t) or
TCons(Content f, int len) { len in [1 .. 5] }
TConsNil(Content f, DataFlowType t) { consCand(f, TFrontNil(t), _) } or
TConsCons(Content f1, Content f2, int len) { consCand(f1, TFrontHead(f2), _) and len in [2 .. 5] }
/**
* Conceptually a list of `Content`s followed by a `Type`, but only the first
@@ -1226,52 +1227,93 @@ private newtype TAccessPath =
* 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 AccessPath extends TAccessPath {
abstract private class AccessPath extends TAccessPath {
abstract string toString();
Content getHead() { this = TCons(result, _) }
Content getHead() {
this = TConsNil(result, _)
or
this = TConsCons(result, _, _)
}
int len() {
this = TNil(_) and result = 0
or
this = TCons(_, result)
this = TConsNil(_, _) and result = 1
or
this = TConsCons(_, _, result)
}
DataFlowType getType() {
this = TNil(result)
or
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
result = this.getHead().getContainerType()
}
abstract AccessPathFront getFront();
/**
* Holds if this access path has `head` at the front and may be followed by `tail`.
*/
abstract predicate pop(Content head, AccessPath tail);
}
private class AccessPathNil extends AccessPath, TNil {
override string toString() { exists(DataFlowType t | this = TNil(t) | result = ppReprType(t)) }
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
}
override AccessPathFront getFront() {
exists(DataFlowType t | this = TNil(t) | result = TFrontNil(t))
}
override predicate pop(Content head, AccessPath tail) { none() }
}
private class AccessPathCons extends AccessPath, TCons {
abstract private class AccessPathCons extends AccessPath { }
private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, int len | this = TCons(f, len) |
result = f.toString() + ", ... (" + len.toString() + ")"
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
)
}
override AccessPathFront getFront() {
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
exists(Content f | this = TConsNil(f, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(DataFlowType t | this = TConsNil(head, t) and tail = TNil(t))
}
}
private class AccessPathConsCons extends AccessPathCons, TConsCons {
override string toString() {
exists(Content f1, Content f2, int len | this = TConsCons(f1, f2, len) |
if len = 2
then result = f1.toString() + ", " + f2.toString()
else result = f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")"
)
}
override AccessPathFront getFront() {
exists(Content f | this = TConsCons(f, _, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(int len, Content next | this = TConsCons(head, next, len) |
tail = TConsCons(next, _, len - 1)
or
len = 2 and
tail = TConsNil(next, _)
)
}
}
/** Holds if `ap0` corresponds to the cons of `f` and `ap`. */
private predicate pop(AccessPath ap0, Content f, AccessPath ap) {
ap0.getFront().headUsesContent(f) and
consCand(f, ap.getFront(), _) and
ap0.len() = 1 + ap.len()
}
private predicate pop(AccessPath ap0, Content f, AccessPath ap) { ap0.pop(f, ap) }
/** Holds if `ap0` corresponds to the cons of `f` and `ap` and `apf` is the front of `ap`. */
pragma[noinline]
@@ -2002,11 +2044,66 @@ 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 = concat(" : " + 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) |
if len = 1
then result = f.toString()
else 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
@@ -2016,7 +2113,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
@@ -2090,7 +2187,7 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
AccessPath ap;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2099,7 +2196,7 @@ private module FlowExploration {
CallContext getCallContext() { result = cc }
AccessPath getAp() { result = ap }
PartialAccessPath getAp() { result = ap }
override Configuration getConfiguration() { result = config }
@@ -2112,7 +2209,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
@@ -2121,8 +2218,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
@@ -2132,15 +2229,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)
)
@@ -2161,7 +2258,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
@@ -2171,7 +2268,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()
@@ -2180,7 +2279,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
@@ -2191,7 +2290,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
@@ -2203,8 +2302,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
@@ -2217,7 +2316,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)
@@ -2227,7 +2326,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(
@@ -2253,7 +2352,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
@@ -2262,16 +2361,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)
@@ -2279,7 +2378,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
@@ -2293,7 +2392,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
@@ -2313,9 +2413,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)
@@ -2323,7 +2423,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
@@ -2333,8 +2434,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
@@ -2343,7 +2444,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

View File

@@ -1217,7 +1217,8 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
private newtype TAccessPath =
TNil(DataFlowType t) or
TCons(Content f, int len) { len in [1 .. 5] }
TConsNil(Content f, DataFlowType t) { consCand(f, TFrontNil(t), _) } or
TConsCons(Content f1, Content f2, int len) { consCand(f1, TFrontHead(f2), _) and len in [2 .. 5] }
/**
* Conceptually a list of `Content`s followed by a `Type`, but only the first
@@ -1226,52 +1227,93 @@ private newtype TAccessPath =
* 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 AccessPath extends TAccessPath {
abstract private class AccessPath extends TAccessPath {
abstract string toString();
Content getHead() { this = TCons(result, _) }
Content getHead() {
this = TConsNil(result, _)
or
this = TConsCons(result, _, _)
}
int len() {
this = TNil(_) and result = 0
or
this = TCons(_, result)
this = TConsNil(_, _) and result = 1
or
this = TConsCons(_, _, result)
}
DataFlowType getType() {
this = TNil(result)
or
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
result = this.getHead().getContainerType()
}
abstract AccessPathFront getFront();
/**
* Holds if this access path has `head` at the front and may be followed by `tail`.
*/
abstract predicate pop(Content head, AccessPath tail);
}
private class AccessPathNil extends AccessPath, TNil {
override string toString() { exists(DataFlowType t | this = TNil(t) | result = ppReprType(t)) }
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
}
override AccessPathFront getFront() {
exists(DataFlowType t | this = TNil(t) | result = TFrontNil(t))
}
override predicate pop(Content head, AccessPath tail) { none() }
}
private class AccessPathCons extends AccessPath, TCons {
abstract private class AccessPathCons extends AccessPath { }
private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, int len | this = TCons(f, len) |
result = f.toString() + ", ... (" + len.toString() + ")"
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
)
}
override AccessPathFront getFront() {
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
exists(Content f | this = TConsNil(f, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(DataFlowType t | this = TConsNil(head, t) and tail = TNil(t))
}
}
private class AccessPathConsCons extends AccessPathCons, TConsCons {
override string toString() {
exists(Content f1, Content f2, int len | this = TConsCons(f1, f2, len) |
if len = 2
then result = f1.toString() + ", " + f2.toString()
else result = f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")"
)
}
override AccessPathFront getFront() {
exists(Content f | this = TConsCons(f, _, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(int len, Content next | this = TConsCons(head, next, len) |
tail = TConsCons(next, _, len - 1)
or
len = 2 and
tail = TConsNil(next, _)
)
}
}
/** Holds if `ap0` corresponds to the cons of `f` and `ap`. */
private predicate pop(AccessPath ap0, Content f, AccessPath ap) {
ap0.getFront().headUsesContent(f) and
consCand(f, ap.getFront(), _) and
ap0.len() = 1 + ap.len()
}
private predicate pop(AccessPath ap0, Content f, AccessPath ap) { ap0.pop(f, ap) }
/** Holds if `ap0` corresponds to the cons of `f` and `ap` and `apf` is the front of `ap`. */
pragma[noinline]
@@ -2002,11 +2044,66 @@ 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 = concat(" : " + 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) |
if len = 1
then result = f.toString()
else 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
@@ -2016,7 +2113,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
@@ -2090,7 +2187,7 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
AccessPath ap;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2099,7 +2196,7 @@ private module FlowExploration {
CallContext getCallContext() { result = cc }
AccessPath getAp() { result = ap }
PartialAccessPath getAp() { result = ap }
override Configuration getConfiguration() { result = config }
@@ -2112,7 +2209,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
@@ -2121,8 +2218,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
@@ -2132,15 +2229,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)
)
@@ -2161,7 +2258,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
@@ -2171,7 +2268,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()
@@ -2180,7 +2279,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
@@ -2191,7 +2290,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
@@ -2203,8 +2302,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
@@ -2217,7 +2316,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)
@@ -2227,7 +2326,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(
@@ -2253,7 +2352,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
@@ -2262,16 +2361,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)
@@ -2279,7 +2378,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
@@ -2293,7 +2392,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
@@ -2313,9 +2413,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)
@@ -2323,7 +2423,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
@@ -2333,8 +2434,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
@@ -2343,7 +2444,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

View File

@@ -7,7 +7,7 @@ class B
Box1 *b1 = new Box1(e, nullptr);
Box2 *b2 = new Box2(b1);
sink(b2->box1->elem1); // flow
sink(b2->box1->elem2); // no flow [FALSE POSITIVE] (due to flow in f2 below)
sink(b2->box1->elem2); // no flow
}
void f2()
@@ -15,7 +15,7 @@ class B
Elem *e = new B::Elem();
Box1 *b1 = new B::Box1(nullptr, e);
Box2 *b2 = new Box2(b1);
sink(b2->box1->elem1); // no flow [FALSE POSITIVE] (due to flow in f1 above)
sink(b2->box1->elem1); // no flow
sink(b2->box1->elem2); // flow
}

View File

@@ -1,222 +1,211 @@
edges
| A.cpp:41:15:41:21 | new [void] | A.cpp:43:10:43:12 | & ... |
| A.cpp:47:12:47:18 | new [void] | A.cpp:48:20:48:20 | c [void] |
| A.cpp:48:12:48:18 | call to make [c, ... (1)] | A.cpp:49:10:49:10 | b [c, ... (1)] |
| A.cpp:48:20:48:20 | c [void] | A.cpp:48:12:48:18 | call to make [c, ... (1)] |
| A.cpp:49:10:49:10 | b [c, ... (1)] | A.cpp:49:13:49:13 | c |
| A.cpp:55:5:55:5 | b [post update] [c, ... (1)] | A.cpp:56:10:56:10 | b [c, ... (1)] |
| A.cpp:55:12:55:19 | new [void] | A.cpp:55:5:55:5 | b [post update] [c, ... (1)] |
| A.cpp:56:10:56:10 | b [c, ... (1)] | A.cpp:56:13:56:15 | call to get |
| A.cpp:57:11:57:24 | call to B [c, ... (1)] | A.cpp:57:11:57:24 | new [c, ... (1)] |
| A.cpp:57:11:57:24 | new [c, ... (1)] | A.cpp:57:28:57:30 | call to get |
| A.cpp:57:17:57:23 | new [void] | A.cpp:57:11:57:24 | call to B [c, ... (1)] |
| A.cpp:64:10:64:15 | call to setOnB [c, ... (1)] | A.cpp:66:10:66:11 | b2 [c, ... (1)] |
| A.cpp:64:21:64:28 | new [void] | A.cpp:64:10:64:15 | call to setOnB [c, ... (1)] |
| A.cpp:66:10:66:11 | b2 [c, ... (1)] | A.cpp:66:14:66:14 | c |
| A.cpp:73:10:73:19 | call to setOnBWrap [c, ... (1)] | A.cpp:75:10:75:11 | b2 [c, ... (1)] |
| A.cpp:73:25:73:32 | new [void] | A.cpp:73:10:73:19 | call to setOnBWrap [c, ... (1)] |
| A.cpp:75:10:75:11 | b2 [c, ... (1)] | A.cpp:75:14:75:14 | c |
| A.cpp:98:12:98:18 | new [void] | A.cpp:100:5:100:13 | ... = ... [void] |
| A.cpp:100:5:100:6 | c1 [post update] [a, ... (1)] | A.cpp:101:8:101:9 | c1 [a, ... (1)] |
| A.cpp:100:5:100:13 | ... = ... [void] | A.cpp:100:5:100:6 | c1 [post update] [a, ... (1)] |
| A.cpp:101:8:101:9 | c1 [a, ... (1)] | A.cpp:103:14:103:14 | c [a, ... (1)] |
| A.cpp:103:14:103:14 | c [a, ... (1)] | A.cpp:107:12:107:13 | c1 [a, ... (1)] |
| A.cpp:103:14:103:14 | c [a, ... (1)] | A.cpp:120:12:120:13 | c1 [a, ... (1)] |
| A.cpp:107:12:107:13 | c1 [a, ... (1)] | A.cpp:107:16:107:16 | a |
| A.cpp:120:12:120:13 | c1 [a, ... (1)] | A.cpp:120:16:120:16 | a |
| A.cpp:126:5:126:5 | b [post update] [c, ... (1)] | A.cpp:131:8:131:8 | ref arg b [c, ... (1)] |
| A.cpp:126:12:126:18 | new [void] | A.cpp:126:5:126:5 | b [post update] [c, ... (1)] |
| A.cpp:131:8:131:8 | ref arg b [c, ... (1)] | A.cpp:132:10:132:10 | b [c, ... (1)] |
| A.cpp:132:10:132:10 | b [c, ... (1)] | A.cpp:132:13:132:13 | c |
| A.cpp:142:7:142:7 | b [post update] [c, ... (1)] | A.cpp:143:7:143:31 | ... = ... [c, ... (1)] |
| A.cpp:142:7:142:7 | b [post update] [c, ... (1)] | A.cpp:151:18:151:18 | ref arg b [c, ... (1)] |
| A.cpp:142:7:142:20 | ... = ... [void] | A.cpp:142:7:142:7 | b [post update] [c, ... (1)] |
| A.cpp:142:14:142:20 | new [void] | A.cpp:142:7:142:20 | ... = ... [void] |
| A.cpp:143:7:143:10 | this [post update] [b, ... (1)] | A.cpp:151:12:151:24 | call to D [b, ... (1)] |
| A.cpp:143:7:143:10 | this [post update] [b, ... (2)] | A.cpp:151:12:151:24 | call to D [b, ... (2)] |
| A.cpp:143:7:143:31 | ... = ... [c, ... (1)] | A.cpp:143:7:143:10 | this [post update] [b, ... (2)] |
| A.cpp:143:7:143:31 | ... = ... [void] | A.cpp:143:7:143:10 | this [post update] [b, ... (1)] |
| A.cpp:143:25:143:31 | new [void] | A.cpp:143:7:143:31 | ... = ... [void] |
| A.cpp:150:12:150:18 | new [void] | A.cpp:151:18:151:18 | b [void] |
| A.cpp:151:12:151:24 | call to D [b, ... (1)] | A.cpp:152:10:152:10 | d [b, ... (1)] |
| A.cpp:151:12:151:24 | call to D [b, ... (2)] | A.cpp:153:10:153:10 | d [b, ... (2)] |
| A.cpp:151:18:151:18 | b [void] | A.cpp:151:12:151:24 | call to D [b, ... (1)] |
| A.cpp:151:18:151:18 | ref arg b [c, ... (1)] | A.cpp:154:10:154:10 | b [c, ... (1)] |
| A.cpp:152:10:152:10 | d [b, ... (1)] | A.cpp:152:13:152:13 | b |
| A.cpp:153:10:153:10 | d [b, ... (2)] | A.cpp:153:13:153:13 | b [c, ... (1)] |
| A.cpp:153:13:153:13 | b [c, ... (1)] | A.cpp:153:16:153:16 | c |
| A.cpp:154:10:154:10 | b [c, ... (1)] | A.cpp:154:13:154:13 | c |
| A.cpp:159:12:159:18 | new [void] | A.cpp:160:29:160:29 | b [void] |
| A.cpp:160:18:160:60 | call to MyList [head, ... (1)] | A.cpp:161:38:161:39 | l1 [head, ... (1)] |
| A.cpp:160:29:160:29 | b [void] | A.cpp:160:18:160:60 | call to MyList [head, ... (1)] |
| A.cpp:161:18:161:40 | call to MyList [next, ... (2)] | A.cpp:162:38:162:39 | l2 [next, ... (2)] |
| A.cpp:161:38:161:39 | l1 [head, ... (1)] | A.cpp:161:18:161:40 | call to MyList [next, ... (2)] |
| A.cpp:162:18:162:40 | call to MyList [next, ... (3)] | A.cpp:165:10:165:11 | l3 [next, ... (3)] |
| A.cpp:162:18:162:40 | call to MyList [next, ... (3)] | A.cpp:167:44:167:44 | l [next, ... (3)] |
| A.cpp:162:38:162:39 | l2 [next, ... (2)] | A.cpp:162:18:162:40 | call to MyList [next, ... (3)] |
| A.cpp:165:10:165:11 | l3 [next, ... (3)] | A.cpp:165:14:165:17 | next [next, ... (2)] |
| A.cpp:165:14:165:17 | next [next, ... (2)] | A.cpp:165:20:165:23 | next [head, ... (1)] |
| A.cpp:165:20:165:23 | next [head, ... (1)] | A.cpp:165:26:165:29 | head |
| A.cpp:167:44:167:44 | l [next, ... (2)] | A.cpp:167:47:167:50 | next [head, ... (1)] |
| A.cpp:167:44:167:44 | l [next, ... (3)] | A.cpp:167:47:167:50 | next [next, ... (2)] |
| A.cpp:167:47:167:50 | next [head, ... (1)] | A.cpp:169:12:169:12 | l [head, ... (1)] |
| A.cpp:167:47:167:50 | next [next, ... (2)] | A.cpp:167:44:167:44 | l [next, ... (2)] |
| A.cpp:169:12:169:12 | l [head, ... (1)] | A.cpp:169:15:169:18 | head |
| B.cpp:6:15:6:24 | new [void] | B.cpp:7:25:7:25 | e [void] |
| B.cpp:7:16:7:35 | call to Box1 [elem1, ... (1)] | B.cpp:8:25:8:26 | b1 [elem1, ... (1)] |
| B.cpp:7:25:7:25 | e [void] | B.cpp:7:16:7:35 | call to Box1 [elem1, ... (1)] |
| B.cpp:8:16:8:27 | call to Box2 [box1, ... (2)] | B.cpp:9:10:9:11 | b2 [box1, ... (2)] |
| B.cpp:8:16:8:27 | call to Box2 [box1, ... (2)] | B.cpp:10:10:10:11 | b2 [box1, ... (2)] |
| B.cpp:8:25:8:26 | b1 [elem1, ... (1)] | B.cpp:8:16:8:27 | call to Box2 [box1, ... (2)] |
| B.cpp:9:10:9:11 | b2 [box1, ... (2)] | B.cpp:9:14:9:17 | box1 [elem1, ... (1)] |
| B.cpp:9:14:9:17 | box1 [elem1, ... (1)] | B.cpp:9:20:9:24 | elem1 |
| B.cpp:10:10:10:11 | b2 [box1, ... (2)] | B.cpp:10:14:10:17 | box1 [elem2, ... (1)] |
| B.cpp:10:14:10:17 | box1 [elem2, ... (1)] | B.cpp:10:20:10:24 | elem2 |
| B.cpp:15:15:15:27 | new [void] | B.cpp:16:37:16:37 | e [void] |
| B.cpp:16:16:16:38 | call to Box1 [elem2, ... (1)] | B.cpp:17:25:17:26 | b1 [elem2, ... (1)] |
| B.cpp:16:37:16:37 | e [void] | B.cpp:16:16:16:38 | call to Box1 [elem2, ... (1)] |
| B.cpp:17:16:17:27 | call to Box2 [box1, ... (2)] | B.cpp:18:10:18:11 | b2 [box1, ... (2)] |
| B.cpp:17:16:17:27 | call to Box2 [box1, ... (2)] | B.cpp:19:10:19:11 | b2 [box1, ... (2)] |
| B.cpp:17:25:17:26 | b1 [elem2, ... (1)] | B.cpp:17:16:17:27 | call to Box2 [box1, ... (2)] |
| B.cpp:18:10:18:11 | b2 [box1, ... (2)] | B.cpp:18:14:18:17 | box1 [elem1, ... (1)] |
| B.cpp:18:14:18:17 | box1 [elem1, ... (1)] | B.cpp:18:20:18:24 | elem1 |
| B.cpp:19:10:19:11 | b2 [box1, ... (2)] | B.cpp:19:14:19:17 | box1 [elem2, ... (1)] |
| B.cpp:19:14:19:17 | box1 [elem2, ... (1)] | B.cpp:19:20:19:24 | elem2 |
| C.cpp:18:12:18:18 | call to C [s1, ... (1)] | C.cpp:19:5:19:5 | c [s1, ... (1)] |
| C.cpp:18:12:18:18 | call to C [s3, ... (1)] | C.cpp:19:5:19:5 | c [s3, ... (1)] |
| C.cpp:19:5:19:5 | c [s1, ... (1)] | C.cpp:27:8:27:11 | `this` parameter in func [s1, ... (1)] |
| C.cpp:19:5:19:5 | c [s3, ... (1)] | C.cpp:27:8:27:11 | `this` parameter in func [s3, ... (1)] |
| C.cpp:22:9:22:22 | constructor init of field s1 [post-this] [s1, ... (1)] | C.cpp:18:12:18:18 | call to C [s1, ... (1)] |
| C.cpp:22:12:22:21 | new [void] | C.cpp:22:9:22:22 | constructor init of field s1 [post-this] [s1, ... (1)] |
| C.cpp:24:5:24:8 | this [post update] [s3, ... (1)] | C.cpp:18:12:18:18 | call to C [s3, ... (1)] |
| C.cpp:24:5:24:25 | ... = ... [void] | C.cpp:24:5:24:8 | this [post update] [s3, ... (1)] |
| C.cpp:24:16:24:25 | new [void] | C.cpp:24:5:24:25 | ... = ... [void] |
| C.cpp:27:8:27:11 | `this` parameter in func [s1, ... (1)] | C.cpp:29:10:29:11 | this [s1, ... (1)] |
| C.cpp:27:8:27:11 | `this` parameter in func [s3, ... (1)] | C.cpp:31:10:31:11 | this [s3, ... (1)] |
| C.cpp:29:10:29:11 | this [s1, ... (1)] | C.cpp:29:10:29:11 | s1 |
| C.cpp:31:10:31:11 | this [s3, ... (1)] | C.cpp:31:10:31:11 | s3 |
| aliasing.cpp:9:3:9:3 | s [post update] [m1, ... (1)] | aliasing.cpp:25:17:25:19 | ref arg & ... [m1, ... (1)] |
| aliasing.cpp:9:3:9:22 | ... = ... [void] | aliasing.cpp:9:3:9:3 | s [post update] [m1, ... (1)] |
| aliasing.cpp:9:11:9:20 | call to user_input [void] | aliasing.cpp:9:3:9:22 | ... = ... [void] |
| aliasing.cpp:13:3:13:3 | s [post update] [m1, ... (1)] | aliasing.cpp:26:19:26:20 | ref arg s2 [m1, ... (1)] |
| aliasing.cpp:13:3:13:21 | ... = ... [void] | aliasing.cpp:13:3:13:3 | s [post update] [m1, ... (1)] |
| aliasing.cpp:13:10:13:19 | call to user_input [void] | aliasing.cpp:13:3:13:21 | ... = ... [void] |
| aliasing.cpp:25:17:25:19 | ref arg & ... [m1, ... (1)] | aliasing.cpp:29:8:29:9 | s1 [m1, ... (1)] |
| aliasing.cpp:26:19:26:20 | ref arg s2 [m1, ... (1)] | aliasing.cpp:30:8:30:9 | s2 [m1, ... (1)] |
| aliasing.cpp:29:8:29:9 | s1 [m1, ... (1)] | aliasing.cpp:29:11:29:12 | m1 |
| aliasing.cpp:30:8:30:9 | s2 [m1, ... (1)] | aliasing.cpp:30:11:30:12 | m1 |
| aliasing.cpp:60:3:60:4 | s2 [post update] [m1, ... (1)] | aliasing.cpp:62:8:62:12 | copy2 [m1, ... (1)] |
| aliasing.cpp:60:3:60:22 | ... = ... [void] | aliasing.cpp:60:3:60:4 | s2 [post update] [m1, ... (1)] |
| aliasing.cpp:60:11:60:20 | call to user_input [void] | aliasing.cpp:60:3:60:22 | ... = ... [void] |
| aliasing.cpp:62:8:62:12 | copy2 [m1, ... (1)] | aliasing.cpp:62:14:62:15 | m1 |
| aliasing.cpp:92:3:92:3 | w [post update] [s, ... (2)] | aliasing.cpp:93:8:93:8 | w [s, ... (2)] |
| aliasing.cpp:92:3:92:23 | ... = ... [void] | aliasing.cpp:92:5:92:5 | s [post update] [m1, ... (1)] |
| aliasing.cpp:92:5:92:5 | s [post update] [m1, ... (1)] | aliasing.cpp:92:3:92:3 | w [post update] [s, ... (2)] |
| aliasing.cpp:92:12:92:21 | call to user_input [void] | aliasing.cpp:92:3:92:23 | ... = ... [void] |
| aliasing.cpp:93:8:93:8 | w [s, ... (2)] | aliasing.cpp:93:10:93:10 | s [m1, ... (1)] |
| aliasing.cpp:93:10:93:10 | s [m1, ... (1)] | aliasing.cpp:93:12:93:13 | m1 |
| complex.cpp:34:15:34:15 | b [f, ... (2)] | complex.cpp:44:8:44:8 | b [f, ... (2)] |
| complex.cpp:34:15:34:15 | b [f, ... (2)] | complex.cpp:45:8:45:8 | b [f, ... (2)] |
| complex.cpp:44:8:44:8 | b [f, ... (2)] | complex.cpp:44:10:44:10 | f [a_, ... (1)] |
| complex.cpp:44:10:44:10 | f [a_, ... (1)] | complex.cpp:44:12:44:12 | call to a |
| complex.cpp:45:8:45:8 | b [f, ... (2)] | complex.cpp:45:10:45:10 | f [b_, ... (1)] |
| complex.cpp:45:10:45:10 | f [b_, ... (1)] | complex.cpp:45:12:45:12 | call to b |
| complex.cpp:55:3:55:4 | b1 [post update] [f, ... (2)] | complex.cpp:61:7:61:8 | b1 [f, ... (2)] |
| complex.cpp:55:6:55:6 | f [post update] [a_, ... (1)] | complex.cpp:55:3:55:4 | b1 [post update] [f, ... (2)] |
| complex.cpp:55:13:55:22 | call to user_input [void] | complex.cpp:55:6:55:6 | f [post update] [a_, ... (1)] |
| complex.cpp:56:3:56:4 | b2 [post update] [f, ... (2)] | complex.cpp:64:7:64:8 | b2 [f, ... (2)] |
| complex.cpp:56:6:56:6 | f [post update] [b_, ... (1)] | complex.cpp:56:3:56:4 | b2 [post update] [f, ... (2)] |
| complex.cpp:56:13:56:22 | call to user_input [void] | complex.cpp:56:6:56:6 | f [post update] [b_, ... (1)] |
| complex.cpp:57:3:57:4 | b3 [post update] [f, ... (2)] | complex.cpp:67:7:67:8 | b3 [f, ... (2)] |
| complex.cpp:57:6:57:6 | f [post update] [a_, ... (1)] | complex.cpp:57:3:57:4 | b3 [post update] [f, ... (2)] |
| complex.cpp:57:13:57:22 | call to user_input [void] | complex.cpp:57:6:57:6 | f [post update] [a_, ... (1)] |
| complex.cpp:58:3:58:4 | b3 [post update] [f, ... (2)] | complex.cpp:67:7:67:8 | b3 [f, ... (2)] |
| complex.cpp:58:6:58:6 | f [post update] [b_, ... (1)] | complex.cpp:58:3:58:4 | b3 [post update] [f, ... (2)] |
| complex.cpp:58:13:58:22 | call to user_input [void] | complex.cpp:58:6:58:6 | f [post update] [b_, ... (1)] |
| complex.cpp:61:7:61:8 | b1 [f, ... (2)] | complex.cpp:34:15:34:15 | b [f, ... (2)] |
| complex.cpp:64:7:64:8 | b2 [f, ... (2)] | complex.cpp:34:15:34:15 | b [f, ... (2)] |
| complex.cpp:67:7:67:8 | b3 [f, ... (2)] | complex.cpp:34:15:34:15 | b [f, ... (2)] |
| constructors.cpp:26:15:26:15 | f [a_, ... (1)] | constructors.cpp:28:10:28:10 | f [a_, ... (1)] |
| constructors.cpp:26:15:26:15 | f [b_, ... (1)] | constructors.cpp:29:10:29:10 | f [b_, ... (1)] |
| constructors.cpp:28:10:28:10 | f [a_, ... (1)] | constructors.cpp:28:12:28:12 | call to a |
| constructors.cpp:29:10:29:10 | f [b_, ... (1)] | constructors.cpp:29:12:29:12 | call to b |
| constructors.cpp:34:11:34:20 | call to user_input [void] | constructors.cpp:34:11:34:26 | call to Foo [a_, ... (1)] |
| constructors.cpp:34:11:34:26 | call to Foo [a_, ... (1)] | constructors.cpp:40:9:40:9 | f [a_, ... (1)] |
| constructors.cpp:35:11:35:26 | call to Foo [b_, ... (1)] | constructors.cpp:43:9:43:9 | g [b_, ... (1)] |
| constructors.cpp:35:14:35:23 | call to user_input [void] | constructors.cpp:35:11:35:26 | call to Foo [b_, ... (1)] |
| constructors.cpp:36:11:36:20 | call to user_input [void] | constructors.cpp:36:11:36:37 | call to Foo [a_, ... (1)] |
| constructors.cpp:36:11:36:37 | call to Foo [a_, ... (1)] | constructors.cpp:46:9:46:9 | h [a_, ... (1)] |
| constructors.cpp:36:11:36:37 | call to Foo [b_, ... (1)] | constructors.cpp:46:9:46:9 | h [b_, ... (1)] |
| constructors.cpp:36:25:36:34 | call to user_input [void] | constructors.cpp:36:11:36:37 | call to Foo [b_, ... (1)] |
| constructors.cpp:40:9:40:9 | f [a_, ... (1)] | constructors.cpp:26:15:26:15 | f [a_, ... (1)] |
| constructors.cpp:43:9:43:9 | g [b_, ... (1)] | constructors.cpp:26:15:26:15 | f [b_, ... (1)] |
| constructors.cpp:46:9:46:9 | h [a_, ... (1)] | constructors.cpp:26:15:26:15 | f [a_, ... (1)] |
| constructors.cpp:46:9:46:9 | h [b_, ... (1)] | constructors.cpp:26:15:26:15 | f [b_, ... (1)] |
| simple.cpp:26:15:26:15 | f [a_, ... (1)] | simple.cpp:28:10:28:10 | f [a_, ... (1)] |
| simple.cpp:26:15:26:15 | f [b_, ... (1)] | simple.cpp:29:10:29:10 | f [b_, ... (1)] |
| simple.cpp:28:10:28:10 | f [a_, ... (1)] | simple.cpp:28:12:28:12 | call to a |
| simple.cpp:29:10:29:10 | f [b_, ... (1)] | simple.cpp:29:12:29:12 | call to b |
| simple.cpp:39:5:39:5 | f [post update] [a_, ... (1)] | simple.cpp:45:9:45:9 | f [a_, ... (1)] |
| simple.cpp:39:12:39:21 | call to user_input [void] | simple.cpp:39:5:39:5 | f [post update] [a_, ... (1)] |
| simple.cpp:40:5:40:5 | g [post update] [b_, ... (1)] | simple.cpp:48:9:48:9 | g [b_, ... (1)] |
| simple.cpp:40:12:40:21 | call to user_input [void] | simple.cpp:40:5:40:5 | g [post update] [b_, ... (1)] |
| simple.cpp:41:5:41:5 | h [post update] [a_, ... (1)] | simple.cpp:51:9:51:9 | h [a_, ... (1)] |
| simple.cpp:41:12:41:21 | call to user_input [void] | simple.cpp:41:5:41:5 | h [post update] [a_, ... (1)] |
| simple.cpp:42:5:42:5 | h [post update] [b_, ... (1)] | simple.cpp:51:9:51:9 | h [b_, ... (1)] |
| simple.cpp:42:12:42:21 | call to user_input [void] | simple.cpp:42:5:42:5 | h [post update] [b_, ... (1)] |
| simple.cpp:45:9:45:9 | f [a_, ... (1)] | simple.cpp:26:15:26:15 | f [a_, ... (1)] |
| simple.cpp:48:9:48:9 | g [b_, ... (1)] | simple.cpp:26:15:26:15 | f [b_, ... (1)] |
| simple.cpp:51:9:51:9 | h [a_, ... (1)] | simple.cpp:26:15:26:15 | f [a_, ... (1)] |
| simple.cpp:51:9:51:9 | h [b_, ... (1)] | simple.cpp:26:15:26:15 | f [b_, ... (1)] |
| struct_init.c:20:17:20:36 | {...} [a, ... (1)] | struct_init.c:22:8:22:9 | ab [a, ... (1)] |
| struct_init.c:20:20:20:29 | call to user_input [void] | struct_init.c:20:17:20:36 | {...} [a, ... (1)] |
| struct_init.c:22:8:22:9 | ab [a, ... (1)] | struct_init.c:22:11:22:11 | a |
| struct_init.c:26:23:29:3 | {...} [nestedAB, ... (2)] | struct_init.c:31:8:31:12 | outer [nestedAB, ... (2)] |
| struct_init.c:27:5:27:23 | {...} [a, ... (1)] | struct_init.c:26:23:29:3 | {...} [nestedAB, ... (2)] |
| struct_init.c:27:7:27:16 | call to user_input [void] | struct_init.c:27:5:27:23 | {...} [a, ... (1)] |
| struct_init.c:31:8:31:12 | outer [nestedAB, ... (2)] | struct_init.c:31:14:31:21 | nestedAB [a, ... (1)] |
| struct_init.c:31:14:31:21 | nestedAB [a, ... (1)] | struct_init.c:31:23:31:23 | a |
| A.cpp:41:15:41:21 | new | A.cpp:43:10:43:12 | & ... |
| A.cpp:47:12:47:18 | new | A.cpp:48:20:48:20 | c |
| A.cpp:48:12:48:18 | call to make [c] | A.cpp:49:10:49:10 | b [c] |
| A.cpp:48:20:48:20 | c | A.cpp:48:12:48:18 | call to make [c] |
| A.cpp:49:10:49:10 | b [c] | A.cpp:49:13:49:13 | c |
| A.cpp:55:5:55:5 | b [post update] [c] | A.cpp:56:10:56:10 | b [c] |
| A.cpp:55:12:55:19 | new | A.cpp:55:5:55:5 | b [post update] [c] |
| A.cpp:56:10:56:10 | b [c] | A.cpp:56:13:56:15 | call to get |
| A.cpp:57:11:57:24 | call to B [c] | A.cpp:57:11:57:24 | new [c] |
| A.cpp:57:11:57:24 | new [c] | A.cpp:57:28:57:30 | call to get |
| A.cpp:57:17:57:23 | new | A.cpp:57:11:57:24 | call to B [c] |
| A.cpp:64:10:64:15 | call to setOnB [c] | A.cpp:66:10:66:11 | b2 [c] |
| A.cpp:64:21:64:28 | new | A.cpp:64:10:64:15 | call to setOnB [c] |
| A.cpp:66:10:66:11 | b2 [c] | A.cpp:66:14:66:14 | c |
| A.cpp:73:10:73:19 | call to setOnBWrap [c] | A.cpp:75:10:75:11 | b2 [c] |
| A.cpp:73:25:73:32 | new | A.cpp:73:10:73:19 | call to setOnBWrap [c] |
| A.cpp:75:10:75:11 | b2 [c] | A.cpp:75:14:75:14 | c |
| A.cpp:98:12:98:18 | new | A.cpp:100:5:100:13 | ... = ... |
| A.cpp:100:5:100:6 | c1 [post update] [a] | A.cpp:101:8:101:9 | c1 [a] |
| A.cpp:100:5:100:13 | ... = ... | A.cpp:100:5:100:6 | c1 [post update] [a] |
| A.cpp:101:8:101:9 | c1 [a] | A.cpp:103:14:103:14 | c [a] |
| A.cpp:103:14:103:14 | c [a] | A.cpp:107:12:107:13 | c1 [a] |
| A.cpp:103:14:103:14 | c [a] | A.cpp:120:12:120:13 | c1 [a] |
| A.cpp:107:12:107:13 | c1 [a] | A.cpp:107:16:107:16 | a |
| A.cpp:120:12:120:13 | c1 [a] | A.cpp:120:16:120:16 | a |
| A.cpp:126:5:126:5 | b [post update] [c] | A.cpp:131:8:131:8 | ref arg b [c] |
| A.cpp:126:12:126:18 | new | A.cpp:126:5:126:5 | b [post update] [c] |
| A.cpp:131:8:131:8 | ref arg b [c] | A.cpp:132:10:132:10 | b [c] |
| A.cpp:132:10:132:10 | b [c] | A.cpp:132:13:132:13 | c |
| A.cpp:142:7:142:7 | b [post update] [c] | A.cpp:143:7:143:31 | ... = ... [c] |
| A.cpp:142:7:142:7 | b [post update] [c] | A.cpp:151:18:151:18 | ref arg b [c] |
| A.cpp:142:7:142:20 | ... = ... | A.cpp:142:7:142:7 | b [post update] [c] |
| A.cpp:142:14:142:20 | new | A.cpp:142:7:142:20 | ... = ... |
| A.cpp:143:7:143:10 | this [post update] [b, c] | A.cpp:151:12:151:24 | call to D [b, c] |
| A.cpp:143:7:143:10 | this [post update] [b] | A.cpp:151:12:151:24 | call to D [b] |
| A.cpp:143:7:143:31 | ... = ... | A.cpp:143:7:143:10 | this [post update] [b] |
| A.cpp:143:7:143:31 | ... = ... [c] | A.cpp:143:7:143:10 | this [post update] [b, c] |
| A.cpp:143:25:143:31 | new | A.cpp:143:7:143:31 | ... = ... |
| A.cpp:150:12:150:18 | new | A.cpp:151:18:151:18 | b |
| A.cpp:151:12:151:24 | call to D [b, c] | A.cpp:153:10:153:10 | d [b, c] |
| A.cpp:151:12:151:24 | call to D [b] | A.cpp:152:10:152:10 | d [b] |
| A.cpp:151:18:151:18 | b | A.cpp:151:12:151:24 | call to D [b] |
| A.cpp:151:18:151:18 | ref arg b [c] | A.cpp:154:10:154:10 | b [c] |
| A.cpp:152:10:152:10 | d [b] | A.cpp:152:13:152:13 | b |
| A.cpp:153:10:153:10 | d [b, c] | A.cpp:153:13:153:13 | b [c] |
| A.cpp:153:13:153:13 | b [c] | A.cpp:153:16:153:16 | c |
| A.cpp:154:10:154:10 | b [c] | A.cpp:154:13:154:13 | c |
| A.cpp:159:12:159:18 | new | A.cpp:160:29:160:29 | b |
| A.cpp:160:18:160:60 | call to MyList [head] | A.cpp:161:38:161:39 | l1 [head] |
| A.cpp:160:29:160:29 | b | A.cpp:160:18:160:60 | call to MyList [head] |
| A.cpp:161:18:161:40 | call to MyList [next, head] | A.cpp:162:38:162:39 | l2 [next, head] |
| A.cpp:161:38:161:39 | l1 [head] | A.cpp:161:18:161:40 | call to MyList [next, head] |
| A.cpp:162:18:162:40 | call to MyList [next, next, ... (3)] | A.cpp:165:10:165:11 | l3 [next, next, ... (3)] |
| A.cpp:162:18:162:40 | call to MyList [next, next, ... (3)] | A.cpp:167:44:167:44 | l [next, next, ... (3)] |
| A.cpp:162:38:162:39 | l2 [next, head] | A.cpp:162:18:162:40 | call to MyList [next, next, ... (3)] |
| A.cpp:165:10:165:11 | l3 [next, next, ... (3)] | A.cpp:165:14:165:17 | next [next, head] |
| A.cpp:165:14:165:17 | next [next, head] | A.cpp:165:20:165:23 | next [head] |
| A.cpp:165:20:165:23 | next [head] | A.cpp:165:26:165:29 | head |
| A.cpp:167:44:167:44 | l [next, head] | A.cpp:167:47:167:50 | next [head] |
| A.cpp:167:44:167:44 | l [next, next, ... (3)] | A.cpp:167:47:167:50 | next [next, head] |
| A.cpp:167:47:167:50 | next [head] | A.cpp:169:12:169:12 | l [head] |
| A.cpp:167:47:167:50 | next [next, head] | A.cpp:167:44:167:44 | l [next, head] |
| A.cpp:169:12:169:12 | l [head] | A.cpp:169:15:169:18 | head |
| B.cpp:6:15:6:24 | new | B.cpp:7:25:7:25 | e |
| B.cpp:7:16:7:35 | call to Box1 [elem1] | B.cpp:8:25:8:26 | b1 [elem1] |
| B.cpp:7:25:7:25 | e | B.cpp:7:16:7:35 | call to Box1 [elem1] |
| B.cpp:8:16:8:27 | call to Box2 [box1, elem1] | B.cpp:9:10:9:11 | b2 [box1, elem1] |
| B.cpp:8:25:8:26 | b1 [elem1] | B.cpp:8:16:8:27 | call to Box2 [box1, elem1] |
| B.cpp:9:10:9:11 | b2 [box1, elem1] | B.cpp:9:14:9:17 | box1 [elem1] |
| B.cpp:9:14:9:17 | box1 [elem1] | B.cpp:9:20:9:24 | elem1 |
| B.cpp:15:15:15:27 | new | B.cpp:16:37:16:37 | e |
| B.cpp:16:16:16:38 | call to Box1 [elem2] | B.cpp:17:25:17:26 | b1 [elem2] |
| B.cpp:16:37:16:37 | e | B.cpp:16:16:16:38 | call to Box1 [elem2] |
| B.cpp:17:16:17:27 | call to Box2 [box1, elem2] | B.cpp:19:10:19:11 | b2 [box1, elem2] |
| B.cpp:17:25:17:26 | b1 [elem2] | B.cpp:17:16:17:27 | call to Box2 [box1, elem2] |
| B.cpp:19:10:19:11 | b2 [box1, elem2] | B.cpp:19:14:19:17 | box1 [elem2] |
| B.cpp:19:14:19:17 | box1 [elem2] | B.cpp:19:20:19:24 | elem2 |
| C.cpp:18:12:18:18 | call to C [s1] | C.cpp:19:5:19:5 | c [s1] |
| C.cpp:18:12:18:18 | call to C [s3] | C.cpp:19:5:19:5 | c [s3] |
| C.cpp:19:5:19:5 | c [s1] | C.cpp:27:8:27:11 | `this` parameter in func [s1] |
| C.cpp:19:5:19:5 | c [s3] | C.cpp:27:8:27:11 | `this` parameter in func [s3] |
| C.cpp:22:9:22:22 | constructor init of field s1 [post-this] [s1] | C.cpp:18:12:18:18 | call to C [s1] |
| C.cpp:22:12:22:21 | new | C.cpp:22:9:22:22 | constructor init of field s1 [post-this] [s1] |
| C.cpp:24:5:24:8 | this [post update] [s3] | C.cpp:18:12:18:18 | call to C [s3] |
| C.cpp:24:5:24:25 | ... = ... | C.cpp:24:5:24:8 | this [post update] [s3] |
| C.cpp:24:16:24:25 | new | C.cpp:24:5:24:25 | ... = ... |
| C.cpp:27:8:27:11 | `this` parameter in func [s1] | C.cpp:29:10:29:11 | this [s1] |
| C.cpp:27:8:27:11 | `this` parameter in func [s3] | C.cpp:31:10:31:11 | this [s3] |
| C.cpp:29:10:29:11 | this [s1] | C.cpp:29:10:29:11 | s1 |
| C.cpp:31:10:31:11 | this [s3] | C.cpp:31:10:31:11 | s3 |
| aliasing.cpp:9:3:9:3 | s [post update] [m1] | aliasing.cpp:25:17:25:19 | ref arg & ... [m1] |
| aliasing.cpp:9:3:9:22 | ... = ... | aliasing.cpp:9:3:9:3 | s [post update] [m1] |
| aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:9:3:9:22 | ... = ... |
| aliasing.cpp:13:3:13:3 | s [post update] [m1] | aliasing.cpp:26:19:26:20 | ref arg s2 [m1] |
| aliasing.cpp:13:3:13:21 | ... = ... | aliasing.cpp:13:3:13:3 | s [post update] [m1] |
| aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:13:3:13:21 | ... = ... |
| aliasing.cpp:25:17:25:19 | ref arg & ... [m1] | aliasing.cpp:29:8:29:9 | s1 [m1] |
| aliasing.cpp:26:19:26:20 | ref arg s2 [m1] | aliasing.cpp:30:8:30:9 | s2 [m1] |
| aliasing.cpp:29:8:29:9 | s1 [m1] | aliasing.cpp:29:11:29:12 | m1 |
| aliasing.cpp:30:8:30:9 | s2 [m1] | aliasing.cpp:30:11:30:12 | m1 |
| aliasing.cpp:60:3:60:4 | s2 [post update] [m1] | aliasing.cpp:62:8:62:12 | copy2 [m1] |
| aliasing.cpp:60:3:60:22 | ... = ... | aliasing.cpp:60:3:60:4 | s2 [post update] [m1] |
| aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:60:3:60:22 | ... = ... |
| aliasing.cpp:62:8:62:12 | copy2 [m1] | aliasing.cpp:62:14:62:15 | m1 |
| aliasing.cpp:92:3:92:3 | w [post update] [s, m1] | aliasing.cpp:93:8:93:8 | w [s, m1] |
| aliasing.cpp:92:3:92:23 | ... = ... | aliasing.cpp:92:5:92:5 | s [post update] [m1] |
| aliasing.cpp:92:5:92:5 | s [post update] [m1] | aliasing.cpp:92:3:92:3 | w [post update] [s, m1] |
| aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:92:3:92:23 | ... = ... |
| aliasing.cpp:93:8:93:8 | w [s, m1] | aliasing.cpp:93:10:93:10 | s [m1] |
| aliasing.cpp:93:10:93:10 | s [m1] | aliasing.cpp:93:12:93:13 | m1 |
| complex.cpp:34:15:34:15 | b [f, a_] | complex.cpp:44:8:44:8 | b [f, a_] |
| complex.cpp:34:15:34:15 | b [f, b_] | complex.cpp:45:8:45:8 | b [f, b_] |
| complex.cpp:44:8:44:8 | b [f, a_] | complex.cpp:44:10:44:10 | f [a_] |
| complex.cpp:44:10:44:10 | f [a_] | complex.cpp:44:12:44:12 | call to a |
| complex.cpp:45:8:45:8 | b [f, b_] | complex.cpp:45:10:45:10 | f [b_] |
| complex.cpp:45:10:45:10 | f [b_] | complex.cpp:45:12:45:12 | call to b |
| complex.cpp:55:3:55:4 | b1 [post update] [f, a_] | complex.cpp:61:7:61:8 | b1 [f, a_] |
| complex.cpp:55:6:55:6 | f [post update] [a_] | complex.cpp:55:3:55:4 | b1 [post update] [f, a_] |
| complex.cpp:55:13:55:22 | call to user_input | complex.cpp:55:6:55:6 | f [post update] [a_] |
| complex.cpp:56:3:56:4 | b2 [post update] [f, b_] | complex.cpp:64:7:64:8 | b2 [f, b_] |
| complex.cpp:56:6:56:6 | f [post update] [b_] | complex.cpp:56:3:56:4 | b2 [post update] [f, b_] |
| complex.cpp:56:13:56:22 | call to user_input | complex.cpp:56:6:56:6 | f [post update] [b_] |
| complex.cpp:57:3:57:4 | b3 [post update] [f, a_] | complex.cpp:67:7:67:8 | b3 [f, a_] |
| complex.cpp:57:6:57:6 | f [post update] [a_] | complex.cpp:57:3:57:4 | b3 [post update] [f, a_] |
| complex.cpp:57:13:57:22 | call to user_input | complex.cpp:57:6:57:6 | f [post update] [a_] |
| complex.cpp:58:3:58:4 | b3 [post update] [f, b_] | complex.cpp:67:7:67:8 | b3 [f, b_] |
| complex.cpp:58:6:58:6 | f [post update] [b_] | complex.cpp:58:3:58:4 | b3 [post update] [f, b_] |
| complex.cpp:58:13:58:22 | call to user_input | complex.cpp:58:6:58:6 | f [post update] [b_] |
| complex.cpp:61:7:61:8 | b1 [f, a_] | complex.cpp:34:15:34:15 | b [f, a_] |
| complex.cpp:64:7:64:8 | b2 [f, b_] | complex.cpp:34:15:34:15 | b [f, b_] |
| complex.cpp:67:7:67:8 | b3 [f, a_] | complex.cpp:34:15:34:15 | b [f, a_] |
| complex.cpp:67:7:67:8 | b3 [f, b_] | complex.cpp:34:15:34:15 | b [f, b_] |
| constructors.cpp:26:15:26:15 | f [a_] | constructors.cpp:28:10:28:10 | f [a_] |
| constructors.cpp:26:15:26:15 | f [b_] | constructors.cpp:29:10:29:10 | f [b_] |
| constructors.cpp:28:10:28:10 | f [a_] | constructors.cpp:28:12:28:12 | call to a |
| constructors.cpp:29:10:29:10 | f [b_] | constructors.cpp:29:12:29:12 | call to b |
| constructors.cpp:34:11:34:20 | call to user_input | constructors.cpp:34:11:34:26 | call to Foo [a_] |
| constructors.cpp:34:11:34:26 | call to Foo [a_] | constructors.cpp:40:9:40:9 | f [a_] |
| constructors.cpp:35:11:35:26 | call to Foo [b_] | constructors.cpp:43:9:43:9 | g [b_] |
| constructors.cpp:35:14:35:23 | call to user_input | constructors.cpp:35:11:35:26 | call to Foo [b_] |
| constructors.cpp:36:11:36:20 | call to user_input | constructors.cpp:36:11:36:37 | call to Foo [a_] |
| constructors.cpp:36:11:36:37 | call to Foo [a_] | constructors.cpp:46:9:46:9 | h [a_] |
| constructors.cpp:36:11:36:37 | call to Foo [b_] | constructors.cpp:46:9:46:9 | h [b_] |
| constructors.cpp:36:25:36:34 | call to user_input | constructors.cpp:36:11:36:37 | call to Foo [b_] |
| constructors.cpp:40:9:40:9 | f [a_] | constructors.cpp:26:15:26:15 | f [a_] |
| constructors.cpp:43:9:43:9 | g [b_] | constructors.cpp:26:15:26:15 | f [b_] |
| constructors.cpp:46:9:46:9 | h [a_] | constructors.cpp:26:15:26:15 | f [a_] |
| constructors.cpp:46:9:46:9 | h [b_] | constructors.cpp:26:15:26:15 | f [b_] |
| simple.cpp:26:15:26:15 | f [a_] | simple.cpp:28:10:28:10 | f [a_] |
| simple.cpp:26:15:26:15 | f [b_] | simple.cpp:29:10:29:10 | f [b_] |
| simple.cpp:28:10:28:10 | f [a_] | simple.cpp:28:12:28:12 | call to a |
| simple.cpp:29:10:29:10 | f [b_] | simple.cpp:29:12:29:12 | call to b |
| simple.cpp:39:5:39:5 | f [post update] [a_] | simple.cpp:45:9:45:9 | f [a_] |
| simple.cpp:39:12:39:21 | call to user_input | simple.cpp:39:5:39:5 | f [post update] [a_] |
| simple.cpp:40:5:40:5 | g [post update] [b_] | simple.cpp:48:9:48:9 | g [b_] |
| simple.cpp:40:12:40:21 | call to user_input | simple.cpp:40:5:40:5 | g [post update] [b_] |
| simple.cpp:41:5:41:5 | h [post update] [a_] | simple.cpp:51:9:51:9 | h [a_] |
| simple.cpp:41:12:41:21 | call to user_input | simple.cpp:41:5:41:5 | h [post update] [a_] |
| simple.cpp:42:5:42:5 | h [post update] [b_] | simple.cpp:51:9:51:9 | h [b_] |
| simple.cpp:42:12:42:21 | call to user_input | simple.cpp:42:5:42:5 | h [post update] [b_] |
| simple.cpp:45:9:45:9 | f [a_] | simple.cpp:26:15:26:15 | f [a_] |
| simple.cpp:48:9:48:9 | g [b_] | simple.cpp:26:15:26:15 | f [b_] |
| simple.cpp:51:9:51:9 | h [a_] | simple.cpp:26:15:26:15 | f [a_] |
| simple.cpp:51:9:51:9 | h [b_] | simple.cpp:26:15:26:15 | f [b_] |
| struct_init.c:20:17:20:36 | {...} [a] | struct_init.c:22:8:22:9 | ab [a] |
| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:20:17:20:36 | {...} [a] |
| struct_init.c:22:8:22:9 | ab [a] | struct_init.c:22:11:22:11 | a |
| struct_init.c:26:23:29:3 | {...} [nestedAB, a] | struct_init.c:31:8:31:12 | outer [nestedAB, a] |
| struct_init.c:27:5:27:23 | {...} [a] | struct_init.c:26:23:29:3 | {...} [nestedAB, a] |
| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:27:5:27:23 | {...} [a] |
| struct_init.c:31:8:31:12 | outer [nestedAB, a] | struct_init.c:31:14:31:21 | nestedAB [a] |
| struct_init.c:31:14:31:21 | nestedAB [a] | struct_init.c:31:23:31:23 | a |
#select
| A.cpp:43:10:43:12 | & ... | A.cpp:41:15:41:21 | new [void] | A.cpp:43:10:43:12 | & ... | & ... flows from $@ | A.cpp:41:15:41:21 | new [void] | new [void] |
| A.cpp:49:13:49:13 | c | A.cpp:47:12:47:18 | new [void] | A.cpp:49:13:49:13 | c | c flows from $@ | A.cpp:47:12:47:18 | new [void] | new [void] |
| A.cpp:56:13:56:15 | call to get | A.cpp:55:12:55:19 | new [void] | A.cpp:56:13:56:15 | call to get | call to get flows from $@ | A.cpp:55:12:55:19 | new [void] | new [void] |
| A.cpp:57:28:57:30 | call to get | A.cpp:57:17:57:23 | new [void] | A.cpp:57:28:57:30 | call to get | call to get flows from $@ | A.cpp:57:17:57:23 | new [void] | new [void] |
| A.cpp:66:14:66:14 | c | A.cpp:64:21:64:28 | new [void] | A.cpp:66:14:66:14 | c | c flows from $@ | A.cpp:64:21:64:28 | new [void] | new [void] |
| A.cpp:75:14:75:14 | c | A.cpp:73:25:73:32 | new [void] | A.cpp:75:14:75:14 | c | c flows from $@ | A.cpp:73:25:73:32 | new [void] | new [void] |
| A.cpp:107:16:107:16 | a | A.cpp:98:12:98:18 | new [void] | A.cpp:107:16:107:16 | a | a flows from $@ | A.cpp:98:12:98:18 | new [void] | new [void] |
| A.cpp:120:16:120:16 | a | A.cpp:98:12:98:18 | new [void] | A.cpp:120:16:120:16 | a | a flows from $@ | A.cpp:98:12:98:18 | new [void] | new [void] |
| A.cpp:132:13:132:13 | c | A.cpp:126:12:126:18 | new [void] | A.cpp:132:13:132:13 | c | c flows from $@ | A.cpp:126:12:126:18 | new [void] | new [void] |
| A.cpp:152:13:152:13 | b | A.cpp:143:25:143:31 | new [void] | A.cpp:152:13:152:13 | b | b flows from $@ | A.cpp:143:25:143:31 | new [void] | new [void] |
| A.cpp:152:13:152:13 | b | A.cpp:150:12:150:18 | new [void] | A.cpp:152:13:152:13 | b | b flows from $@ | A.cpp:150:12:150:18 | new [void] | new [void] |
| A.cpp:153:16:153:16 | c | A.cpp:142:14:142:20 | new [void] | A.cpp:153:16:153:16 | c | c flows from $@ | A.cpp:142:14:142:20 | new [void] | new [void] |
| A.cpp:154:13:154:13 | c | A.cpp:142:14:142:20 | new [void] | A.cpp:154:13:154:13 | c | c flows from $@ | A.cpp:142:14:142:20 | new [void] | new [void] |
| A.cpp:165:26:165:29 | head | A.cpp:159:12:159:18 | new [void] | A.cpp:165:26:165:29 | head | head flows from $@ | A.cpp:159:12:159:18 | new [void] | new [void] |
| A.cpp:169:15:169:18 | head | A.cpp:159:12:159:18 | new [void] | A.cpp:169:15:169:18 | head | head flows from $@ | A.cpp:159:12:159:18 | new [void] | new [void] |
| B.cpp:9:20:9:24 | elem1 | B.cpp:6:15:6:24 | new [void] | B.cpp:9:20:9:24 | elem1 | elem1 flows from $@ | B.cpp:6:15:6:24 | new [void] | new [void] |
| B.cpp:10:20:10:24 | elem2 | B.cpp:6:15:6:24 | new [void] | B.cpp:10:20:10:24 | elem2 | elem2 flows from $@ | B.cpp:6:15:6:24 | new [void] | new [void] |
| B.cpp:18:20:18:24 | elem1 | B.cpp:15:15:15:27 | new [void] | B.cpp:18:20:18:24 | elem1 | elem1 flows from $@ | B.cpp:15:15:15:27 | new [void] | new [void] |
| B.cpp:19:20:19:24 | elem2 | B.cpp:15:15:15:27 | new [void] | B.cpp:19:20:19:24 | elem2 | elem2 flows from $@ | B.cpp:15:15:15:27 | new [void] | new [void] |
| C.cpp:29:10:29:11 | s1 | C.cpp:22:12:22:21 | new [void] | C.cpp:29:10:29:11 | s1 | s1 flows from $@ | C.cpp:22:12:22:21 | new [void] | new [void] |
| C.cpp:31:10:31:11 | s3 | C.cpp:24:16:24:25 | new [void] | C.cpp:31:10:31:11 | s3 | s3 flows from $@ | C.cpp:24:16:24:25 | new [void] | new [void] |
| aliasing.cpp:29:11:29:12 | m1 | aliasing.cpp:9:11:9:20 | call to user_input [void] | aliasing.cpp:29:11:29:12 | m1 | m1 flows from $@ | aliasing.cpp:9:11:9:20 | call to user_input [void] | call to user_input [void] |
| aliasing.cpp:30:11:30:12 | m1 | aliasing.cpp:13:10:13:19 | call to user_input [void] | aliasing.cpp:30:11:30:12 | m1 | m1 flows from $@ | aliasing.cpp:13:10:13:19 | call to user_input [void] | call to user_input [void] |
| aliasing.cpp:62:14:62:15 | m1 | aliasing.cpp:60:11:60:20 | call to user_input [void] | aliasing.cpp:62:14:62:15 | m1 | m1 flows from $@ | aliasing.cpp:60:11:60:20 | call to user_input [void] | call to user_input [void] |
| aliasing.cpp:93:12:93:13 | m1 | aliasing.cpp:92:12:92:21 | call to user_input [void] | aliasing.cpp:93:12:93:13 | m1 | m1 flows from $@ | aliasing.cpp:92:12:92:21 | call to user_input [void] | call to user_input [void] |
| complex.cpp:44:12:44:12 | call to a | complex.cpp:55:13:55:22 | call to user_input [void] | complex.cpp:44:12:44:12 | call to a | call to a flows from $@ | complex.cpp:55:13:55:22 | call to user_input [void] | call to user_input [void] |
| complex.cpp:44:12:44:12 | call to a | complex.cpp:56:13:56:22 | call to user_input [void] | complex.cpp:44:12:44:12 | call to a | call to a flows from $@ | complex.cpp:56:13:56:22 | call to user_input [void] | call to user_input [void] |
| complex.cpp:44:12:44:12 | call to a | complex.cpp:57:13:57:22 | call to user_input [void] | complex.cpp:44:12:44:12 | call to a | call to a flows from $@ | complex.cpp:57:13:57:22 | call to user_input [void] | call to user_input [void] |
| complex.cpp:44:12:44:12 | call to a | complex.cpp:58:13:58:22 | call to user_input [void] | complex.cpp:44:12:44:12 | call to a | call to a flows from $@ | complex.cpp:58:13:58:22 | call to user_input [void] | call to user_input [void] |
| complex.cpp:45:12:45:12 | call to b | complex.cpp:55:13:55:22 | call to user_input [void] | complex.cpp:45:12:45:12 | call to b | call to b flows from $@ | complex.cpp:55:13:55:22 | call to user_input [void] | call to user_input [void] |
| complex.cpp:45:12:45:12 | call to b | complex.cpp:56:13:56:22 | call to user_input [void] | complex.cpp:45:12:45:12 | call to b | call to b flows from $@ | complex.cpp:56:13:56:22 | call to user_input [void] | call to user_input [void] |
| complex.cpp:45:12:45:12 | call to b | complex.cpp:57:13:57:22 | call to user_input [void] | complex.cpp:45:12:45:12 | call to b | call to b flows from $@ | complex.cpp:57:13:57:22 | call to user_input [void] | call to user_input [void] |
| complex.cpp:45:12:45:12 | call to b | complex.cpp:58:13:58:22 | call to user_input [void] | complex.cpp:45:12:45:12 | call to b | call to b flows from $@ | complex.cpp:58:13:58:22 | call to user_input [void] | call to user_input [void] |
| constructors.cpp:28:12:28:12 | call to a | constructors.cpp:34:11:34:20 | call to user_input [void] | constructors.cpp:28:12:28:12 | call to a | call to a flows from $@ | constructors.cpp:34:11:34:20 | call to user_input [void] | call to user_input [void] |
| constructors.cpp:28:12:28:12 | call to a | constructors.cpp:36:11:36:20 | call to user_input [void] | constructors.cpp:28:12:28:12 | call to a | call to a flows from $@ | constructors.cpp:36:11:36:20 | call to user_input [void] | call to user_input [void] |
| constructors.cpp:29:12:29:12 | call to b | constructors.cpp:35:14:35:23 | call to user_input [void] | constructors.cpp:29:12:29:12 | call to b | call to b flows from $@ | constructors.cpp:35:14:35:23 | call to user_input [void] | call to user_input [void] |
| constructors.cpp:29:12:29:12 | call to b | constructors.cpp:36:25:36:34 | call to user_input [void] | constructors.cpp:29:12:29:12 | call to b | call to b flows from $@ | constructors.cpp:36:25:36:34 | call to user_input [void] | call to user_input [void] |
| simple.cpp:28:12:28:12 | call to a | simple.cpp:39:12:39:21 | call to user_input [void] | simple.cpp:28:12:28:12 | call to a | call to a flows from $@ | simple.cpp:39:12:39:21 | call to user_input [void] | call to user_input [void] |
| simple.cpp:28:12:28:12 | call to a | simple.cpp:41:12:41:21 | call to user_input [void] | simple.cpp:28:12:28:12 | call to a | call to a flows from $@ | simple.cpp:41:12:41:21 | call to user_input [void] | call to user_input [void] |
| simple.cpp:29:12:29:12 | call to b | simple.cpp:40:12:40:21 | call to user_input [void] | simple.cpp:29:12:29:12 | call to b | call to b flows from $@ | simple.cpp:40:12:40:21 | call to user_input [void] | call to user_input [void] |
| simple.cpp:29:12:29:12 | call to b | simple.cpp:42:12:42:21 | call to user_input [void] | simple.cpp:29:12:29:12 | call to b | call to b flows from $@ | simple.cpp:42:12:42:21 | call to user_input [void] | call to user_input [void] |
| struct_init.c:22:11:22:11 | a | struct_init.c:20:20:20:29 | call to user_input [void] | struct_init.c:22:11:22:11 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input [void] | call to user_input [void] |
| struct_init.c:31:23:31:23 | a | struct_init.c:27:7:27:16 | call to user_input [void] | struct_init.c:31:23:31:23 | a | a flows from $@ | struct_init.c:27:7:27:16 | call to user_input [void] | call to user_input [void] |
| A.cpp:43:10:43:12 | & ... | A.cpp:41:15:41:21 | new | A.cpp:43:10:43:12 | & ... | & ... flows from $@ | A.cpp:41:15:41:21 | new | new |
| A.cpp:49:13:49:13 | c | A.cpp:47:12:47:18 | new | A.cpp:49:13:49:13 | c | c flows from $@ | A.cpp:47:12:47:18 | new | new |
| A.cpp:56:13:56:15 | call to get | A.cpp:55:12:55:19 | new | A.cpp:56:13:56:15 | call to get | call to get flows from $@ | A.cpp:55:12:55:19 | new | new |
| A.cpp:57:28:57:30 | call to get | A.cpp:57:17:57:23 | new | A.cpp:57:28:57:30 | call to get | call to get flows from $@ | A.cpp:57:17:57:23 | new | new |
| A.cpp:66:14:66:14 | c | A.cpp:64:21:64:28 | new | A.cpp:66:14:66:14 | c | c flows from $@ | A.cpp:64:21:64:28 | new | new |
| A.cpp:75:14:75:14 | c | A.cpp:73:25:73:32 | new | A.cpp:75:14:75:14 | c | c flows from $@ | A.cpp:73:25:73:32 | new | new |
| A.cpp:107:16:107:16 | a | A.cpp:98:12:98:18 | new | A.cpp:107:16:107:16 | a | a flows from $@ | A.cpp:98:12:98:18 | new | new |
| A.cpp:120:16:120:16 | a | A.cpp:98:12:98:18 | new | A.cpp:120:16:120:16 | a | a flows from $@ | A.cpp:98:12:98:18 | new | new |
| A.cpp:132:13:132:13 | c | A.cpp:126:12:126:18 | new | A.cpp:132:13:132:13 | c | c flows from $@ | A.cpp:126:12:126:18 | new | new |
| A.cpp:152:13:152:13 | b | A.cpp:143:25:143:31 | new | A.cpp:152:13:152:13 | b | b flows from $@ | A.cpp:143:25:143:31 | new | new |
| A.cpp:152:13:152:13 | b | A.cpp:150:12:150:18 | new | A.cpp:152:13:152:13 | b | b flows from $@ | A.cpp:150:12:150:18 | new | new |
| A.cpp:153:16:153:16 | c | A.cpp:142:14:142:20 | new | A.cpp:153:16:153:16 | c | c flows from $@ | A.cpp:142:14:142:20 | new | new |
| A.cpp:154:13:154:13 | c | A.cpp:142:14:142:20 | new | A.cpp:154:13:154:13 | c | c flows from $@ | A.cpp:142:14:142:20 | new | new |
| A.cpp:165:26:165:29 | head | A.cpp:159:12:159:18 | new | A.cpp:165:26:165:29 | head | head flows from $@ | A.cpp:159:12:159:18 | new | new |
| A.cpp:169:15:169:18 | head | A.cpp:159:12:159:18 | new | A.cpp:169:15:169:18 | head | head flows from $@ | A.cpp:159:12:159:18 | new | new |
| B.cpp:9:20:9:24 | elem1 | B.cpp:6:15:6:24 | new | B.cpp:9:20:9:24 | elem1 | elem1 flows from $@ | B.cpp:6:15:6:24 | new | new |
| B.cpp:19:20:19:24 | elem2 | B.cpp:15:15:15:27 | new | B.cpp:19:20:19:24 | elem2 | elem2 flows from $@ | B.cpp:15:15:15:27 | new | new |
| C.cpp:29:10:29:11 | s1 | C.cpp:22:12:22:21 | new | C.cpp:29:10:29:11 | s1 | s1 flows from $@ | C.cpp:22:12:22:21 | new | new |
| C.cpp:31:10:31:11 | s3 | C.cpp:24:16:24:25 | new | C.cpp:31:10:31:11 | s3 | s3 flows from $@ | C.cpp:24:16:24:25 | new | new |
| aliasing.cpp:29:11:29:12 | m1 | aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:29:11:29:12 | m1 | m1 flows from $@ | aliasing.cpp:9:11:9:20 | call to user_input | call to user_input |
| aliasing.cpp:30:11:30:12 | m1 | aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:30:11:30:12 | m1 | m1 flows from $@ | aliasing.cpp:13:10:13:19 | call to user_input | call to user_input |
| aliasing.cpp:62:14:62:15 | m1 | aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:62:14:62:15 | m1 | m1 flows from $@ | aliasing.cpp:60:11:60:20 | call to user_input | call to user_input |
| aliasing.cpp:93:12:93:13 | m1 | aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:93:12:93:13 | m1 | m1 flows from $@ | aliasing.cpp:92:12:92:21 | call to user_input | call to user_input |
| complex.cpp:44:12:44:12 | call to a | complex.cpp:55:13:55:22 | call to user_input | complex.cpp:44:12:44:12 | call to a | call to a flows from $@ | complex.cpp:55:13:55:22 | call to user_input | call to user_input |
| complex.cpp:44:12:44:12 | call to a | complex.cpp:57:13:57:22 | call to user_input | complex.cpp:44:12:44:12 | call to a | call to a flows from $@ | complex.cpp:57:13:57:22 | call to user_input | call to user_input |
| complex.cpp:45:12:45:12 | call to b | complex.cpp:56:13:56:22 | call to user_input | complex.cpp:45:12:45:12 | call to b | call to b flows from $@ | complex.cpp:56:13:56:22 | call to user_input | call to user_input |
| complex.cpp:45:12:45:12 | call to b | complex.cpp:58:13:58:22 | call to user_input | complex.cpp:45:12:45:12 | call to b | call to b flows from $@ | complex.cpp:58:13:58:22 | call to user_input | call to user_input |
| constructors.cpp:28:12:28:12 | call to a | constructors.cpp:34:11:34:20 | call to user_input | constructors.cpp:28:12:28:12 | call to a | call to a flows from $@ | constructors.cpp:34:11:34:20 | call to user_input | call to user_input |
| constructors.cpp:28:12:28:12 | call to a | constructors.cpp:36:11:36:20 | call to user_input | constructors.cpp:28:12:28:12 | call to a | call to a flows from $@ | constructors.cpp:36:11:36:20 | call to user_input | call to user_input |
| constructors.cpp:29:12:29:12 | call to b | constructors.cpp:35:14:35:23 | call to user_input | constructors.cpp:29:12:29:12 | call to b | call to b flows from $@ | constructors.cpp:35:14:35:23 | call to user_input | call to user_input |
| constructors.cpp:29:12:29:12 | call to b | constructors.cpp:36:25:36:34 | call to user_input | constructors.cpp:29:12:29:12 | call to b | call to b flows from $@ | constructors.cpp:36:25:36:34 | call to user_input | call to user_input |
| simple.cpp:28:12:28:12 | call to a | simple.cpp:39:12:39:21 | call to user_input | simple.cpp:28:12:28:12 | call to a | call to a flows from $@ | simple.cpp:39:12:39:21 | call to user_input | call to user_input |
| simple.cpp:28:12:28:12 | call to a | simple.cpp:41:12:41:21 | call to user_input | simple.cpp:28:12:28:12 | call to a | call to a flows from $@ | simple.cpp:41:12:41:21 | call to user_input | call to user_input |
| simple.cpp:29:12:29:12 | call to b | simple.cpp:40:12:40:21 | call to user_input | simple.cpp:29:12:29:12 | call to b | call to b flows from $@ | simple.cpp:40:12:40:21 | call to user_input | call to user_input |
| simple.cpp:29:12:29:12 | call to b | simple.cpp:42:12:42:21 | call to user_input | simple.cpp:29:12:29:12 | call to b | call to b flows from $@ | simple.cpp:42:12:42:21 | call to user_input | call to user_input |
| struct_init.c:22:11:22:11 | a | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:22:11:22:11 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input | call to user_input |
| struct_init.c:31:23:31:23 | a | struct_init.c:27:7:27:16 | call to user_input | struct_init.c:31:23:31:23 | a | a flows from $@ | struct_init.c:27:7:27:16 | call to user_input | call to user_input |

View File

@@ -1,26 +1,26 @@
edges
| test.cpp:26:29:26:29 | b [void] | test.cpp:27:2:27:2 | b |
| test.cpp:30:34:30:34 | b [void] | test.cpp:31:2:31:2 | b |
| test.cpp:34:31:34:31 | b [void] | test.cpp:35:2:35:2 | b |
| test.cpp:50:31:50:31 | b [void] | test.cpp:51:11:51:11 | b |
| test.cpp:57:19:57:19 | d [void] | test.cpp:26:29:26:29 | b [void] |
| test.cpp:58:25:58:25 | d [void] | test.cpp:30:34:30:34 | b [void] |
| test.cpp:59:21:59:21 | d [void] | test.cpp:34:31:34:31 | b [void] |
| test.cpp:74:19:74:21 | dss [void] | test.cpp:26:29:26:29 | b [void] |
| test.cpp:75:25:75:27 | dss [void] | test.cpp:30:34:30:34 | b [void] |
| test.cpp:76:21:76:23 | dss [void] | test.cpp:34:31:34:31 | b [void] |
| test.cpp:86:19:86:20 | d2 [void] | test.cpp:26:29:26:29 | b [void] |
| test.cpp:87:25:87:26 | d2 [void] | test.cpp:30:34:30:34 | b [void] |
| test.cpp:88:21:88:22 | d2 [void] | test.cpp:34:31:34:31 | b [void] |
| test.cpp:95:21:95:21 | d [void] | test.cpp:50:31:50:31 | b [void] |
| test.cpp:96:21:96:23 | dss [void] | test.cpp:50:31:50:31 | b [void] |
| test.cpp:26:29:26:29 | b | test.cpp:27:2:27:2 | b |
| test.cpp:30:34:30:34 | b | test.cpp:31:2:31:2 | b |
| test.cpp:34:31:34:31 | b | test.cpp:35:2:35:2 | b |
| test.cpp:50:31:50:31 | b | test.cpp:51:11:51:11 | b |
| test.cpp:57:19:57:19 | d | test.cpp:26:29:26:29 | b |
| test.cpp:58:25:58:25 | d | test.cpp:30:34:30:34 | b |
| test.cpp:59:21:59:21 | d | test.cpp:34:31:34:31 | b |
| test.cpp:74:19:74:21 | dss | test.cpp:26:29:26:29 | b |
| test.cpp:75:25:75:27 | dss | test.cpp:30:34:30:34 | b |
| test.cpp:76:21:76:23 | dss | test.cpp:34:31:34:31 | b |
| test.cpp:86:19:86:20 | d2 | test.cpp:26:29:26:29 | b |
| test.cpp:87:25:87:26 | d2 | test.cpp:30:34:30:34 | b |
| test.cpp:88:21:88:22 | d2 | test.cpp:34:31:34:31 | b |
| test.cpp:95:21:95:21 | d | test.cpp:50:31:50:31 | b |
| test.cpp:96:21:96:23 | dss | test.cpp:50:31:50:31 | b |
#select
| test.cpp:27:2:27:2 | b | test.cpp:57:19:57:19 | d [void] | test.cpp:27:2:27:2 | b | Pointer arithmetic here may be done with the wrong type because of the cast $@. | test.cpp:57:19:57:19 | d [void] | here |
| test.cpp:27:2:27:2 | b | test.cpp:74:19:74:21 | dss [void] | test.cpp:27:2:27:2 | b | Pointer arithmetic here may be done with the wrong type because of the cast $@. | test.cpp:74:19:74:21 | dss [void] | here |
| test.cpp:27:2:27:2 | b | test.cpp:86:19:86:20 | d2 [void] | test.cpp:27:2:27:2 | b | Pointer arithmetic here may be done with the wrong type because of the cast $@. | test.cpp:86:19:86:20 | d2 [void] | here |
| test.cpp:31:2:31:2 | b | test.cpp:58:25:58:25 | d [void] | test.cpp:31:2:31:2 | b | Pointer arithmetic here may be done with the wrong type because of the cast $@. | test.cpp:58:25:58:25 | d [void] | here |
| test.cpp:31:2:31:2 | b | test.cpp:75:25:75:27 | dss [void] | test.cpp:31:2:31:2 | b | Pointer arithmetic here may be done with the wrong type because of the cast $@. | test.cpp:75:25:75:27 | dss [void] | here |
| test.cpp:31:2:31:2 | b | test.cpp:87:25:87:26 | d2 [void] | test.cpp:31:2:31:2 | b | Pointer arithmetic here may be done with the wrong type because of the cast $@. | test.cpp:87:25:87:26 | d2 [void] | here |
| test.cpp:35:2:35:2 | b | test.cpp:59:21:59:21 | d [void] | test.cpp:35:2:35:2 | b | Pointer arithmetic here may be done with the wrong type because of the cast $@. | test.cpp:59:21:59:21 | d [void] | here |
| test.cpp:35:2:35:2 | b | test.cpp:76:21:76:23 | dss [void] | test.cpp:35:2:35:2 | b | Pointer arithmetic here may be done with the wrong type because of the cast $@. | test.cpp:76:21:76:23 | dss [void] | here |
| test.cpp:35:2:35:2 | b | test.cpp:88:21:88:22 | d2 [void] | test.cpp:35:2:35:2 | b | Pointer arithmetic here may be done with the wrong type because of the cast $@. | test.cpp:88:21:88:22 | d2 [void] | here |
| test.cpp:27:2:27:2 | b | test.cpp:57:19:57:19 | d | test.cpp:27:2:27:2 | b | Pointer arithmetic here may be done with the wrong type because of the cast $@. | test.cpp:57:19:57:19 | d | here |
| test.cpp:27:2:27:2 | b | test.cpp:74:19:74:21 | dss | test.cpp:27:2:27:2 | b | Pointer arithmetic here may be done with the wrong type because of the cast $@. | test.cpp:74:19:74:21 | dss | here |
| test.cpp:27:2:27:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:27:2:27:2 | b | Pointer arithmetic here may be done with the wrong type because of the cast $@. | test.cpp:86:19:86:20 | d2 | here |
| test.cpp:31:2:31:2 | b | test.cpp:58:25:58:25 | d | test.cpp:31:2:31:2 | b | Pointer arithmetic here may be done with the wrong type because of the cast $@. | test.cpp:58:25:58:25 | d | here |
| test.cpp:31:2:31:2 | b | test.cpp:75:25:75:27 | dss | test.cpp:31:2:31:2 | b | Pointer arithmetic here may be done with the wrong type because of the cast $@. | test.cpp:75:25:75:27 | dss | here |
| test.cpp:31:2:31:2 | b | test.cpp:87:25:87:26 | d2 | test.cpp:31:2:31:2 | b | Pointer arithmetic here may be done with the wrong type because of the cast $@. | test.cpp:87:25:87:26 | d2 | here |
| test.cpp:35:2:35:2 | b | test.cpp:59:21:59:21 | d | test.cpp:35:2:35:2 | b | Pointer arithmetic here may be done with the wrong type because of the cast $@. | test.cpp:59:21:59:21 | d | here |
| test.cpp:35:2:35:2 | b | test.cpp:76:21:76:23 | dss | test.cpp:35:2:35:2 | b | Pointer arithmetic here may be done with the wrong type because of the cast $@. | test.cpp:76:21:76:23 | dss | here |
| test.cpp:35:2:35:2 | b | test.cpp:88:21:88:22 | d2 | test.cpp:35:2:35:2 | b | Pointer arithmetic here may be done with the wrong type because of the cast $@. | test.cpp:88:21:88:22 | d2 | here |

View File

@@ -1217,7 +1217,8 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
private newtype TAccessPath =
TNil(DataFlowType t) or
TCons(Content f, int len) { len in [1 .. 5] }
TConsNil(Content f, DataFlowType t) { consCand(f, TFrontNil(t), _) } or
TConsCons(Content f1, Content f2, int len) { consCand(f1, TFrontHead(f2), _) and len in [2 .. 5] }
/**
* Conceptually a list of `Content`s followed by a `Type`, but only the first
@@ -1226,52 +1227,93 @@ private newtype TAccessPath =
* 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 AccessPath extends TAccessPath {
abstract private class AccessPath extends TAccessPath {
abstract string toString();
Content getHead() { this = TCons(result, _) }
Content getHead() {
this = TConsNil(result, _)
or
this = TConsCons(result, _, _)
}
int len() {
this = TNil(_) and result = 0
or
this = TCons(_, result)
this = TConsNil(_, _) and result = 1
or
this = TConsCons(_, _, result)
}
DataFlowType getType() {
this = TNil(result)
or
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
result = this.getHead().getContainerType()
}
abstract AccessPathFront getFront();
/**
* Holds if this access path has `head` at the front and may be followed by `tail`.
*/
abstract predicate pop(Content head, AccessPath tail);
}
private class AccessPathNil extends AccessPath, TNil {
override string toString() { exists(DataFlowType t | this = TNil(t) | result = ppReprType(t)) }
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
}
override AccessPathFront getFront() {
exists(DataFlowType t | this = TNil(t) | result = TFrontNil(t))
}
override predicate pop(Content head, AccessPath tail) { none() }
}
private class AccessPathCons extends AccessPath, TCons {
abstract private class AccessPathCons extends AccessPath { }
private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, int len | this = TCons(f, len) |
result = f.toString() + ", ... (" + len.toString() + ")"
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
)
}
override AccessPathFront getFront() {
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
exists(Content f | this = TConsNil(f, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(DataFlowType t | this = TConsNil(head, t) and tail = TNil(t))
}
}
private class AccessPathConsCons extends AccessPathCons, TConsCons {
override string toString() {
exists(Content f1, Content f2, int len | this = TConsCons(f1, f2, len) |
if len = 2
then result = f1.toString() + ", " + f2.toString()
else result = f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")"
)
}
override AccessPathFront getFront() {
exists(Content f | this = TConsCons(f, _, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(int len, Content next | this = TConsCons(head, next, len) |
tail = TConsCons(next, _, len - 1)
or
len = 2 and
tail = TConsNil(next, _)
)
}
}
/** Holds if `ap0` corresponds to the cons of `f` and `ap`. */
private predicate pop(AccessPath ap0, Content f, AccessPath ap) {
ap0.getFront().headUsesContent(f) and
consCand(f, ap.getFront(), _) and
ap0.len() = 1 + ap.len()
}
private predicate pop(AccessPath ap0, Content f, AccessPath ap) { ap0.pop(f, ap) }
/** Holds if `ap0` corresponds to the cons of `f` and `ap` and `apf` is the front of `ap`. */
pragma[noinline]
@@ -2002,11 +2044,66 @@ 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 = concat(" : " + 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) |
if len = 1
then result = f.toString()
else 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
@@ -2016,7 +2113,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
@@ -2090,7 +2187,7 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
AccessPath ap;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2099,7 +2196,7 @@ private module FlowExploration {
CallContext getCallContext() { result = cc }
AccessPath getAp() { result = ap }
PartialAccessPath getAp() { result = ap }
override Configuration getConfiguration() { result = config }
@@ -2112,7 +2209,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
@@ -2121,8 +2218,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
@@ -2132,15 +2229,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)
)
@@ -2161,7 +2258,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
@@ -2171,7 +2268,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()
@@ -2180,7 +2279,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
@@ -2191,7 +2290,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
@@ -2203,8 +2302,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
@@ -2217,7 +2316,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)
@@ -2227,7 +2326,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(
@@ -2253,7 +2352,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
@@ -2262,16 +2361,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)
@@ -2279,7 +2378,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
@@ -2293,7 +2392,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
@@ -2313,9 +2413,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)
@@ -2323,7 +2423,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
@@ -2333,8 +2434,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
@@ -2343,7 +2444,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

View File

@@ -1217,7 +1217,8 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
private newtype TAccessPath =
TNil(DataFlowType t) or
TCons(Content f, int len) { len in [1 .. 5] }
TConsNil(Content f, DataFlowType t) { consCand(f, TFrontNil(t), _) } or
TConsCons(Content f1, Content f2, int len) { consCand(f1, TFrontHead(f2), _) and len in [2 .. 5] }
/**
* Conceptually a list of `Content`s followed by a `Type`, but only the first
@@ -1226,52 +1227,93 @@ private newtype TAccessPath =
* 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 AccessPath extends TAccessPath {
abstract private class AccessPath extends TAccessPath {
abstract string toString();
Content getHead() { this = TCons(result, _) }
Content getHead() {
this = TConsNil(result, _)
or
this = TConsCons(result, _, _)
}
int len() {
this = TNil(_) and result = 0
or
this = TCons(_, result)
this = TConsNil(_, _) and result = 1
or
this = TConsCons(_, _, result)
}
DataFlowType getType() {
this = TNil(result)
or
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
result = this.getHead().getContainerType()
}
abstract AccessPathFront getFront();
/**
* Holds if this access path has `head` at the front and may be followed by `tail`.
*/
abstract predicate pop(Content head, AccessPath tail);
}
private class AccessPathNil extends AccessPath, TNil {
override string toString() { exists(DataFlowType t | this = TNil(t) | result = ppReprType(t)) }
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
}
override AccessPathFront getFront() {
exists(DataFlowType t | this = TNil(t) | result = TFrontNil(t))
}
override predicate pop(Content head, AccessPath tail) { none() }
}
private class AccessPathCons extends AccessPath, TCons {
abstract private class AccessPathCons extends AccessPath { }
private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, int len | this = TCons(f, len) |
result = f.toString() + ", ... (" + len.toString() + ")"
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
)
}
override AccessPathFront getFront() {
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
exists(Content f | this = TConsNil(f, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(DataFlowType t | this = TConsNil(head, t) and tail = TNil(t))
}
}
private class AccessPathConsCons extends AccessPathCons, TConsCons {
override string toString() {
exists(Content f1, Content f2, int len | this = TConsCons(f1, f2, len) |
if len = 2
then result = f1.toString() + ", " + f2.toString()
else result = f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")"
)
}
override AccessPathFront getFront() {
exists(Content f | this = TConsCons(f, _, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(int len, Content next | this = TConsCons(head, next, len) |
tail = TConsCons(next, _, len - 1)
or
len = 2 and
tail = TConsNil(next, _)
)
}
}
/** Holds if `ap0` corresponds to the cons of `f` and `ap`. */
private predicate pop(AccessPath ap0, Content f, AccessPath ap) {
ap0.getFront().headUsesContent(f) and
consCand(f, ap.getFront(), _) and
ap0.len() = 1 + ap.len()
}
private predicate pop(AccessPath ap0, Content f, AccessPath ap) { ap0.pop(f, ap) }
/** Holds if `ap0` corresponds to the cons of `f` and `ap` and `apf` is the front of `ap`. */
pragma[noinline]
@@ -2002,11 +2044,66 @@ 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 = concat(" : " + 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) |
if len = 1
then result = f.toString()
else 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
@@ -2016,7 +2113,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
@@ -2090,7 +2187,7 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
AccessPath ap;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2099,7 +2196,7 @@ private module FlowExploration {
CallContext getCallContext() { result = cc }
AccessPath getAp() { result = ap }
PartialAccessPath getAp() { result = ap }
override Configuration getConfiguration() { result = config }
@@ -2112,7 +2209,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
@@ -2121,8 +2218,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
@@ -2132,15 +2229,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)
)
@@ -2161,7 +2258,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
@@ -2171,7 +2268,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()
@@ -2180,7 +2279,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
@@ -2191,7 +2290,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
@@ -2203,8 +2302,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
@@ -2217,7 +2316,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)
@@ -2227,7 +2326,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(
@@ -2253,7 +2352,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
@@ -2262,16 +2361,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)
@@ -2279,7 +2378,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
@@ -2293,7 +2392,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
@@ -2313,9 +2413,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)
@@ -2323,7 +2423,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
@@ -2333,8 +2434,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
@@ -2343,7 +2444,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

View File

@@ -1217,7 +1217,8 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
private newtype TAccessPath =
TNil(DataFlowType t) or
TCons(Content f, int len) { len in [1 .. 5] }
TConsNil(Content f, DataFlowType t) { consCand(f, TFrontNil(t), _) } or
TConsCons(Content f1, Content f2, int len) { consCand(f1, TFrontHead(f2), _) and len in [2 .. 5] }
/**
* Conceptually a list of `Content`s followed by a `Type`, but only the first
@@ -1226,52 +1227,93 @@ private newtype TAccessPath =
* 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 AccessPath extends TAccessPath {
abstract private class AccessPath extends TAccessPath {
abstract string toString();
Content getHead() { this = TCons(result, _) }
Content getHead() {
this = TConsNil(result, _)
or
this = TConsCons(result, _, _)
}
int len() {
this = TNil(_) and result = 0
or
this = TCons(_, result)
this = TConsNil(_, _) and result = 1
or
this = TConsCons(_, _, result)
}
DataFlowType getType() {
this = TNil(result)
or
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
result = this.getHead().getContainerType()
}
abstract AccessPathFront getFront();
/**
* Holds if this access path has `head` at the front and may be followed by `tail`.
*/
abstract predicate pop(Content head, AccessPath tail);
}
private class AccessPathNil extends AccessPath, TNil {
override string toString() { exists(DataFlowType t | this = TNil(t) | result = ppReprType(t)) }
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
}
override AccessPathFront getFront() {
exists(DataFlowType t | this = TNil(t) | result = TFrontNil(t))
}
override predicate pop(Content head, AccessPath tail) { none() }
}
private class AccessPathCons extends AccessPath, TCons {
abstract private class AccessPathCons extends AccessPath { }
private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, int len | this = TCons(f, len) |
result = f.toString() + ", ... (" + len.toString() + ")"
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
)
}
override AccessPathFront getFront() {
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
exists(Content f | this = TConsNil(f, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(DataFlowType t | this = TConsNil(head, t) and tail = TNil(t))
}
}
private class AccessPathConsCons extends AccessPathCons, TConsCons {
override string toString() {
exists(Content f1, Content f2, int len | this = TConsCons(f1, f2, len) |
if len = 2
then result = f1.toString() + ", " + f2.toString()
else result = f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")"
)
}
override AccessPathFront getFront() {
exists(Content f | this = TConsCons(f, _, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(int len, Content next | this = TConsCons(head, next, len) |
tail = TConsCons(next, _, len - 1)
or
len = 2 and
tail = TConsNil(next, _)
)
}
}
/** Holds if `ap0` corresponds to the cons of `f` and `ap`. */
private predicate pop(AccessPath ap0, Content f, AccessPath ap) {
ap0.getFront().headUsesContent(f) and
consCand(f, ap.getFront(), _) and
ap0.len() = 1 + ap.len()
}
private predicate pop(AccessPath ap0, Content f, AccessPath ap) { ap0.pop(f, ap) }
/** Holds if `ap0` corresponds to the cons of `f` and `ap` and `apf` is the front of `ap`. */
pragma[noinline]
@@ -2002,11 +2044,66 @@ 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 = concat(" : " + 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) |
if len = 1
then result = f.toString()
else 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
@@ -2016,7 +2113,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
@@ -2090,7 +2187,7 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
AccessPath ap;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2099,7 +2196,7 @@ private module FlowExploration {
CallContext getCallContext() { result = cc }
AccessPath getAp() { result = ap }
PartialAccessPath getAp() { result = ap }
override Configuration getConfiguration() { result = config }
@@ -2112,7 +2209,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
@@ -2121,8 +2218,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
@@ -2132,15 +2229,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)
)
@@ -2161,7 +2258,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
@@ -2171,7 +2268,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()
@@ -2180,7 +2279,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
@@ -2191,7 +2290,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
@@ -2203,8 +2302,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
@@ -2217,7 +2316,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)
@@ -2227,7 +2326,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(
@@ -2253,7 +2352,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
@@ -2262,16 +2361,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)
@@ -2279,7 +2378,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
@@ -2293,7 +2392,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
@@ -2313,9 +2413,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)
@@ -2323,7 +2423,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
@@ -2333,8 +2434,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
@@ -2343,7 +2444,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

View File

@@ -1217,7 +1217,8 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
private newtype TAccessPath =
TNil(DataFlowType t) or
TCons(Content f, int len) { len in [1 .. 5] }
TConsNil(Content f, DataFlowType t) { consCand(f, TFrontNil(t), _) } or
TConsCons(Content f1, Content f2, int len) { consCand(f1, TFrontHead(f2), _) and len in [2 .. 5] }
/**
* Conceptually a list of `Content`s followed by a `Type`, but only the first
@@ -1226,52 +1227,93 @@ private newtype TAccessPath =
* 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 AccessPath extends TAccessPath {
abstract private class AccessPath extends TAccessPath {
abstract string toString();
Content getHead() { this = TCons(result, _) }
Content getHead() {
this = TConsNil(result, _)
or
this = TConsCons(result, _, _)
}
int len() {
this = TNil(_) and result = 0
or
this = TCons(_, result)
this = TConsNil(_, _) and result = 1
or
this = TConsCons(_, _, result)
}
DataFlowType getType() {
this = TNil(result)
or
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
result = this.getHead().getContainerType()
}
abstract AccessPathFront getFront();
/**
* Holds if this access path has `head` at the front and may be followed by `tail`.
*/
abstract predicate pop(Content head, AccessPath tail);
}
private class AccessPathNil extends AccessPath, TNil {
override string toString() { exists(DataFlowType t | this = TNil(t) | result = ppReprType(t)) }
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
}
override AccessPathFront getFront() {
exists(DataFlowType t | this = TNil(t) | result = TFrontNil(t))
}
override predicate pop(Content head, AccessPath tail) { none() }
}
private class AccessPathCons extends AccessPath, TCons {
abstract private class AccessPathCons extends AccessPath { }
private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, int len | this = TCons(f, len) |
result = f.toString() + ", ... (" + len.toString() + ")"
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
)
}
override AccessPathFront getFront() {
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
exists(Content f | this = TConsNil(f, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(DataFlowType t | this = TConsNil(head, t) and tail = TNil(t))
}
}
private class AccessPathConsCons extends AccessPathCons, TConsCons {
override string toString() {
exists(Content f1, Content f2, int len | this = TConsCons(f1, f2, len) |
if len = 2
then result = f1.toString() + ", " + f2.toString()
else result = f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")"
)
}
override AccessPathFront getFront() {
exists(Content f | this = TConsCons(f, _, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(int len, Content next | this = TConsCons(head, next, len) |
tail = TConsCons(next, _, len - 1)
or
len = 2 and
tail = TConsNil(next, _)
)
}
}
/** Holds if `ap0` corresponds to the cons of `f` and `ap`. */
private predicate pop(AccessPath ap0, Content f, AccessPath ap) {
ap0.getFront().headUsesContent(f) and
consCand(f, ap.getFront(), _) and
ap0.len() = 1 + ap.len()
}
private predicate pop(AccessPath ap0, Content f, AccessPath ap) { ap0.pop(f, ap) }
/** Holds if `ap0` corresponds to the cons of `f` and `ap` and `apf` is the front of `ap`. */
pragma[noinline]
@@ -2002,11 +2044,66 @@ 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 = concat(" : " + 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) |
if len = 1
then result = f.toString()
else 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
@@ -2016,7 +2113,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
@@ -2090,7 +2187,7 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
AccessPath ap;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2099,7 +2196,7 @@ private module FlowExploration {
CallContext getCallContext() { result = cc }
AccessPath getAp() { result = ap }
PartialAccessPath getAp() { result = ap }
override Configuration getConfiguration() { result = config }
@@ -2112,7 +2209,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
@@ -2121,8 +2218,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
@@ -2132,15 +2229,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)
)
@@ -2161,7 +2258,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
@@ -2171,7 +2268,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()
@@ -2180,7 +2279,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
@@ -2191,7 +2290,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
@@ -2203,8 +2302,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
@@ -2217,7 +2316,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)
@@ -2227,7 +2326,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(
@@ -2253,7 +2352,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
@@ -2262,16 +2361,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)
@@ -2279,7 +2378,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
@@ -2293,7 +2392,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
@@ -2313,9 +2413,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)
@@ -2323,7 +2423,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
@@ -2333,8 +2434,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
@@ -2343,7 +2444,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

View File

@@ -1217,7 +1217,8 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
private newtype TAccessPath =
TNil(DataFlowType t) or
TCons(Content f, int len) { len in [1 .. 5] }
TConsNil(Content f, DataFlowType t) { consCand(f, TFrontNil(t), _) } or
TConsCons(Content f1, Content f2, int len) { consCand(f1, TFrontHead(f2), _) and len in [2 .. 5] }
/**
* Conceptually a list of `Content`s followed by a `Type`, but only the first
@@ -1226,52 +1227,93 @@ private newtype TAccessPath =
* 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 AccessPath extends TAccessPath {
abstract private class AccessPath extends TAccessPath {
abstract string toString();
Content getHead() { this = TCons(result, _) }
Content getHead() {
this = TConsNil(result, _)
or
this = TConsCons(result, _, _)
}
int len() {
this = TNil(_) and result = 0
or
this = TCons(_, result)
this = TConsNil(_, _) and result = 1
or
this = TConsCons(_, _, result)
}
DataFlowType getType() {
this = TNil(result)
or
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
result = this.getHead().getContainerType()
}
abstract AccessPathFront getFront();
/**
* Holds if this access path has `head` at the front and may be followed by `tail`.
*/
abstract predicate pop(Content head, AccessPath tail);
}
private class AccessPathNil extends AccessPath, TNil {
override string toString() { exists(DataFlowType t | this = TNil(t) | result = ppReprType(t)) }
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
}
override AccessPathFront getFront() {
exists(DataFlowType t | this = TNil(t) | result = TFrontNil(t))
}
override predicate pop(Content head, AccessPath tail) { none() }
}
private class AccessPathCons extends AccessPath, TCons {
abstract private class AccessPathCons extends AccessPath { }
private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, int len | this = TCons(f, len) |
result = f.toString() + ", ... (" + len.toString() + ")"
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
)
}
override AccessPathFront getFront() {
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
exists(Content f | this = TConsNil(f, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(DataFlowType t | this = TConsNil(head, t) and tail = TNil(t))
}
}
private class AccessPathConsCons extends AccessPathCons, TConsCons {
override string toString() {
exists(Content f1, Content f2, int len | this = TConsCons(f1, f2, len) |
if len = 2
then result = f1.toString() + ", " + f2.toString()
else result = f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")"
)
}
override AccessPathFront getFront() {
exists(Content f | this = TConsCons(f, _, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(int len, Content next | this = TConsCons(head, next, len) |
tail = TConsCons(next, _, len - 1)
or
len = 2 and
tail = TConsNil(next, _)
)
}
}
/** Holds if `ap0` corresponds to the cons of `f` and `ap`. */
private predicate pop(AccessPath ap0, Content f, AccessPath ap) {
ap0.getFront().headUsesContent(f) and
consCand(f, ap.getFront(), _) and
ap0.len() = 1 + ap.len()
}
private predicate pop(AccessPath ap0, Content f, AccessPath ap) { ap0.pop(f, ap) }
/** Holds if `ap0` corresponds to the cons of `f` and `ap` and `apf` is the front of `ap`. */
pragma[noinline]
@@ -2002,11 +2044,66 @@ 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 = concat(" : " + 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) |
if len = 1
then result = f.toString()
else 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
@@ -2016,7 +2113,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
@@ -2090,7 +2187,7 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
AccessPath ap;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2099,7 +2196,7 @@ private module FlowExploration {
CallContext getCallContext() { result = cc }
AccessPath getAp() { result = ap }
PartialAccessPath getAp() { result = ap }
override Configuration getConfiguration() { result = config }
@@ -2112,7 +2209,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
@@ -2121,8 +2218,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
@@ -2132,15 +2229,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)
)
@@ -2161,7 +2258,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
@@ -2171,7 +2268,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()
@@ -2180,7 +2279,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
@@ -2191,7 +2290,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
@@ -2203,8 +2302,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
@@ -2217,7 +2316,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)
@@ -2227,7 +2326,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(
@@ -2253,7 +2352,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
@@ -2262,16 +2361,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)
@@ -2279,7 +2378,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
@@ -2293,7 +2392,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
@@ -2313,9 +2413,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)
@@ -2323,7 +2423,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
@@ -2333,8 +2434,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
@@ -2343,7 +2444,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

View File

@@ -1248,8 +1248,7 @@ DotNet::Type getErasedRepr(DotNet::Type t) {
}
/** Gets a string representation of a type returned by `getErasedRepr`. */
bindingset[t]
string ppReprType(DotNet::Type t) { suppressUnusedType(t) and result = "" } // stub implementation
string ppReprType(DotNet::Type t) { none() } // stub implementation
/**
* Holds if `t1` and `t2` are compatible, that is, whether data can flow from

View File

@@ -6,7 +6,7 @@ public class B
var b1 = new Box1(e, null);
var b2 = new Box2(b1);
Sink(b2.box1.elem1); // flow
Sink(b2.box1.elem2); // FP due to flow in M2 below
Sink(b2.box1.elem2); // no flow
}
public void M2()
@@ -14,7 +14,7 @@ public class B
var e = new Elem();
var b1 = new Box1(null, e);
var b2 = new Box2(b1);
Sink(b2.box1.elem1); // FP due to flow in M1 above
Sink(b2.box1.elem1); // no flow
Sink(b2.box1.elem2); // flow
}

View File

@@ -1,184 +1,178 @@
edges
| A.cs:5:17:5:23 | object creation of type C | A.cs:6:24:6:24 | access to local variable c |
| A.cs:6:17:6:25 | call to method Make [c, ... (1)] | A.cs:7:14:7:14 | access to local variable b [c, ... (1)] |
| A.cs:6:24:6:24 | access to local variable c | A.cs:6:17:6:25 | call to method Make [c, ... (1)] |
| A.cs:7:14:7:14 | access to local variable b [c, ... (1)] | A.cs:7:14:7:16 | access to field c |
| A.cs:13:9:13:9 | [post] access to local variable b [c, ... (1)] | A.cs:14:14:14:14 | access to local variable b [c, ... (1)] |
| A.cs:13:15:13:22 | object creation of type C1 | A.cs:13:9:13:9 | [post] access to local variable b [c, ... (1)] |
| A.cs:14:14:14:14 | access to local variable b [c, ... (1)] | A.cs:14:14:14:20 | call to method Get |
| A.cs:15:15:15:28 | object creation of type B [c, ... (1)] | A.cs:15:14:15:35 | call to method Get |
| A.cs:15:21:15:27 | object creation of type C | A.cs:15:15:15:28 | object creation of type B [c, ... (1)] |
| A.cs:22:14:22:33 | call to method SetOnB [c, ... (1)] | A.cs:24:14:24:15 | access to local variable b2 [c, ... (1)] |
| A.cs:22:25:22:32 | object creation of type C2 | A.cs:22:14:22:33 | call to method SetOnB [c, ... (1)] |
| A.cs:24:14:24:15 | access to local variable b2 [c, ... (1)] | A.cs:24:14:24:17 | access to field c |
| A.cs:31:14:31:37 | call to method SetOnBWrap [c, ... (1)] | A.cs:33:14:33:15 | access to local variable b2 [c, ... (1)] |
| A.cs:31:29:31:36 | object creation of type C2 | A.cs:31:14:31:37 | call to method SetOnBWrap [c, ... (1)] |
| A.cs:33:14:33:15 | access to local variable b2 [c, ... (1)] | A.cs:33:14:33:17 | access to field c |
| A.cs:6:17:6:25 | call to method Make [c] | A.cs:7:14:7:14 | access to local variable b [c] |
| A.cs:6:24:6:24 | access to local variable c | A.cs:6:17:6:25 | call to method Make [c] |
| A.cs:7:14:7:14 | access to local variable b [c] | A.cs:7:14:7:16 | access to field c |
| A.cs:13:9:13:9 | [post] access to local variable b [c] | A.cs:14:14:14:14 | access to local variable b [c] |
| A.cs:13:15:13:22 | object creation of type C1 | A.cs:13:9:13:9 | [post] access to local variable b [c] |
| A.cs:14:14:14:14 | access to local variable b [c] | A.cs:14:14:14:20 | call to method Get |
| A.cs:15:15:15:28 | object creation of type B [c] | A.cs:15:14:15:35 | call to method Get |
| A.cs:15:21:15:27 | object creation of type C | A.cs:15:15:15:28 | object creation of type B [c] |
| A.cs:22:14:22:33 | call to method SetOnB [c] | A.cs:24:14:24:15 | access to local variable b2 [c] |
| A.cs:22:25:22:32 | object creation of type C2 | A.cs:22:14:22:33 | call to method SetOnB [c] |
| A.cs:24:14:24:15 | access to local variable b2 [c] | A.cs:24:14:24:17 | access to field c |
| A.cs:31:14:31:37 | call to method SetOnBWrap [c] | A.cs:33:14:33:15 | access to local variable b2 [c] |
| A.cs:31:29:31:36 | object creation of type C2 | A.cs:31:14:31:37 | call to method SetOnBWrap [c] |
| A.cs:33:14:33:15 | access to local variable b2 [c] | A.cs:33:14:33:17 | access to field c |
| A.cs:55:17:55:23 | object creation of type A | A.cs:57:16:57:16 | access to local variable a |
| A.cs:57:9:57:10 | [post] access to local variable c1 [a, ... (1)] | A.cs:58:12:58:13 | access to local variable c1 [a, ... (1)] |
| A.cs:57:16:57:16 | access to local variable a | A.cs:57:9:57:10 | [post] access to local variable c1 [a, ... (1)] |
| A.cs:58:12:58:13 | access to local variable c1 [a, ... (1)] | A.cs:60:22:60:22 | c [a, ... (1)] |
| A.cs:60:22:60:22 | c [a, ... (1)] | A.cs:64:19:64:23 | (...) ... [a, ... (1)] |
| A.cs:60:22:60:22 | c [a, ... (1)] | A.cs:69:18:69:22 | (...) ... [a, ... (1)] |
| A.cs:64:19:64:23 | (...) ... [a, ... (1)] | A.cs:64:18:64:26 | access to field a |
| A.cs:69:18:69:22 | (...) ... [a, ... (1)] | A.cs:77:19:77:24 | (...) ... [a, ... (1)] |
| A.cs:77:19:77:24 | (...) ... [a, ... (1)] | A.cs:77:18:77:27 | access to field a |
| A.cs:83:9:83:9 | [post] access to parameter b [c, ... (1)] | A.cs:88:12:88:12 | [post] access to local variable b [c, ... (1)] |
| A.cs:83:15:83:21 | object creation of type C | A.cs:83:9:83:9 | [post] access to parameter b [c, ... (1)] |
| A.cs:88:12:88:12 | [post] access to local variable b [c, ... (1)] | A.cs:89:14:89:14 | access to local variable b [c, ... (1)] |
| A.cs:89:14:89:14 | access to local variable b [c, ... (1)] | A.cs:89:14:89:16 | access to field c |
| A.cs:97:13:97:13 | [post] access to parameter b [c, ... (1)] | A.cs:98:22:98:36 | ... ? ... : ... [c, ... (1)] |
| A.cs:97:13:97:13 | [post] access to parameter b [c, ... (1)] | A.cs:105:23:105:23 | [post] access to local variable b [c, ... (1)] |
| A.cs:97:19:97:25 | object creation of type C | A.cs:97:13:97:13 | [post] access to parameter b [c, ... (1)] |
| A.cs:98:13:98:16 | [post] this access [b, ... (1)] | A.cs:105:17:105:29 | object creation of type D [b, ... (1)] |
| A.cs:98:13:98:16 | [post] this access [b, ... (2)] | A.cs:105:17:105:29 | object creation of type D [b, ... (2)] |
| A.cs:98:22:98:36 | ... ? ... : ... | A.cs:98:13:98:16 | [post] this access [b, ... (1)] |
| A.cs:98:22:98:36 | ... ? ... : ... [c, ... (1)] | A.cs:98:13:98:16 | [post] this access [b, ... (2)] |
| A.cs:57:9:57:10 | [post] access to local variable c1 [a] | A.cs:58:12:58:13 | access to local variable c1 [a] |
| A.cs:57:16:57:16 | access to local variable a | A.cs:57:9:57:10 | [post] access to local variable c1 [a] |
| A.cs:58:12:58:13 | access to local variable c1 [a] | A.cs:60:22:60:22 | c [a] |
| A.cs:60:22:60:22 | c [a] | A.cs:64:19:64:23 | (...) ... [a] |
| A.cs:60:22:60:22 | c [a] | A.cs:69:18:69:22 | (...) ... [a] |
| A.cs:64:19:64:23 | (...) ... [a] | A.cs:64:18:64:26 | access to field a |
| A.cs:69:18:69:22 | (...) ... [a] | A.cs:77:19:77:24 | (...) ... [a] |
| A.cs:77:19:77:24 | (...) ... [a] | A.cs:77:18:77:27 | access to field a |
| A.cs:83:9:83:9 | [post] access to parameter b [c] | A.cs:88:12:88:12 | [post] access to local variable b [c] |
| A.cs:83:15:83:21 | object creation of type C | A.cs:83:9:83:9 | [post] access to parameter b [c] |
| A.cs:88:12:88:12 | [post] access to local variable b [c] | A.cs:89:14:89:14 | access to local variable b [c] |
| A.cs:89:14:89:14 | access to local variable b [c] | A.cs:89:14:89:16 | access to field c |
| A.cs:97:13:97:13 | [post] access to parameter b [c] | A.cs:98:22:98:36 | ... ? ... : ... [c] |
| A.cs:97:13:97:13 | [post] access to parameter b [c] | A.cs:105:23:105:23 | [post] access to local variable b [c] |
| A.cs:97:19:97:25 | object creation of type C | A.cs:97:13:97:13 | [post] access to parameter b [c] |
| A.cs:98:13:98:16 | [post] this access [b, c] | A.cs:105:17:105:29 | object creation of type D [b, c] |
| A.cs:98:13:98:16 | [post] this access [b] | A.cs:105:17:105:29 | object creation of type D [b] |
| A.cs:98:22:98:36 | ... ? ... : ... | A.cs:98:13:98:16 | [post] this access [b] |
| A.cs:98:22:98:36 | ... ? ... : ... [c] | A.cs:98:13:98:16 | [post] this access [b, c] |
| A.cs:98:30:98:36 | object creation of type B | A.cs:98:22:98:36 | ... ? ... : ... |
| A.cs:104:17:104:23 | object creation of type B | A.cs:105:23:105:23 | access to local variable b |
| A.cs:105:17:105:29 | object creation of type D [b, ... (1)] | A.cs:106:14:106:14 | access to local variable d [b, ... (1)] |
| A.cs:105:17:105:29 | object creation of type D [b, ... (2)] | A.cs:107:14:107:14 | access to local variable d [b, ... (2)] |
| A.cs:105:23:105:23 | [post] access to local variable b [c, ... (1)] | A.cs:108:14:108:14 | access to local variable b [c, ... (1)] |
| A.cs:105:23:105:23 | access to local variable b | A.cs:105:17:105:29 | object creation of type D [b, ... (1)] |
| A.cs:106:14:106:14 | access to local variable d [b, ... (1)] | A.cs:106:14:106:16 | access to field b |
| A.cs:107:14:107:14 | access to local variable d [b, ... (2)] | A.cs:107:14:107:16 | access to field b [c, ... (1)] |
| A.cs:107:14:107:16 | access to field b [c, ... (1)] | A.cs:107:14:107:18 | access to field c |
| A.cs:108:14:108:14 | access to local variable b [c, ... (1)] | A.cs:108:14:108:16 | access to field c |
| A.cs:105:17:105:29 | object creation of type D [b, c] | A.cs:107:14:107:14 | access to local variable d [b, c] |
| A.cs:105:17:105:29 | object creation of type D [b] | A.cs:106:14:106:14 | access to local variable d [b] |
| A.cs:105:23:105:23 | [post] access to local variable b [c] | A.cs:108:14:108:14 | access to local variable b [c] |
| A.cs:105:23:105:23 | access to local variable b | A.cs:105:17:105:29 | object creation of type D [b] |
| A.cs:106:14:106:14 | access to local variable d [b] | A.cs:106:14:106:16 | access to field b |
| A.cs:107:14:107:14 | access to local variable d [b, c] | A.cs:107:14:107:16 | access to field b [c] |
| A.cs:107:14:107:16 | access to field b [c] | A.cs:107:14:107:18 | access to field c |
| A.cs:108:14:108:14 | access to local variable b [c] | A.cs:108:14:108:16 | access to field c |
| A.cs:113:17:113:23 | object creation of type B | A.cs:114:29:114:29 | access to local variable b |
| A.cs:114:18:114:54 | object creation of type MyList [head, ... (1)] | A.cs:115:35:115:36 | access to local variable l1 [head, ... (1)] |
| A.cs:114:29:114:29 | access to local variable b | A.cs:114:18:114:54 | object creation of type MyList [head, ... (1)] |
| A.cs:115:18:115:37 | object creation of type MyList [next, ... (2)] | A.cs:116:35:116:36 | access to local variable l2 [next, ... (2)] |
| A.cs:115:35:115:36 | access to local variable l1 [head, ... (1)] | A.cs:115:18:115:37 | object creation of type MyList [next, ... (2)] |
| A.cs:116:18:116:37 | object creation of type MyList [next, ... (3)] | A.cs:119:14:119:15 | access to local variable l3 [next, ... (3)] |
| A.cs:116:18:116:37 | object creation of type MyList [next, ... (3)] | A.cs:121:41:121:41 | access to local variable l [next, ... (3)] |
| A.cs:116:35:116:36 | access to local variable l2 [next, ... (2)] | A.cs:116:18:116:37 | object creation of type MyList [next, ... (3)] |
| A.cs:119:14:119:15 | access to local variable l3 [next, ... (3)] | A.cs:119:14:119:20 | access to field next [next, ... (2)] |
| A.cs:119:14:119:20 | access to field next [next, ... (2)] | A.cs:119:14:119:25 | access to field next [head, ... (1)] |
| A.cs:119:14:119:25 | access to field next [head, ... (1)] | A.cs:119:14:119:30 | access to field head |
| A.cs:121:41:121:41 | access to local variable l [next, ... (2)] | A.cs:121:41:121:46 | access to field next [head, ... (1)] |
| A.cs:121:41:121:41 | access to local variable l [next, ... (3)] | A.cs:121:41:121:46 | access to field next [next, ... (2)] |
| A.cs:121:41:121:46 | access to field next [head, ... (1)] | A.cs:123:18:123:18 | access to local variable l [head, ... (1)] |
| A.cs:121:41:121:46 | access to field next [next, ... (2)] | A.cs:121:41:121:41 | access to local variable l [next, ... (2)] |
| A.cs:123:18:123:18 | access to local variable l [head, ... (1)] | A.cs:123:18:123:23 | access to field head |
| A.cs:114:18:114:54 | object creation of type MyList [head] | A.cs:115:35:115:36 | access to local variable l1 [head] |
| A.cs:114:29:114:29 | access to local variable b | A.cs:114:18:114:54 | object creation of type MyList [head] |
| A.cs:115:18:115:37 | object creation of type MyList [next, head] | A.cs:116:35:116:36 | access to local variable l2 [next, head] |
| A.cs:115:35:115:36 | access to local variable l1 [head] | A.cs:115:18:115:37 | object creation of type MyList [next, head] |
| A.cs:116:18:116:37 | object creation of type MyList [next, next, ... (3)] | A.cs:119:14:119:15 | access to local variable l3 [next, next, ... (3)] |
| A.cs:116:18:116:37 | object creation of type MyList [next, next, ... (3)] | A.cs:121:41:121:41 | access to local variable l [next, next, ... (3)] |
| A.cs:116:35:116:36 | access to local variable l2 [next, head] | A.cs:116:18:116:37 | object creation of type MyList [next, next, ... (3)] |
| A.cs:119:14:119:15 | access to local variable l3 [next, next, ... (3)] | A.cs:119:14:119:20 | access to field next [next, head] |
| A.cs:119:14:119:20 | access to field next [next, head] | A.cs:119:14:119:25 | access to field next [head] |
| A.cs:119:14:119:25 | access to field next [head] | A.cs:119:14:119:30 | access to field head |
| A.cs:121:41:121:41 | access to local variable l [next, head] | A.cs:121:41:121:46 | access to field next [head] |
| A.cs:121:41:121:41 | access to local variable l [next, next, ... (3)] | A.cs:121:41:121:46 | access to field next [next, head] |
| A.cs:121:41:121:46 | access to field next [head] | A.cs:123:18:123:18 | access to local variable l [head] |
| A.cs:121:41:121:46 | access to field next [next, head] | A.cs:121:41:121:41 | access to local variable l [next, head] |
| A.cs:123:18:123:18 | access to local variable l [head] | A.cs:123:18:123:23 | access to field head |
| B.cs:5:17:5:26 | object creation of type Elem | B.cs:6:27:6:27 | access to local variable e |
| B.cs:6:18:6:34 | object creation of type Box1 [elem1, ... (1)] | B.cs:7:27:7:28 | access to local variable b1 [elem1, ... (1)] |
| B.cs:6:27:6:27 | access to local variable e | B.cs:6:18:6:34 | object creation of type Box1 [elem1, ... (1)] |
| B.cs:7:18:7:29 | object creation of type Box2 [box1, ... (2)] | B.cs:8:14:8:15 | access to local variable b2 [box1, ... (2)] |
| B.cs:7:18:7:29 | object creation of type Box2 [box1, ... (2)] | B.cs:9:14:9:15 | access to local variable b2 [box1, ... (2)] |
| B.cs:7:27:7:28 | access to local variable b1 [elem1, ... (1)] | B.cs:7:18:7:29 | object creation of type Box2 [box1, ... (2)] |
| B.cs:8:14:8:15 | access to local variable b2 [box1, ... (2)] | B.cs:8:14:8:20 | access to field box1 [elem1, ... (1)] |
| B.cs:8:14:8:20 | access to field box1 [elem1, ... (1)] | B.cs:8:14:8:26 | access to field elem1 |
| B.cs:9:14:9:15 | access to local variable b2 [box1, ... (2)] | B.cs:9:14:9:20 | access to field box1 [elem2, ... (1)] |
| B.cs:9:14:9:20 | access to field box1 [elem2, ... (1)] | B.cs:9:14:9:26 | access to field elem2 |
| B.cs:6:18:6:34 | object creation of type Box1 [elem1] | B.cs:7:27:7:28 | access to local variable b1 [elem1] |
| B.cs:6:27:6:27 | access to local variable e | B.cs:6:18:6:34 | object creation of type Box1 [elem1] |
| B.cs:7:18:7:29 | object creation of type Box2 [box1, elem1] | B.cs:8:14:8:15 | access to local variable b2 [box1, elem1] |
| B.cs:7:27:7:28 | access to local variable b1 [elem1] | B.cs:7:18:7:29 | object creation of type Box2 [box1, elem1] |
| B.cs:8:14:8:15 | access to local variable b2 [box1, elem1] | B.cs:8:14:8:20 | access to field box1 [elem1] |
| B.cs:8:14:8:20 | access to field box1 [elem1] | B.cs:8:14:8:26 | access to field elem1 |
| B.cs:14:17:14:26 | object creation of type Elem | B.cs:15:33:15:33 | access to local variable e |
| B.cs:15:18:15:34 | object creation of type Box1 [elem2, ... (1)] | B.cs:16:27:16:28 | access to local variable b1 [elem2, ... (1)] |
| B.cs:15:33:15:33 | access to local variable e | B.cs:15:18:15:34 | object creation of type Box1 [elem2, ... (1)] |
| B.cs:16:18:16:29 | object creation of type Box2 [box1, ... (2)] | B.cs:17:14:17:15 | access to local variable b2 [box1, ... (2)] |
| B.cs:16:18:16:29 | object creation of type Box2 [box1, ... (2)] | B.cs:18:14:18:15 | access to local variable b2 [box1, ... (2)] |
| B.cs:16:27:16:28 | access to local variable b1 [elem2, ... (1)] | B.cs:16:18:16:29 | object creation of type Box2 [box1, ... (2)] |
| B.cs:17:14:17:15 | access to local variable b2 [box1, ... (2)] | B.cs:17:14:17:20 | access to field box1 [elem1, ... (1)] |
| B.cs:17:14:17:20 | access to field box1 [elem1, ... (1)] | B.cs:17:14:17:26 | access to field elem1 |
| B.cs:18:14:18:15 | access to local variable b2 [box1, ... (2)] | B.cs:18:14:18:20 | access to field box1 [elem2, ... (1)] |
| B.cs:18:14:18:20 | access to field box1 [elem2, ... (1)] | B.cs:18:14:18:26 | access to field elem2 |
| C.cs:3:18:3:19 | [post] this access [s1, ... (1)] | C.cs:12:15:12:21 | object creation of type C [s1, ... (1)] |
| C.cs:3:23:3:32 | object creation of type Elem | C.cs:3:18:3:19 | [post] this access [s1, ... (1)] |
| C.cs:4:27:4:28 | [post] this access [s2, ... (1)] | C.cs:12:15:12:21 | object creation of type C [s2, ... (1)] |
| C.cs:4:32:4:41 | object creation of type Elem | C.cs:4:27:4:28 | [post] this access [s2, ... (1)] |
| B.cs:15:18:15:34 | object creation of type Box1 [elem2] | B.cs:16:27:16:28 | access to local variable b1 [elem2] |
| B.cs:15:33:15:33 | access to local variable e | B.cs:15:18:15:34 | object creation of type Box1 [elem2] |
| B.cs:16:18:16:29 | object creation of type Box2 [box1, elem2] | B.cs:18:14:18:15 | access to local variable b2 [box1, elem2] |
| B.cs:16:27:16:28 | access to local variable b1 [elem2] | B.cs:16:18:16:29 | object creation of type Box2 [box1, elem2] |
| B.cs:18:14:18:15 | access to local variable b2 [box1, elem2] | B.cs:18:14:18:20 | access to field box1 [elem2] |
| B.cs:18:14:18:20 | access to field box1 [elem2] | B.cs:18:14:18:26 | access to field elem2 |
| C.cs:3:18:3:19 | [post] this access [s1] | C.cs:12:15:12:21 | object creation of type C [s1] |
| C.cs:3:23:3:32 | object creation of type Elem | C.cs:3:18:3:19 | [post] this access [s1] |
| C.cs:4:27:4:28 | [post] this access [s2] | C.cs:12:15:12:21 | object creation of type C [s2] |
| C.cs:4:32:4:41 | object creation of type Elem | C.cs:4:27:4:28 | [post] this access [s2] |
| C.cs:6:30:6:39 | object creation of type Elem | C.cs:26:14:26:15 | access to field s4 |
| C.cs:7:18:7:19 | [post] this access [s5, ... (1)] | C.cs:12:15:12:21 | object creation of type C [s5, ... (1)] |
| C.cs:7:37:7:46 | object creation of type Elem | C.cs:7:18:7:19 | [post] this access [s5, ... (1)] |
| C.cs:7:18:7:19 | [post] this access [s5] | C.cs:12:15:12:21 | object creation of type C [s5] |
| C.cs:7:37:7:46 | object creation of type Elem | C.cs:7:18:7:19 | [post] this access [s5] |
| C.cs:8:30:8:39 | object creation of type Elem | C.cs:28:14:28:15 | access to property s6 |
| C.cs:12:15:12:21 | object creation of type C [s1, ... (1)] | C.cs:13:9:13:9 | access to local variable c [s1, ... (1)] |
| C.cs:12:15:12:21 | object creation of type C [s2, ... (1)] | C.cs:13:9:13:9 | access to local variable c [s2, ... (1)] |
| C.cs:12:15:12:21 | object creation of type C [s3, ... (1)] | C.cs:13:9:13:9 | access to local variable c [s3, ... (1)] |
| C.cs:12:15:12:21 | object creation of type C [s5, ... (1)] | C.cs:13:9:13:9 | access to local variable c [s5, ... (1)] |
| C.cs:13:9:13:9 | access to local variable c [s1, ... (1)] | C.cs:21:17:21:18 | this [s1, ... (1)] |
| C.cs:13:9:13:9 | access to local variable c [s2, ... (1)] | C.cs:21:17:21:18 | this [s2, ... (1)] |
| C.cs:13:9:13:9 | access to local variable c [s3, ... (1)] | C.cs:21:17:21:18 | this [s3, ... (1)] |
| C.cs:13:9:13:9 | access to local variable c [s5, ... (1)] | C.cs:21:17:21:18 | this [s5, ... (1)] |
| C.cs:18:9:18:12 | [post] this access [s3, ... (1)] | C.cs:12:15:12:21 | object creation of type C [s3, ... (1)] |
| C.cs:18:19:18:28 | object creation of type Elem | C.cs:18:9:18:12 | [post] this access [s3, ... (1)] |
| C.cs:21:17:21:18 | this [s1, ... (1)] | C.cs:23:14:23:15 | this access [s1, ... (1)] |
| C.cs:21:17:21:18 | this [s2, ... (1)] | C.cs:24:14:24:15 | this access [s2, ... (1)] |
| C.cs:21:17:21:18 | this [s3, ... (1)] | C.cs:25:14:25:15 | this access [s3, ... (1)] |
| C.cs:21:17:21:18 | this [s5, ... (1)] | C.cs:27:14:27:15 | this access [s5, ... (1)] |
| C.cs:23:14:23:15 | this access [s1, ... (1)] | C.cs:23:14:23:15 | access to field s1 |
| C.cs:24:14:24:15 | this access [s2, ... (1)] | C.cs:24:14:24:15 | access to field s2 |
| C.cs:25:14:25:15 | this access [s3, ... (1)] | C.cs:25:14:25:15 | access to field s3 |
| C.cs:27:14:27:15 | this access [s5, ... (1)] | C.cs:27:14:27:15 | access to property s5 |
| C.cs:12:15:12:21 | object creation of type C [s1] | C.cs:13:9:13:9 | access to local variable c [s1] |
| C.cs:12:15:12:21 | object creation of type C [s2] | C.cs:13:9:13:9 | access to local variable c [s2] |
| C.cs:12:15:12:21 | object creation of type C [s3] | C.cs:13:9:13:9 | access to local variable c [s3] |
| C.cs:12:15:12:21 | object creation of type C [s5] | C.cs:13:9:13:9 | access to local variable c [s5] |
| C.cs:13:9:13:9 | access to local variable c [s1] | C.cs:21:17:21:18 | this [s1] |
| C.cs:13:9:13:9 | access to local variable c [s2] | C.cs:21:17:21:18 | this [s2] |
| C.cs:13:9:13:9 | access to local variable c [s3] | C.cs:21:17:21:18 | this [s3] |
| C.cs:13:9:13:9 | access to local variable c [s5] | C.cs:21:17:21:18 | this [s5] |
| C.cs:18:9:18:12 | [post] this access [s3] | C.cs:12:15:12:21 | object creation of type C [s3] |
| C.cs:18:19:18:28 | object creation of type Elem | C.cs:18:9:18:12 | [post] this access [s3] |
| C.cs:21:17:21:18 | this [s1] | C.cs:23:14:23:15 | this access [s1] |
| C.cs:21:17:21:18 | this [s2] | C.cs:24:14:24:15 | this access [s2] |
| C.cs:21:17:21:18 | this [s3] | C.cs:25:14:25:15 | this access [s3] |
| C.cs:21:17:21:18 | this [s5] | C.cs:27:14:27:15 | this access [s5] |
| C.cs:23:14:23:15 | this access [s1] | C.cs:23:14:23:15 | access to field s1 |
| C.cs:24:14:24:15 | this access [s2] | C.cs:24:14:24:15 | access to field s2 |
| C.cs:25:14:25:15 | this access [s3] | C.cs:25:14:25:15 | access to field s3 |
| C.cs:27:14:27:15 | this access [s5] | C.cs:27:14:27:15 | access to property s5 |
| D.cs:29:17:29:28 | object creation of type Object | D.cs:31:24:31:24 | access to local variable o |
| D.cs:29:17:29:28 | object creation of type Object | D.cs:37:26:37:26 | access to local variable o |
| D.cs:29:17:29:28 | object creation of type Object | D.cs:43:32:43:32 | access to local variable o |
| D.cs:31:17:31:37 | call to method Create [AutoProp, ... (1)] | D.cs:32:14:32:14 | access to local variable d [AutoProp, ... (1)] |
| D.cs:31:24:31:24 | access to local variable o | D.cs:31:17:31:37 | call to method Create [AutoProp, ... (1)] |
| D.cs:32:14:32:14 | access to local variable d [AutoProp, ... (1)] | D.cs:32:14:32:23 | access to property AutoProp |
| D.cs:37:13:37:33 | call to method Create [trivialPropField, ... (1)] | D.cs:39:14:39:14 | access to local variable d [trivialPropField, ... (1)] |
| D.cs:37:13:37:33 | call to method Create [trivialPropField, ... (1)] | D.cs:40:14:40:14 | access to local variable d [trivialPropField, ... (1)] |
| D.cs:37:13:37:33 | call to method Create [trivialPropField, ... (1)] | D.cs:41:14:41:14 | access to local variable d [trivialPropField, ... (1)] |
| D.cs:37:26:37:26 | access to local variable o | D.cs:37:13:37:33 | call to method Create [trivialPropField, ... (1)] |
| D.cs:39:14:39:14 | access to local variable d [trivialPropField, ... (1)] | D.cs:39:14:39:26 | access to property TrivialProp |
| D.cs:40:14:40:14 | access to local variable d [trivialPropField, ... (1)] | D.cs:40:14:40:31 | access to field trivialPropField |
| D.cs:41:14:41:14 | access to local variable d [trivialPropField, ... (1)] | D.cs:41:14:41:26 | access to property ComplexProp |
| D.cs:43:13:43:33 | call to method Create [trivialPropField, ... (1)] | D.cs:45:14:45:14 | access to local variable d [trivialPropField, ... (1)] |
| D.cs:43:13:43:33 | call to method Create [trivialPropField, ... (1)] | D.cs:46:14:46:14 | access to local variable d [trivialPropField, ... (1)] |
| D.cs:43:13:43:33 | call to method Create [trivialPropField, ... (1)] | D.cs:47:14:47:14 | access to local variable d [trivialPropField, ... (1)] |
| D.cs:43:32:43:32 | access to local variable o | D.cs:43:13:43:33 | call to method Create [trivialPropField, ... (1)] |
| D.cs:45:14:45:14 | access to local variable d [trivialPropField, ... (1)] | D.cs:45:14:45:26 | access to property TrivialProp |
| D.cs:46:14:46:14 | access to local variable d [trivialPropField, ... (1)] | D.cs:46:14:46:31 | access to field trivialPropField |
| D.cs:47:14:47:14 | access to local variable d [trivialPropField, ... (1)] | D.cs:47:14:47:26 | access to property ComplexProp |
| D.cs:31:17:31:37 | call to method Create [AutoProp] | D.cs:32:14:32:14 | access to local variable d [AutoProp] |
| D.cs:31:24:31:24 | access to local variable o | D.cs:31:17:31:37 | call to method Create [AutoProp] |
| D.cs:32:14:32:14 | access to local variable d [AutoProp] | D.cs:32:14:32:23 | access to property AutoProp |
| D.cs:37:13:37:33 | call to method Create [trivialPropField] | D.cs:39:14:39:14 | access to local variable d [trivialPropField] |
| D.cs:37:13:37:33 | call to method Create [trivialPropField] | D.cs:40:14:40:14 | access to local variable d [trivialPropField] |
| D.cs:37:13:37:33 | call to method Create [trivialPropField] | D.cs:41:14:41:14 | access to local variable d [trivialPropField] |
| D.cs:37:26:37:26 | access to local variable o | D.cs:37:13:37:33 | call to method Create [trivialPropField] |
| D.cs:39:14:39:14 | access to local variable d [trivialPropField] | D.cs:39:14:39:26 | access to property TrivialProp |
| D.cs:40:14:40:14 | access to local variable d [trivialPropField] | D.cs:40:14:40:31 | access to field trivialPropField |
| D.cs:41:14:41:14 | access to local variable d [trivialPropField] | D.cs:41:14:41:26 | access to property ComplexProp |
| D.cs:43:13:43:33 | call to method Create [trivialPropField] | D.cs:45:14:45:14 | access to local variable d [trivialPropField] |
| D.cs:43:13:43:33 | call to method Create [trivialPropField] | D.cs:46:14:46:14 | access to local variable d [trivialPropField] |
| D.cs:43:13:43:33 | call to method Create [trivialPropField] | D.cs:47:14:47:14 | access to local variable d [trivialPropField] |
| D.cs:43:32:43:32 | access to local variable o | D.cs:43:13:43:33 | call to method Create [trivialPropField] |
| D.cs:45:14:45:14 | access to local variable d [trivialPropField] | D.cs:45:14:45:26 | access to property TrivialProp |
| D.cs:46:14:46:14 | access to local variable d [trivialPropField] | D.cs:46:14:46:31 | access to field trivialPropField |
| D.cs:47:14:47:14 | access to local variable d [trivialPropField] | D.cs:47:14:47:26 | access to property ComplexProp |
| E.cs:22:17:22:28 | object creation of type Object | E.cs:23:25:23:25 | access to local variable o |
| E.cs:23:17:23:26 | call to method CreateS [Field, ... (1)] | E.cs:24:14:24:14 | access to local variable s [Field, ... (1)] |
| E.cs:23:25:23:25 | access to local variable o | E.cs:23:17:23:26 | call to method CreateS [Field, ... (1)] |
| E.cs:24:14:24:14 | access to local variable s [Field, ... (1)] | E.cs:24:14:24:20 | access to field Field |
| E.cs:23:17:23:26 | call to method CreateS [Field] | E.cs:24:14:24:14 | access to local variable s [Field] |
| E.cs:23:25:23:25 | access to local variable o | E.cs:23:17:23:26 | call to method CreateS [Field] |
| E.cs:24:14:24:14 | access to local variable s [Field] | E.cs:24:14:24:20 | access to field Field |
| F.cs:10:17:10:28 | object creation of type Object | F.cs:11:24:11:24 | access to local variable o |
| F.cs:10:17:10:28 | object creation of type Object | F.cs:15:26:15:26 | access to local variable o |
| F.cs:10:17:10:28 | object creation of type Object | F.cs:19:32:19:32 | access to local variable o |
| F.cs:10:17:10:28 | object creation of type Object | F.cs:23:32:23:32 | access to local variable o |
| F.cs:11:17:11:31 | call to method Create [Field1, ... (1)] | F.cs:12:14:12:14 | access to local variable f [Field1, ... (1)] |
| F.cs:11:24:11:24 | access to local variable o | F.cs:11:17:11:31 | call to method Create [Field1, ... (1)] |
| F.cs:12:14:12:14 | access to local variable f [Field1, ... (1)] | F.cs:12:14:12:21 | access to field Field1 |
| F.cs:15:13:15:27 | call to method Create [Field2, ... (1)] | F.cs:17:14:17:14 | access to local variable f [Field2, ... (1)] |
| F.cs:15:26:15:26 | access to local variable o | F.cs:15:13:15:27 | call to method Create [Field2, ... (1)] |
| F.cs:17:14:17:14 | access to local variable f [Field2, ... (1)] | F.cs:17:14:17:21 | access to field Field2 |
| F.cs:19:13:19:34 | object creation of type F [Field1, ... (1)] | F.cs:20:14:20:14 | access to local variable f [Field1, ... (1)] |
| F.cs:19:32:19:32 | access to local variable o | F.cs:19:13:19:34 | object creation of type F [Field1, ... (1)] |
| F.cs:20:14:20:14 | access to local variable f [Field1, ... (1)] | F.cs:20:14:20:21 | access to field Field1 |
| F.cs:23:13:23:34 | object creation of type F [Field2, ... (1)] | F.cs:25:14:25:14 | access to local variable f [Field2, ... (1)] |
| F.cs:23:32:23:32 | access to local variable o | F.cs:23:13:23:34 | object creation of type F [Field2, ... (1)] |
| F.cs:25:14:25:14 | access to local variable f [Field2, ... (1)] | F.cs:25:14:25:21 | access to field Field2 |
| F.cs:11:17:11:31 | call to method Create [Field1] | F.cs:12:14:12:14 | access to local variable f [Field1] |
| F.cs:11:24:11:24 | access to local variable o | F.cs:11:17:11:31 | call to method Create [Field1] |
| F.cs:12:14:12:14 | access to local variable f [Field1] | F.cs:12:14:12:21 | access to field Field1 |
| F.cs:15:13:15:27 | call to method Create [Field2] | F.cs:17:14:17:14 | access to local variable f [Field2] |
| F.cs:15:26:15:26 | access to local variable o | F.cs:15:13:15:27 | call to method Create [Field2] |
| F.cs:17:14:17:14 | access to local variable f [Field2] | F.cs:17:14:17:21 | access to field Field2 |
| F.cs:19:13:19:34 | object creation of type F [Field1] | F.cs:20:14:20:14 | access to local variable f [Field1] |
| F.cs:19:32:19:32 | access to local variable o | F.cs:19:13:19:34 | object creation of type F [Field1] |
| F.cs:20:14:20:14 | access to local variable f [Field1] | F.cs:20:14:20:21 | access to field Field1 |
| F.cs:23:13:23:34 | object creation of type F [Field2] | F.cs:25:14:25:14 | access to local variable f [Field2] |
| F.cs:23:32:23:32 | access to local variable o | F.cs:23:13:23:34 | object creation of type F [Field2] |
| F.cs:25:14:25:14 | access to local variable f [Field2] | F.cs:25:14:25:21 | access to field Field2 |
| G.cs:7:18:7:27 | object creation of type Elem | G.cs:9:23:9:23 | access to local variable e |
| G.cs:9:9:9:9 | [post] access to local variable b [Box1, ... (2)] | G.cs:10:18:10:18 | access to local variable b [Box1, ... (2)] |
| G.cs:9:9:9:14 | [post] access to field Box1 [Elem, ... (1)] | G.cs:9:9:9:9 | [post] access to local variable b [Box1, ... (2)] |
| G.cs:9:23:9:23 | access to local variable e | G.cs:9:9:9:14 | [post] access to field Box1 [Elem, ... (1)] |
| G.cs:10:18:10:18 | access to local variable b [Box1, ... (2)] | G.cs:37:38:37:39 | b2 [Box1, ... (2)] |
| G.cs:9:9:9:9 | [post] access to local variable b [Box1, Elem] | G.cs:10:18:10:18 | access to local variable b [Box1, Elem] |
| G.cs:9:9:9:14 | [post] access to field Box1 [Elem] | G.cs:9:9:9:9 | [post] access to local variable b [Box1, Elem] |
| G.cs:9:23:9:23 | access to local variable e | G.cs:9:9:9:14 | [post] access to field Box1 [Elem] |
| G.cs:10:18:10:18 | access to local variable b [Box1, Elem] | G.cs:37:38:37:39 | b2 [Box1, Elem] |
| G.cs:15:18:15:27 | object creation of type Elem | G.cs:17:24:17:24 | access to local variable e |
| G.cs:17:9:17:9 | [post] access to local variable b [Box1, ... (2)] | G.cs:18:18:18:18 | access to local variable b [Box1, ... (2)] |
| G.cs:17:9:17:14 | [post] access to field Box1 [Elem, ... (1)] | G.cs:17:9:17:9 | [post] access to local variable b [Box1, ... (2)] |
| G.cs:17:24:17:24 | access to local variable e | G.cs:17:9:17:14 | [post] access to field Box1 [Elem, ... (1)] |
| G.cs:18:18:18:18 | access to local variable b [Box1, ... (2)] | G.cs:37:38:37:39 | b2 [Box1, ... (2)] |
| G.cs:17:9:17:9 | [post] access to local variable b [Box1, Elem] | G.cs:18:18:18:18 | access to local variable b [Box1, Elem] |
| G.cs:17:9:17:14 | [post] access to field Box1 [Elem] | G.cs:17:9:17:9 | [post] access to local variable b [Box1, Elem] |
| G.cs:17:24:17:24 | access to local variable e | G.cs:17:9:17:14 | [post] access to field Box1 [Elem] |
| G.cs:18:18:18:18 | access to local variable b [Box1, Elem] | G.cs:37:38:37:39 | b2 [Box1, Elem] |
| G.cs:23:18:23:27 | object creation of type Elem | G.cs:25:28:25:28 | access to local variable e |
| G.cs:25:9:25:9 | [post] access to local variable b [Box1, ... (2)] | G.cs:26:18:26:18 | access to local variable b [Box1, ... (2)] |
| G.cs:25:9:25:19 | [post] call to method GetBox1 [Elem, ... (1)] | G.cs:25:9:25:9 | [post] access to local variable b [Box1, ... (2)] |
| G.cs:25:28:25:28 | access to local variable e | G.cs:25:9:25:19 | [post] call to method GetBox1 [Elem, ... (1)] |
| G.cs:26:18:26:18 | access to local variable b [Box1, ... (2)] | G.cs:37:38:37:39 | b2 [Box1, ... (2)] |
| G.cs:25:9:25:9 | [post] access to local variable b [Box1, Elem] | G.cs:26:18:26:18 | access to local variable b [Box1, Elem] |
| G.cs:25:9:25:19 | [post] call to method GetBox1 [Elem] | G.cs:25:9:25:9 | [post] access to local variable b [Box1, Elem] |
| G.cs:25:28:25:28 | access to local variable e | G.cs:25:9:25:19 | [post] call to method GetBox1 [Elem] |
| G.cs:26:18:26:18 | access to local variable b [Box1, Elem] | G.cs:37:38:37:39 | b2 [Box1, Elem] |
| G.cs:31:18:31:27 | object creation of type Elem | G.cs:33:29:33:29 | access to local variable e |
| G.cs:33:9:33:9 | [post] access to local variable b [Box1, ... (2)] | G.cs:34:18:34:18 | access to local variable b [Box1, ... (2)] |
| G.cs:33:9:33:19 | [post] call to method GetBox1 [Elem, ... (1)] | G.cs:33:9:33:9 | [post] access to local variable b [Box1, ... (2)] |
| G.cs:33:29:33:29 | access to local variable e | G.cs:33:9:33:19 | [post] call to method GetBox1 [Elem, ... (1)] |
| G.cs:34:18:34:18 | access to local variable b [Box1, ... (2)] | G.cs:37:38:37:39 | b2 [Box1, ... (2)] |
| G.cs:37:38:37:39 | b2 [Box1, ... (2)] | G.cs:39:14:39:15 | access to parameter b2 [Box1, ... (2)] |
| G.cs:39:14:39:15 | access to parameter b2 [Box1, ... (2)] | G.cs:39:14:39:25 | call to method GetBox1 [Elem, ... (1)] |
| G.cs:39:14:39:25 | call to method GetBox1 [Elem, ... (1)] | G.cs:39:14:39:35 | call to method GetElem |
| G.cs:33:9:33:9 | [post] access to local variable b [Box1, Elem] | G.cs:34:18:34:18 | access to local variable b [Box1, Elem] |
| G.cs:33:9:33:19 | [post] call to method GetBox1 [Elem] | G.cs:33:9:33:9 | [post] access to local variable b [Box1, Elem] |
| G.cs:33:29:33:29 | access to local variable e | G.cs:33:9:33:19 | [post] call to method GetBox1 [Elem] |
| G.cs:34:18:34:18 | access to local variable b [Box1, Elem] | G.cs:37:38:37:39 | b2 [Box1, Elem] |
| G.cs:37:38:37:39 | b2 [Box1, Elem] | G.cs:39:14:39:15 | access to parameter b2 [Box1, Elem] |
| G.cs:39:14:39:15 | access to parameter b2 [Box1, Elem] | G.cs:39:14:39:25 | call to method GetBox1 [Elem] |
| G.cs:39:14:39:25 | call to method GetBox1 [Elem] | G.cs:39:14:39:35 | call to method GetElem |
| G.cs:44:18:44:27 | object creation of type Elem | G.cs:46:30:46:30 | access to local variable e |
| G.cs:46:9:46:16 | [post] access to field boxfield [Box1, ... (2)] | G.cs:46:9:46:16 | [post] this access [boxfield, ... (3)] |
| G.cs:46:9:46:16 | [post] this access [boxfield, ... (3)] | G.cs:47:9:47:13 | this access [boxfield, ... (3)] |
| G.cs:46:9:46:21 | [post] access to field Box1 [Elem, ... (1)] | G.cs:46:9:46:16 | [post] access to field boxfield [Box1, ... (2)] |
| G.cs:46:30:46:30 | access to local variable e | G.cs:46:9:46:21 | [post] access to field Box1 [Elem, ... (1)] |
| G.cs:47:9:47:13 | this access [boxfield, ... (3)] | G.cs:50:18:50:20 | this [boxfield, ... (3)] |
| G.cs:50:18:50:20 | this [boxfield, ... (3)] | G.cs:52:14:52:21 | this access [boxfield, ... (3)] |
| G.cs:52:14:52:21 | access to field boxfield [Box1, ... (2)] | G.cs:52:14:52:26 | access to field Box1 [Elem, ... (1)] |
| G.cs:52:14:52:21 | this access [boxfield, ... (3)] | G.cs:52:14:52:21 | access to field boxfield [Box1, ... (2)] |
| G.cs:52:14:52:26 | access to field Box1 [Elem, ... (1)] | G.cs:52:14:52:31 | access to field Elem |
| G.cs:46:9:46:16 | [post] access to field boxfield [Box1, Elem] | G.cs:46:9:46:16 | [post] this access [boxfield, Box1, ... (3)] |
| G.cs:46:9:46:16 | [post] this access [boxfield, Box1, ... (3)] | G.cs:47:9:47:13 | this access [boxfield, Box1, ... (3)] |
| G.cs:46:9:46:21 | [post] access to field Box1 [Elem] | G.cs:46:9:46:16 | [post] access to field boxfield [Box1, Elem] |
| G.cs:46:30:46:30 | access to local variable e | G.cs:46:9:46:21 | [post] access to field Box1 [Elem] |
| G.cs:47:9:47:13 | this access [boxfield, Box1, ... (3)] | G.cs:50:18:50:20 | this [boxfield, Box1, ... (3)] |
| G.cs:50:18:50:20 | this [boxfield, Box1, ... (3)] | G.cs:52:14:52:21 | this access [boxfield, Box1, ... (3)] |
| G.cs:52:14:52:21 | access to field boxfield [Box1, Elem] | G.cs:52:14:52:26 | access to field Box1 [Elem] |
| G.cs:52:14:52:21 | this access [boxfield, Box1, ... (3)] | G.cs:52:14:52:21 | access to field boxfield [Box1, Elem] |
| G.cs:52:14:52:26 | access to field Box1 [Elem] | G.cs:52:14:52:31 | access to field Elem |
#select
| A.cs:7:14:7:16 | access to field c | A.cs:5:17:5:23 | object creation of type C | A.cs:7:14:7:16 | access to field c | $@ | A.cs:5:17:5:23 | object creation of type C | object creation of type C |
| A.cs:14:14:14:20 | call to method Get | A.cs:13:15:13:22 | object creation of type C1 | A.cs:14:14:14:20 | call to method Get | $@ | A.cs:13:15:13:22 | object creation of type C1 | object creation of type C1 |
@@ -195,8 +189,6 @@ edges
| A.cs:119:14:119:30 | access to field head | A.cs:113:17:113:23 | object creation of type B | A.cs:119:14:119:30 | access to field head | $@ | A.cs:113:17:113:23 | object creation of type B | object creation of type B |
| A.cs:123:18:123:23 | access to field head | A.cs:113:17:113:23 | object creation of type B | A.cs:123:18:123:23 | access to field head | $@ | A.cs:113:17:113:23 | object creation of type B | object creation of type B |
| B.cs:8:14:8:26 | access to field elem1 | B.cs:5:17:5:26 | object creation of type Elem | B.cs:8:14:8:26 | access to field elem1 | $@ | B.cs:5:17:5:26 | object creation of type Elem | object creation of type Elem |
| B.cs:9:14:9:26 | access to field elem2 | B.cs:5:17:5:26 | object creation of type Elem | B.cs:9:14:9:26 | access to field elem2 | $@ | B.cs:5:17:5:26 | object creation of type Elem | object creation of type Elem |
| B.cs:17:14:17:26 | access to field elem1 | B.cs:14:17:14:26 | object creation of type Elem | B.cs:17:14:17:26 | access to field elem1 | $@ | B.cs:14:17:14:26 | object creation of type Elem | object creation of type Elem |
| B.cs:18:14:18:26 | access to field elem2 | B.cs:14:17:14:26 | object creation of type Elem | B.cs:18:14:18:26 | access to field elem2 | $@ | B.cs:14:17:14:26 | object creation of type Elem | object creation of type Elem |
| C.cs:23:14:23:15 | access to field s1 | C.cs:3:23:3:32 | object creation of type Elem | C.cs:23:14:23:15 | access to field s1 | $@ | C.cs:3:23:3:32 | object creation of type Elem | object creation of type Elem |
| C.cs:24:14:24:15 | access to field s2 | C.cs:4:32:4:41 | object creation of type Elem | C.cs:24:14:24:15 | access to field s2 | $@ | C.cs:4:32:4:41 | object creation of type Elem | object creation of type Elem |

View File

@@ -1217,7 +1217,8 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
private newtype TAccessPath =
TNil(DataFlowType t) or
TCons(Content f, int len) { len in [1 .. 5] }
TConsNil(Content f, DataFlowType t) { consCand(f, TFrontNil(t), _) } or
TConsCons(Content f1, Content f2, int len) { consCand(f1, TFrontHead(f2), _) and len in [2 .. 5] }
/**
* Conceptually a list of `Content`s followed by a `Type`, but only the first
@@ -1226,52 +1227,93 @@ private newtype TAccessPath =
* 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 AccessPath extends TAccessPath {
abstract private class AccessPath extends TAccessPath {
abstract string toString();
Content getHead() { this = TCons(result, _) }
Content getHead() {
this = TConsNil(result, _)
or
this = TConsCons(result, _, _)
}
int len() {
this = TNil(_) and result = 0
or
this = TCons(_, result)
this = TConsNil(_, _) and result = 1
or
this = TConsCons(_, _, result)
}
DataFlowType getType() {
this = TNil(result)
or
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
result = this.getHead().getContainerType()
}
abstract AccessPathFront getFront();
/**
* Holds if this access path has `head` at the front and may be followed by `tail`.
*/
abstract predicate pop(Content head, AccessPath tail);
}
private class AccessPathNil extends AccessPath, TNil {
override string toString() { exists(DataFlowType t | this = TNil(t) | result = ppReprType(t)) }
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
}
override AccessPathFront getFront() {
exists(DataFlowType t | this = TNil(t) | result = TFrontNil(t))
}
override predicate pop(Content head, AccessPath tail) { none() }
}
private class AccessPathCons extends AccessPath, TCons {
abstract private class AccessPathCons extends AccessPath { }
private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, int len | this = TCons(f, len) |
result = f.toString() + ", ... (" + len.toString() + ")"
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
)
}
override AccessPathFront getFront() {
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
exists(Content f | this = TConsNil(f, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(DataFlowType t | this = TConsNil(head, t) and tail = TNil(t))
}
}
private class AccessPathConsCons extends AccessPathCons, TConsCons {
override string toString() {
exists(Content f1, Content f2, int len | this = TConsCons(f1, f2, len) |
if len = 2
then result = f1.toString() + ", " + f2.toString()
else result = f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")"
)
}
override AccessPathFront getFront() {
exists(Content f | this = TConsCons(f, _, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(int len, Content next | this = TConsCons(head, next, len) |
tail = TConsCons(next, _, len - 1)
or
len = 2 and
tail = TConsNil(next, _)
)
}
}
/** Holds if `ap0` corresponds to the cons of `f` and `ap`. */
private predicate pop(AccessPath ap0, Content f, AccessPath ap) {
ap0.getFront().headUsesContent(f) and
consCand(f, ap.getFront(), _) and
ap0.len() = 1 + ap.len()
}
private predicate pop(AccessPath ap0, Content f, AccessPath ap) { ap0.pop(f, ap) }
/** Holds if `ap0` corresponds to the cons of `f` and `ap` and `apf` is the front of `ap`. */
pragma[noinline]
@@ -2002,11 +2044,66 @@ 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 = concat(" : " + 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) |
if len = 1
then result = f.toString()
else 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
@@ -2016,7 +2113,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
@@ -2090,7 +2187,7 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
AccessPath ap;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2099,7 +2196,7 @@ private module FlowExploration {
CallContext getCallContext() { result = cc }
AccessPath getAp() { result = ap }
PartialAccessPath getAp() { result = ap }
override Configuration getConfiguration() { result = config }
@@ -2112,7 +2209,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
@@ -2121,8 +2218,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
@@ -2132,15 +2229,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)
)
@@ -2161,7 +2258,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
@@ -2171,7 +2268,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()
@@ -2180,7 +2279,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
@@ -2191,7 +2290,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
@@ -2203,8 +2302,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
@@ -2217,7 +2316,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)
@@ -2227,7 +2326,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(
@@ -2253,7 +2352,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
@@ -2262,16 +2361,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)
@@ -2279,7 +2378,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
@@ -2293,7 +2392,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
@@ -2313,9 +2413,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)
@@ -2323,7 +2423,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
@@ -2333,8 +2434,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
@@ -2343,7 +2444,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

View File

@@ -1217,7 +1217,8 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
private newtype TAccessPath =
TNil(DataFlowType t) or
TCons(Content f, int len) { len in [1 .. 5] }
TConsNil(Content f, DataFlowType t) { consCand(f, TFrontNil(t), _) } or
TConsCons(Content f1, Content f2, int len) { consCand(f1, TFrontHead(f2), _) and len in [2 .. 5] }
/**
* Conceptually a list of `Content`s followed by a `Type`, but only the first
@@ -1226,52 +1227,93 @@ private newtype TAccessPath =
* 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 AccessPath extends TAccessPath {
abstract private class AccessPath extends TAccessPath {
abstract string toString();
Content getHead() { this = TCons(result, _) }
Content getHead() {
this = TConsNil(result, _)
or
this = TConsCons(result, _, _)
}
int len() {
this = TNil(_) and result = 0
or
this = TCons(_, result)
this = TConsNil(_, _) and result = 1
or
this = TConsCons(_, _, result)
}
DataFlowType getType() {
this = TNil(result)
or
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
result = this.getHead().getContainerType()
}
abstract AccessPathFront getFront();
/**
* Holds if this access path has `head` at the front and may be followed by `tail`.
*/
abstract predicate pop(Content head, AccessPath tail);
}
private class AccessPathNil extends AccessPath, TNil {
override string toString() { exists(DataFlowType t | this = TNil(t) | result = ppReprType(t)) }
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
}
override AccessPathFront getFront() {
exists(DataFlowType t | this = TNil(t) | result = TFrontNil(t))
}
override predicate pop(Content head, AccessPath tail) { none() }
}
private class AccessPathCons extends AccessPath, TCons {
abstract private class AccessPathCons extends AccessPath { }
private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, int len | this = TCons(f, len) |
result = f.toString() + ", ... (" + len.toString() + ")"
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
)
}
override AccessPathFront getFront() {
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
exists(Content f | this = TConsNil(f, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(DataFlowType t | this = TConsNil(head, t) and tail = TNil(t))
}
}
private class AccessPathConsCons extends AccessPathCons, TConsCons {
override string toString() {
exists(Content f1, Content f2, int len | this = TConsCons(f1, f2, len) |
if len = 2
then result = f1.toString() + ", " + f2.toString()
else result = f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")"
)
}
override AccessPathFront getFront() {
exists(Content f | this = TConsCons(f, _, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(int len, Content next | this = TConsCons(head, next, len) |
tail = TConsCons(next, _, len - 1)
or
len = 2 and
tail = TConsNil(next, _)
)
}
}
/** Holds if `ap0` corresponds to the cons of `f` and `ap`. */
private predicate pop(AccessPath ap0, Content f, AccessPath ap) {
ap0.getFront().headUsesContent(f) and
consCand(f, ap.getFront(), _) and
ap0.len() = 1 + ap.len()
}
private predicate pop(AccessPath ap0, Content f, AccessPath ap) { ap0.pop(f, ap) }
/** Holds if `ap0` corresponds to the cons of `f` and `ap` and `apf` is the front of `ap`. */
pragma[noinline]
@@ -2002,11 +2044,66 @@ 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 = concat(" : " + 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) |
if len = 1
then result = f.toString()
else 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
@@ -2016,7 +2113,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
@@ -2090,7 +2187,7 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
AccessPath ap;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2099,7 +2196,7 @@ private module FlowExploration {
CallContext getCallContext() { result = cc }
AccessPath getAp() { result = ap }
PartialAccessPath getAp() { result = ap }
override Configuration getConfiguration() { result = config }
@@ -2112,7 +2209,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
@@ -2121,8 +2218,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
@@ -2132,15 +2229,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)
)
@@ -2161,7 +2258,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
@@ -2171,7 +2268,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()
@@ -2180,7 +2279,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
@@ -2191,7 +2290,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
@@ -2203,8 +2302,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
@@ -2217,7 +2316,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)
@@ -2227,7 +2326,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(
@@ -2253,7 +2352,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
@@ -2262,16 +2361,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)
@@ -2279,7 +2378,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
@@ -2293,7 +2392,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
@@ -2313,9 +2413,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)
@@ -2323,7 +2423,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
@@ -2333,8 +2434,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
@@ -2343,7 +2444,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

View File

@@ -1217,7 +1217,8 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
private newtype TAccessPath =
TNil(DataFlowType t) or
TCons(Content f, int len) { len in [1 .. 5] }
TConsNil(Content f, DataFlowType t) { consCand(f, TFrontNil(t), _) } or
TConsCons(Content f1, Content f2, int len) { consCand(f1, TFrontHead(f2), _) and len in [2 .. 5] }
/**
* Conceptually a list of `Content`s followed by a `Type`, but only the first
@@ -1226,52 +1227,93 @@ private newtype TAccessPath =
* 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 AccessPath extends TAccessPath {
abstract private class AccessPath extends TAccessPath {
abstract string toString();
Content getHead() { this = TCons(result, _) }
Content getHead() {
this = TConsNil(result, _)
or
this = TConsCons(result, _, _)
}
int len() {
this = TNil(_) and result = 0
or
this = TCons(_, result)
this = TConsNil(_, _) and result = 1
or
this = TConsCons(_, _, result)
}
DataFlowType getType() {
this = TNil(result)
or
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
result = this.getHead().getContainerType()
}
abstract AccessPathFront getFront();
/**
* Holds if this access path has `head` at the front and may be followed by `tail`.
*/
abstract predicate pop(Content head, AccessPath tail);
}
private class AccessPathNil extends AccessPath, TNil {
override string toString() { exists(DataFlowType t | this = TNil(t) | result = ppReprType(t)) }
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
}
override AccessPathFront getFront() {
exists(DataFlowType t | this = TNil(t) | result = TFrontNil(t))
}
override predicate pop(Content head, AccessPath tail) { none() }
}
private class AccessPathCons extends AccessPath, TCons {
abstract private class AccessPathCons extends AccessPath { }
private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, int len | this = TCons(f, len) |
result = f.toString() + ", ... (" + len.toString() + ")"
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
)
}
override AccessPathFront getFront() {
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
exists(Content f | this = TConsNil(f, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(DataFlowType t | this = TConsNil(head, t) and tail = TNil(t))
}
}
private class AccessPathConsCons extends AccessPathCons, TConsCons {
override string toString() {
exists(Content f1, Content f2, int len | this = TConsCons(f1, f2, len) |
if len = 2
then result = f1.toString() + ", " + f2.toString()
else result = f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")"
)
}
override AccessPathFront getFront() {
exists(Content f | this = TConsCons(f, _, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(int len, Content next | this = TConsCons(head, next, len) |
tail = TConsCons(next, _, len - 1)
or
len = 2 and
tail = TConsNil(next, _)
)
}
}
/** Holds if `ap0` corresponds to the cons of `f` and `ap`. */
private predicate pop(AccessPath ap0, Content f, AccessPath ap) {
ap0.getFront().headUsesContent(f) and
consCand(f, ap.getFront(), _) and
ap0.len() = 1 + ap.len()
}
private predicate pop(AccessPath ap0, Content f, AccessPath ap) { ap0.pop(f, ap) }
/** Holds if `ap0` corresponds to the cons of `f` and `ap` and `apf` is the front of `ap`. */
pragma[noinline]
@@ -2002,11 +2044,66 @@ 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 = concat(" : " + 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) |
if len = 1
then result = f.toString()
else 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
@@ -2016,7 +2113,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
@@ -2090,7 +2187,7 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
AccessPath ap;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2099,7 +2196,7 @@ private module FlowExploration {
CallContext getCallContext() { result = cc }
AccessPath getAp() { result = ap }
PartialAccessPath getAp() { result = ap }
override Configuration getConfiguration() { result = config }
@@ -2112,7 +2209,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
@@ -2121,8 +2218,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
@@ -2132,15 +2229,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)
)
@@ -2161,7 +2258,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
@@ -2171,7 +2268,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()
@@ -2180,7 +2279,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
@@ -2191,7 +2290,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
@@ -2203,8 +2302,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
@@ -2217,7 +2316,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)
@@ -2227,7 +2326,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(
@@ -2253,7 +2352,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
@@ -2262,16 +2361,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)
@@ -2279,7 +2378,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
@@ -2293,7 +2392,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
@@ -2313,9 +2413,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)
@@ -2323,7 +2423,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
@@ -2333,8 +2434,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
@@ -2343,7 +2444,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

View File

@@ -1217,7 +1217,8 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
private newtype TAccessPath =
TNil(DataFlowType t) or
TCons(Content f, int len) { len in [1 .. 5] }
TConsNil(Content f, DataFlowType t) { consCand(f, TFrontNil(t), _) } or
TConsCons(Content f1, Content f2, int len) { consCand(f1, TFrontHead(f2), _) and len in [2 .. 5] }
/**
* Conceptually a list of `Content`s followed by a `Type`, but only the first
@@ -1226,52 +1227,93 @@ private newtype TAccessPath =
* 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 AccessPath extends TAccessPath {
abstract private class AccessPath extends TAccessPath {
abstract string toString();
Content getHead() { this = TCons(result, _) }
Content getHead() {
this = TConsNil(result, _)
or
this = TConsCons(result, _, _)
}
int len() {
this = TNil(_) and result = 0
or
this = TCons(_, result)
this = TConsNil(_, _) and result = 1
or
this = TConsCons(_, _, result)
}
DataFlowType getType() {
this = TNil(result)
or
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
result = this.getHead().getContainerType()
}
abstract AccessPathFront getFront();
/**
* Holds if this access path has `head` at the front and may be followed by `tail`.
*/
abstract predicate pop(Content head, AccessPath tail);
}
private class AccessPathNil extends AccessPath, TNil {
override string toString() { exists(DataFlowType t | this = TNil(t) | result = ppReprType(t)) }
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
}
override AccessPathFront getFront() {
exists(DataFlowType t | this = TNil(t) | result = TFrontNil(t))
}
override predicate pop(Content head, AccessPath tail) { none() }
}
private class AccessPathCons extends AccessPath, TCons {
abstract private class AccessPathCons extends AccessPath { }
private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, int len | this = TCons(f, len) |
result = f.toString() + ", ... (" + len.toString() + ")"
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
)
}
override AccessPathFront getFront() {
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
exists(Content f | this = TConsNil(f, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(DataFlowType t | this = TConsNil(head, t) and tail = TNil(t))
}
}
private class AccessPathConsCons extends AccessPathCons, TConsCons {
override string toString() {
exists(Content f1, Content f2, int len | this = TConsCons(f1, f2, len) |
if len = 2
then result = f1.toString() + ", " + f2.toString()
else result = f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")"
)
}
override AccessPathFront getFront() {
exists(Content f | this = TConsCons(f, _, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(int len, Content next | this = TConsCons(head, next, len) |
tail = TConsCons(next, _, len - 1)
or
len = 2 and
tail = TConsNil(next, _)
)
}
}
/** Holds if `ap0` corresponds to the cons of `f` and `ap`. */
private predicate pop(AccessPath ap0, Content f, AccessPath ap) {
ap0.getFront().headUsesContent(f) and
consCand(f, ap.getFront(), _) and
ap0.len() = 1 + ap.len()
}
private predicate pop(AccessPath ap0, Content f, AccessPath ap) { ap0.pop(f, ap) }
/** Holds if `ap0` corresponds to the cons of `f` and `ap` and `apf` is the front of `ap`. */
pragma[noinline]
@@ -2002,11 +2044,66 @@ 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 = concat(" : " + 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) |
if len = 1
then result = f.toString()
else 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
@@ -2016,7 +2113,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
@@ -2090,7 +2187,7 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
AccessPath ap;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2099,7 +2196,7 @@ private module FlowExploration {
CallContext getCallContext() { result = cc }
AccessPath getAp() { result = ap }
PartialAccessPath getAp() { result = ap }
override Configuration getConfiguration() { result = config }
@@ -2112,7 +2209,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
@@ -2121,8 +2218,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
@@ -2132,15 +2229,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)
)
@@ -2161,7 +2258,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
@@ -2171,7 +2268,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()
@@ -2180,7 +2279,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
@@ -2191,7 +2290,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
@@ -2203,8 +2302,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
@@ -2217,7 +2316,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)
@@ -2227,7 +2326,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(
@@ -2253,7 +2352,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
@@ -2262,16 +2361,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)
@@ -2279,7 +2378,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
@@ -2293,7 +2392,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
@@ -2313,9 +2413,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)
@@ -2323,7 +2423,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
@@ -2333,8 +2434,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
@@ -2343,7 +2444,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

View File

@@ -1217,7 +1217,8 @@ private predicate consCand(Content f, AccessPathFront apf, Configuration config)
private newtype TAccessPath =
TNil(DataFlowType t) or
TCons(Content f, int len) { len in [1 .. 5] }
TConsNil(Content f, DataFlowType t) { consCand(f, TFrontNil(t), _) } or
TConsCons(Content f1, Content f2, int len) { consCand(f1, TFrontHead(f2), _) and len in [2 .. 5] }
/**
* Conceptually a list of `Content`s followed by a `Type`, but only the first
@@ -1226,52 +1227,93 @@ private newtype TAccessPath =
* 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 AccessPath extends TAccessPath {
abstract private class AccessPath extends TAccessPath {
abstract string toString();
Content getHead() { this = TCons(result, _) }
Content getHead() {
this = TConsNil(result, _)
or
this = TConsCons(result, _, _)
}
int len() {
this = TNil(_) and result = 0
or
this = TCons(_, result)
this = TConsNil(_, _) and result = 1
or
this = TConsCons(_, _, result)
}
DataFlowType getType() {
this = TNil(result)
or
exists(Content head | this = TCons(head, _) | result = head.getContainerType())
result = this.getHead().getContainerType()
}
abstract AccessPathFront getFront();
/**
* Holds if this access path has `head` at the front and may be followed by `tail`.
*/
abstract predicate pop(Content head, AccessPath tail);
}
private class AccessPathNil extends AccessPath, TNil {
override string toString() { exists(DataFlowType t | this = TNil(t) | result = ppReprType(t)) }
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(ppReprType(t)))
}
override AccessPathFront getFront() {
exists(DataFlowType t | this = TNil(t) | result = TFrontNil(t))
}
override predicate pop(Content head, AccessPath tail) { none() }
}
private class AccessPathCons extends AccessPath, TCons {
abstract private class AccessPathCons extends AccessPath { }
private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, int len | this = TCons(f, len) |
result = f.toString() + ", ... (" + len.toString() + ")"
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
)
}
override AccessPathFront getFront() {
exists(Content f | this = TCons(f, _) | result = TFrontHead(f))
exists(Content f | this = TConsNil(f, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(DataFlowType t | this = TConsNil(head, t) and tail = TNil(t))
}
}
private class AccessPathConsCons extends AccessPathCons, TConsCons {
override string toString() {
exists(Content f1, Content f2, int len | this = TConsCons(f1, f2, len) |
if len = 2
then result = f1.toString() + ", " + f2.toString()
else result = f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")"
)
}
override AccessPathFront getFront() {
exists(Content f | this = TConsCons(f, _, _) | result = TFrontHead(f))
}
override predicate pop(Content head, AccessPath tail) {
exists(int len, Content next | this = TConsCons(head, next, len) |
tail = TConsCons(next, _, len - 1)
or
len = 2 and
tail = TConsNil(next, _)
)
}
}
/** Holds if `ap0` corresponds to the cons of `f` and `ap`. */
private predicate pop(AccessPath ap0, Content f, AccessPath ap) {
ap0.getFront().headUsesContent(f) and
consCand(f, ap.getFront(), _) and
ap0.len() = 1 + ap.len()
}
private predicate pop(AccessPath ap0, Content f, AccessPath ap) { ap0.pop(f, ap) }
/** Holds if `ap0` corresponds to the cons of `f` and `ap` and `apf` is the front of `ap`. */
pragma[noinline]
@@ -2002,11 +2044,66 @@ 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 = concat(" : " + 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) |
if len = 1
then result = f.toString()
else 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
@@ -2016,7 +2113,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
@@ -2090,7 +2187,7 @@ private module FlowExploration {
private class PartialPathNodePriv extends PartialPathNode {
Node node;
CallContext cc;
AccessPath ap;
PartialAccessPath ap;
Configuration config;
PartialPathNodePriv() { this = TPartialPathNodeMk(node, cc, ap, config) }
@@ -2099,7 +2196,7 @@ private module FlowExploration {
CallContext getCallContext() { result = cc }
AccessPath getAp() { result = ap }
PartialAccessPath getAp() { result = ap }
override Configuration getConfiguration() { result = config }
@@ -2112,7 +2209,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
@@ -2121,8 +2218,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
@@ -2132,15 +2229,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)
)
@@ -2161,7 +2258,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
@@ -2171,7 +2268,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()
@@ -2180,7 +2279,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
@@ -2191,7 +2290,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
@@ -2203,8 +2302,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
@@ -2217,7 +2316,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)
@@ -2227,7 +2326,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(
@@ -2253,7 +2352,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
@@ -2262,16 +2361,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)
@@ -2279,7 +2378,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
@@ -2293,7 +2392,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
@@ -2313,9 +2413,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)
@@ -2323,7 +2423,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
@@ -2333,8 +2434,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
@@ -2343,7 +2444,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

View File

@@ -5,14 +5,14 @@ public class B {
Box1 b1 = new Box1(e, null);
Box2 b2 = new Box2(b1);
sink(b2.box1.elem1); // flow
sink(b2.box1.elem2); // FP due to flow in f2 below
sink(b2.box1.elem2); // no flow
}
public void f2() {
Elem e = new Elem();
Box1 b1 = new Box1(null, e);
Box2 b2 = new Box2(b1);
sink(b2.box1.elem1); // FP due to flow in f1 above
sink(b2.box1.elem1); // no flow
sink(b2.box1.elem2); // flow
}

View File

@@ -12,8 +12,6 @@
| A.java:94:11:94:17 | new B(...) | A.java:100:10:100:26 | l3.next.next.head |
| A.java:94:11:94:17 | new B(...) | A.java:103:12:103:17 | l.head |
| B.java:4:14:4:23 | new Elem(...) | B.java:7:10:7:22 | b2.box1.elem1 |
| B.java:4:14:4:23 | new Elem(...) | B.java:8:10:8:22 | b2.box1.elem2 |
| B.java:12:14:12:23 | new Elem(...) | B.java:15:10:15:22 | b2.box1.elem1 |
| B.java:12:14:12:23 | new Elem(...) | B.java:16:10:16:22 | b2.box1.elem2 |
| C.java:3:21:3:30 | new Elem(...) | C.java:18:10:18:11 | s1 |
| C.java:4:27:4:36 | new Elem(...) | C.java:19:10:19:11 | s2 |

View File

@@ -1,14 +1,14 @@
edges
| A.java:12:5:12:5 | b [post update] [elem, ... (1)] | A.java:13:12:13:12 | b [elem, ... (1)] |
| A.java:12:14:12:18 | src(...) [Object] | A.java:12:5:12:5 | b [post update] [elem, ... (1)] |
| A.java:12:14:12:18 | src(...) [Object] | A.java:12:5:12:18 | ...=... [Object] |
| A.java:13:12:13:12 | b [elem, ... (1)] | A.java:17:13:17:16 | f1(...) [elem, ... (1)] |
| A.java:17:13:17:16 | f1(...) [elem, ... (1)] | A.java:18:8:18:8 | b [elem, ... (1)] |
| A.java:18:8:18:8 | b [elem, ... (1)] | A.java:21:11:21:15 | b [elem, ... (1)] |
| A.java:12:5:12:5 | b [post update] [elem] | A.java:13:12:13:12 | b [elem] |
| A.java:12:14:12:18 | src(...) [ : Object] | A.java:12:5:12:5 | b [post update] [elem] |
| A.java:12:14:12:18 | src(...) [ : Object] | A.java:12:5:12:18 | ...=... [ : Object] |
| A.java:13:12:13:12 | b [elem] | A.java:17:13:17:16 | f1(...) [elem] |
| A.java:17:13:17:16 | f1(...) [elem] | A.java:18:8:18:8 | b [elem] |
| A.java:18:8:18:8 | b [elem] | A.java:21:11:21:15 | b [elem] |
#select
| 0 | A.java:12:5:12:5 | b [post update] [elem, ... (1)] |
| 0 | A.java:12:5:12:18 | ...=... [Object] |
| 0 | A.java:13:12:13:12 | b [elem, ... (1)] |
| 1 | A.java:17:13:17:16 | f1(...) [elem, ... (1)] |
| 1 | A.java:18:8:18:8 | b [elem, ... (1)] |
| 2 | A.java:21:11:21:15 | b [elem, ... (1)] |
| 0 | A.java:12:5:12:5 | b [post update] [elem] |
| 0 | A.java:12:5:12:18 | ...=... [ : Object] |
| 0 | A.java:13:12:13:12 | b [elem] |
| 1 | A.java:17:13:17:16 | f1(...) [elem] |
| 1 | A.java:18:8:18:8 | b [elem] |
| 2 | A.java:21:11:21:15 | b [elem] |

View File

@@ -8,9 +8,9 @@ edges
| ArithmeticTainted.java:17:46:17:54 | System.in [InputStream] | ArithmeticTainted.java:119:10:119:13 | data [Number] |
| ArithmeticTainted.java:17:46:17:54 | System.in [InputStream] | ArithmeticTainted.java:120:10:120:13 | data [Number] |
| ArithmeticTainted.java:17:46:17:54 | System.in [InputStream] | ArithmeticTainted.java:121:10:121:13 | data [Number] |
| ArithmeticTainted.java:64:4:64:10 | tainted [post update] [dat, ... (1)] | ArithmeticTainted.java:66:18:66:24 | tainted [dat, ... (1)] |
| ArithmeticTainted.java:64:20:64:23 | data [Number] | ArithmeticTainted.java:64:4:64:10 | tainted [post update] [dat, ... (1)] |
| ArithmeticTainted.java:66:18:66:24 | tainted [dat, ... (1)] | ArithmeticTainted.java:66:18:66:34 | getData(...) [Number] |
| ArithmeticTainted.java:64:4:64:10 | tainted [post update] [dat : Number] | ArithmeticTainted.java:66:18:66:24 | tainted [dat : Number] |
| ArithmeticTainted.java:64:20:64:23 | data [Number] | ArithmeticTainted.java:64:4:64:10 | tainted [post update] [dat : Number] |
| ArithmeticTainted.java:66:18:66:24 | tainted [dat : Number] | ArithmeticTainted.java:66:18:66:34 | getData(...) [Number] |
| ArithmeticTainted.java:66:18:66:34 | getData(...) [Number] | ArithmeticTainted.java:71:17:71:23 | herring |
| ArithmeticTainted.java:118:9:118:12 | data [Number] | ArithmeticTainted.java:125:26:125:33 | data [Number] |
| ArithmeticTainted.java:119:10:119:13 | data [Number] | ArithmeticTainted.java:129:27:129:34 | data [Number] |