Merge remote-tracking branch 'upstream/master' into dataflow-ref-parameter

I've accepted the new test output, which shows that this branch fixes
two false negatives in the test cases from #2088.
This commit is contained in:
Jonas Jensen
2019-10-08 13:09:20 +02:00
147 changed files with 10839 additions and 4360 deletions

View File

@@ -30,7 +30,7 @@ private predicate additionalLogicalCheck(Expr e, string operation, int valueToCh
/**
* An `Operation` that seems to be checking for leap year.
*/
class CheckForLeapYearOperation extends Operation {
class CheckForLeapYearOperation extends Expr {
CheckForLeapYearOperation() {
exists(BinaryArithmeticOperation bo | bo = this |
bo.getAnOperand().getValue().toInt() = 4 and
@@ -39,8 +39,6 @@ class CheckForLeapYearOperation extends Operation {
additionalLogicalCheck(this.getEnclosingElement(), "%", 400)
)
}
override string getOperator() { result = "LeapYearCheck" }
}
/**

View File

@@ -7,7 +7,7 @@
* on each other without introducing mutual recursion among those configurations.
*/
private import DataFlowImplCommon
private import DataFlowImplCommon::Public
private import DataFlowImplSpecific::Private
import DataFlowImplSpecific::Public
@@ -1075,6 +1075,7 @@ private predicate flowCandFwd0(Node node, boolean fromArg, AccessPathFront apf,
flowCandFwd(mid, fromArg, _, config) and
store(mid, f, node) and
nodeCand(node, unbind(config)) and
readStoreCand(f, unbind(config)) and
apf.headUsesContent(f)
)
or
@@ -1175,12 +1176,12 @@ private predicate flowCand0(Node node, boolean toReturn, AccessPathFront apf, Co
exists(Content f, AccessPathFront apf0 |
flowCandStore(node, f, toReturn, apf0, config) and
apf0.headUsesContent(f) and
consCand(f, apf, unbind(config))
consCand(f, apf, config)
)
or
exists(Content f, AccessPathFront apf0 |
flowCandRead(node, f, toReturn, apf0, config) and
consCandFwd(f, apf0, unbind(config)) and
consCandFwd(f, apf0, config) and
apf.headUsesContent(f)
)
}
@@ -1221,8 +1222,8 @@ private newtype TAccessPath =
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
* element of the list and its length are tracked. If data flows from a source to
* Conceptually a list of `Content`s followed by a `Type`, but only the first two
* elements 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.
@@ -1260,7 +1261,7 @@ abstract private class AccessPath extends TAccessPath {
private class AccessPathNil extends AccessPath, TNil {
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(" : " + ppReprType(t)))
exists(DataFlowType t | this = TNil(t) | result = concat(": " + ppReprType(t)))
}
override AccessPathFront getFront() {
@@ -1276,7 +1277,7 @@ private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
result = "[" + f.toString() + "]" + concat(" : " + ppReprType(t))
)
}
@@ -1293,8 +1294,8 @@ 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() + ")"
then result = "[" + f1.toString() + ", " + f2.toString() + "]"
else result = "[" + f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")]"
)
}
@@ -1625,7 +1626,7 @@ abstract class PathNode extends TPathNode {
this instanceof PathNodeSink and result = ""
or
exists(string s | s = this.(PathNodeMid).getAp().toString() |
if s = "" then result = "" else result = " [" + s + "]"
if s = "" then result = "" else result = " " + s
)
}
@@ -2070,7 +2071,7 @@ private module FlowExploration {
private class PartialAccessPathNil extends PartialAccessPath, TPartialNil {
override string toString() {
exists(DataFlowType t | this = TPartialNil(t) | result = concat(" : " + ppReprType(t)))
exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t)))
}
override AccessPathFront getFront() {
@@ -2082,8 +2083,8 @@ private module FlowExploration {
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() + ")"
then result = "[" + f.toString() + "]"
else result = "[" + f.toString() + ", ... (" + len.toString() + ")]"
)
}
@@ -2160,7 +2161,7 @@ private module FlowExploration {
private string ppAp() {
exists(string s | s = this.(PartialPathNodePriv).getAp().toString() |
if s = "" then result = "" else result = " [" + s + "]"
if s = "" then result = "" else result = " " + s
)
}

View File

@@ -7,7 +7,7 @@
* on each other without introducing mutual recursion among those configurations.
*/
private import DataFlowImplCommon
private import DataFlowImplCommon::Public
private import DataFlowImplSpecific::Private
import DataFlowImplSpecific::Public
@@ -1075,6 +1075,7 @@ private predicate flowCandFwd0(Node node, boolean fromArg, AccessPathFront apf,
flowCandFwd(mid, fromArg, _, config) and
store(mid, f, node) and
nodeCand(node, unbind(config)) and
readStoreCand(f, unbind(config)) and
apf.headUsesContent(f)
)
or
@@ -1175,12 +1176,12 @@ private predicate flowCand0(Node node, boolean toReturn, AccessPathFront apf, Co
exists(Content f, AccessPathFront apf0 |
flowCandStore(node, f, toReturn, apf0, config) and
apf0.headUsesContent(f) and
consCand(f, apf, unbind(config))
consCand(f, apf, config)
)
or
exists(Content f, AccessPathFront apf0 |
flowCandRead(node, f, toReturn, apf0, config) and
consCandFwd(f, apf0, unbind(config)) and
consCandFwd(f, apf0, config) and
apf.headUsesContent(f)
)
}
@@ -1221,8 +1222,8 @@ private newtype TAccessPath =
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
* element of the list and its length are tracked. If data flows from a source to
* Conceptually a list of `Content`s followed by a `Type`, but only the first two
* elements 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.
@@ -1260,7 +1261,7 @@ abstract private class AccessPath extends TAccessPath {
private class AccessPathNil extends AccessPath, TNil {
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(" : " + ppReprType(t)))
exists(DataFlowType t | this = TNil(t) | result = concat(": " + ppReprType(t)))
}
override AccessPathFront getFront() {
@@ -1276,7 +1277,7 @@ private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
result = "[" + f.toString() + "]" + concat(" : " + ppReprType(t))
)
}
@@ -1293,8 +1294,8 @@ 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() + ")"
then result = "[" + f1.toString() + ", " + f2.toString() + "]"
else result = "[" + f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")]"
)
}
@@ -1625,7 +1626,7 @@ abstract class PathNode extends TPathNode {
this instanceof PathNodeSink and result = ""
or
exists(string s | s = this.(PathNodeMid).getAp().toString() |
if s = "" then result = "" else result = " [" + s + "]"
if s = "" then result = "" else result = " " + s
)
}
@@ -2070,7 +2071,7 @@ private module FlowExploration {
private class PartialAccessPathNil extends PartialAccessPath, TPartialNil {
override string toString() {
exists(DataFlowType t | this = TPartialNil(t) | result = concat(" : " + ppReprType(t)))
exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t)))
}
override AccessPathFront getFront() {
@@ -2082,8 +2083,8 @@ private module FlowExploration {
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() + ")"
then result = "[" + f.toString() + "]"
else result = "[" + f.toString() + ", ... (" + len.toString() + ")]"
)
}
@@ -2160,7 +2161,7 @@ private module FlowExploration {
private string ppAp() {
exists(string s | s = this.(PartialPathNodePriv).getAp().toString() |
if s = "" then result = "" else result = " [" + s + "]"
if s = "" then result = "" else result = " " + s
)
}

View File

@@ -7,7 +7,7 @@
* on each other without introducing mutual recursion among those configurations.
*/
private import DataFlowImplCommon
private import DataFlowImplCommon::Public
private import DataFlowImplSpecific::Private
import DataFlowImplSpecific::Public
@@ -1075,6 +1075,7 @@ private predicate flowCandFwd0(Node node, boolean fromArg, AccessPathFront apf,
flowCandFwd(mid, fromArg, _, config) and
store(mid, f, node) and
nodeCand(node, unbind(config)) and
readStoreCand(f, unbind(config)) and
apf.headUsesContent(f)
)
or
@@ -1175,12 +1176,12 @@ private predicate flowCand0(Node node, boolean toReturn, AccessPathFront apf, Co
exists(Content f, AccessPathFront apf0 |
flowCandStore(node, f, toReturn, apf0, config) and
apf0.headUsesContent(f) and
consCand(f, apf, unbind(config))
consCand(f, apf, config)
)
or
exists(Content f, AccessPathFront apf0 |
flowCandRead(node, f, toReturn, apf0, config) and
consCandFwd(f, apf0, unbind(config)) and
consCandFwd(f, apf0, config) and
apf.headUsesContent(f)
)
}
@@ -1221,8 +1222,8 @@ private newtype TAccessPath =
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
* element of the list and its length are tracked. If data flows from a source to
* Conceptually a list of `Content`s followed by a `Type`, but only the first two
* elements 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.
@@ -1260,7 +1261,7 @@ abstract private class AccessPath extends TAccessPath {
private class AccessPathNil extends AccessPath, TNil {
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(" : " + ppReprType(t)))
exists(DataFlowType t | this = TNil(t) | result = concat(": " + ppReprType(t)))
}
override AccessPathFront getFront() {
@@ -1276,7 +1277,7 @@ private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
result = "[" + f.toString() + "]" + concat(" : " + ppReprType(t))
)
}
@@ -1293,8 +1294,8 @@ 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() + ")"
then result = "[" + f1.toString() + ", " + f2.toString() + "]"
else result = "[" + f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")]"
)
}
@@ -1625,7 +1626,7 @@ abstract class PathNode extends TPathNode {
this instanceof PathNodeSink and result = ""
or
exists(string s | s = this.(PathNodeMid).getAp().toString() |
if s = "" then result = "" else result = " [" + s + "]"
if s = "" then result = "" else result = " " + s
)
}
@@ -2070,7 +2071,7 @@ private module FlowExploration {
private class PartialAccessPathNil extends PartialAccessPath, TPartialNil {
override string toString() {
exists(DataFlowType t | this = TPartialNil(t) | result = concat(" : " + ppReprType(t)))
exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t)))
}
override AccessPathFront getFront() {
@@ -2082,8 +2083,8 @@ private module FlowExploration {
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() + ")"
then result = "[" + f.toString() + "]"
else result = "[" + f.toString() + ", ... (" + len.toString() + ")]"
)
}
@@ -2160,7 +2161,7 @@ private module FlowExploration {
private string ppAp() {
exists(string s | s = this.(PartialPathNodePriv).getAp().toString() |
if s = "" then result = "" else result = " [" + s + "]"
if s = "" then result = "" else result = " " + s
)
}

View File

@@ -7,7 +7,7 @@
* on each other without introducing mutual recursion among those configurations.
*/
private import DataFlowImplCommon
private import DataFlowImplCommon::Public
private import DataFlowImplSpecific::Private
import DataFlowImplSpecific::Public
@@ -1075,6 +1075,7 @@ private predicate flowCandFwd0(Node node, boolean fromArg, AccessPathFront apf,
flowCandFwd(mid, fromArg, _, config) and
store(mid, f, node) and
nodeCand(node, unbind(config)) and
readStoreCand(f, unbind(config)) and
apf.headUsesContent(f)
)
or
@@ -1175,12 +1176,12 @@ private predicate flowCand0(Node node, boolean toReturn, AccessPathFront apf, Co
exists(Content f, AccessPathFront apf0 |
flowCandStore(node, f, toReturn, apf0, config) and
apf0.headUsesContent(f) and
consCand(f, apf, unbind(config))
consCand(f, apf, config)
)
or
exists(Content f, AccessPathFront apf0 |
flowCandRead(node, f, toReturn, apf0, config) and
consCandFwd(f, apf0, unbind(config)) and
consCandFwd(f, apf0, config) and
apf.headUsesContent(f)
)
}
@@ -1221,8 +1222,8 @@ private newtype TAccessPath =
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
* element of the list and its length are tracked. If data flows from a source to
* Conceptually a list of `Content`s followed by a `Type`, but only the first two
* elements 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.
@@ -1260,7 +1261,7 @@ abstract private class AccessPath extends TAccessPath {
private class AccessPathNil extends AccessPath, TNil {
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(" : " + ppReprType(t)))
exists(DataFlowType t | this = TNil(t) | result = concat(": " + ppReprType(t)))
}
override AccessPathFront getFront() {
@@ -1276,7 +1277,7 @@ private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
result = "[" + f.toString() + "]" + concat(" : " + ppReprType(t))
)
}
@@ -1293,8 +1294,8 @@ 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() + ")"
then result = "[" + f1.toString() + ", " + f2.toString() + "]"
else result = "[" + f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")]"
)
}
@@ -1625,7 +1626,7 @@ abstract class PathNode extends TPathNode {
this instanceof PathNodeSink and result = ""
or
exists(string s | s = this.(PathNodeMid).getAp().toString() |
if s = "" then result = "" else result = " [" + s + "]"
if s = "" then result = "" else result = " " + s
)
}
@@ -2070,7 +2071,7 @@ private module FlowExploration {
private class PartialAccessPathNil extends PartialAccessPath, TPartialNil {
override string toString() {
exists(DataFlowType t | this = TPartialNil(t) | result = concat(" : " + ppReprType(t)))
exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t)))
}
override AccessPathFront getFront() {
@@ -2082,8 +2083,8 @@ private module FlowExploration {
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() + ")"
then result = "[" + f.toString() + "]"
else result = "[" + f.toString() + ", ... (" + len.toString() + ")]"
)
}
@@ -2160,7 +2161,7 @@ private module FlowExploration {
private string ppAp() {
exists(string s | s = this.(PartialPathNodePriv).getAp().toString() |
if s = "" then result = "" else result = " [" + s + "]"
if s = "" then result = "" else result = " " + s
)
}

View File

@@ -7,7 +7,7 @@
* on each other without introducing mutual recursion among those configurations.
*/
private import DataFlowImplCommon
private import DataFlowImplCommon::Public
private import DataFlowImplSpecific::Private
import DataFlowImplSpecific::Public
@@ -1075,6 +1075,7 @@ private predicate flowCandFwd0(Node node, boolean fromArg, AccessPathFront apf,
flowCandFwd(mid, fromArg, _, config) and
store(mid, f, node) and
nodeCand(node, unbind(config)) and
readStoreCand(f, unbind(config)) and
apf.headUsesContent(f)
)
or
@@ -1175,12 +1176,12 @@ private predicate flowCand0(Node node, boolean toReturn, AccessPathFront apf, Co
exists(Content f, AccessPathFront apf0 |
flowCandStore(node, f, toReturn, apf0, config) and
apf0.headUsesContent(f) and
consCand(f, apf, unbind(config))
consCand(f, apf, config)
)
or
exists(Content f, AccessPathFront apf0 |
flowCandRead(node, f, toReturn, apf0, config) and
consCandFwd(f, apf0, unbind(config)) and
consCandFwd(f, apf0, config) and
apf.headUsesContent(f)
)
}
@@ -1221,8 +1222,8 @@ private newtype TAccessPath =
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
* element of the list and its length are tracked. If data flows from a source to
* Conceptually a list of `Content`s followed by a `Type`, but only the first two
* elements 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.
@@ -1260,7 +1261,7 @@ abstract private class AccessPath extends TAccessPath {
private class AccessPathNil extends AccessPath, TNil {
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(" : " + ppReprType(t)))
exists(DataFlowType t | this = TNil(t) | result = concat(": " + ppReprType(t)))
}
override AccessPathFront getFront() {
@@ -1276,7 +1277,7 @@ private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
result = "[" + f.toString() + "]" + concat(" : " + ppReprType(t))
)
}
@@ -1293,8 +1294,8 @@ 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() + ")"
then result = "[" + f1.toString() + ", " + f2.toString() + "]"
else result = "[" + f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")]"
)
}
@@ -1625,7 +1626,7 @@ abstract class PathNode extends TPathNode {
this instanceof PathNodeSink and result = ""
or
exists(string s | s = this.(PathNodeMid).getAp().toString() |
if s = "" then result = "" else result = " [" + s + "]"
if s = "" then result = "" else result = " " + s
)
}
@@ -2070,7 +2071,7 @@ private module FlowExploration {
private class PartialAccessPathNil extends PartialAccessPath, TPartialNil {
override string toString() {
exists(DataFlowType t | this = TPartialNil(t) | result = concat(" : " + ppReprType(t)))
exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t)))
}
override AccessPathFront getFront() {
@@ -2082,8 +2083,8 @@ private module FlowExploration {
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() + ")"
then result = "[" + f.toString() + "]"
else result = "[" + f.toString() + ", ... (" + len.toString() + ")]"
)
}
@@ -2160,7 +2161,7 @@ private module FlowExploration {
private string ppAp() {
exists(string s | s = this.(PartialPathNodePriv).getAp().toString() |
if s = "" then result = "" else result = " [" + s + "]"
if s = "" then result = "" else result = " " + s
)
}

View File

@@ -511,7 +511,7 @@ module FlowVar_internal {
exists(VariableAccess va |
va.getTarget() = result and
readAccess(va) and
bbNotInLoop(va.getBasicBlock())
exists(BasicBlock bb | bb = va.getBasicBlock() | not this.bbInLoop(bb))
)
}
@@ -534,10 +534,8 @@ module FlowVar_internal {
bbInLoopCondition(bb)
}
predicate bbNotInLoop(BasicBlock bb) {
not this.bbInLoop(bb) and
bb.getEnclosingFunction() = this.getEnclosingFunction()
}
/** Holds if `sbb` is inside this loop. */
predicate sbbInLoop(SubBasicBlock sbb) { this.bbInLoop(sbb.getBasicBlock()) }
/**
* Holds if `bb` is a basic block inside this loop where `v` has not been
@@ -558,22 +556,19 @@ module FlowVar_internal {
}
/**
* Holds if some loop always assigns to `v` before leaving through an edge
* from `bbInside` in its condition to `bbOutside` outside the loop, where
* (`sbbDef`, `v`) is a `BlockVar` defined outside the loop. Also, `v` must
* be used outside the loop.
* Holds if `loop` always assigns to `v` before leaving through an edge
* from `bbInside` in its condition to `bbOutside` outside the loop. Also,
* `v` must be used outside the loop.
*/
predicate skipLoop(
SubBasicBlock sbbInside, SubBasicBlock sbbOutside, SubBasicBlock sbbDef, Variable v
SubBasicBlock sbbInside, SubBasicBlock sbbOutside, Variable v, AlwaysTrueUponEntryLoop loop
) {
exists(AlwaysTrueUponEntryLoop loop, BasicBlock bbInside, BasicBlock bbOutside |
exists(BasicBlock bbInside, BasicBlock bbOutside |
loop.alwaysAssignsBeforeLeavingCondition(bbInside, bbOutside, v) and
bbInside = sbbInside.getBasicBlock() and
bbOutside = sbbOutside.getBasicBlock() and
sbbInside.lastInBB() and
sbbOutside.firstInBB() and
loop.bbNotInLoop(sbbDef.getBasicBlock()) and
exists(TBlockVar(sbbDef, v))
sbbOutside.firstInBB()
)
}
@@ -592,7 +587,7 @@ module FlowVar_internal {
start = TBlockVar(sbbDef, v) and
result = mid.getASuccessor() and
variableLiveInSBB(result, v) and
not skipLoop(mid, result, sbbDef, v) and
forall(AlwaysTrueUponEntryLoop loop | skipLoop(mid, result, v, loop) | loop.sbbInLoop(sbbDef)) and
not assignmentLikeOperation(result, v, _, _)
)
}
@@ -711,10 +706,11 @@ module FlowVar_internal {
predicate dominatedByOverwrite(UninitializedLocalVariable v, VariableAccess va) {
exists(BasicBlock bb, int vaIndex |
va = bb.getNode(vaIndex) and
va.getTarget() = v
|
va.getTarget() = v and
vaIndex > indexOfFirstOverwriteInBB(v, bb)
or
va = bb.getNode(vaIndex) and
va.getTarget() = v and
bbStrictlyDominates(getAnOverwritingBB(v), bb)
)
}

View File

@@ -4,25 +4,17 @@ private import semmle.code.cpp.ir.dataflow.DataFlow
private import semmle.code.cpp.ir.IR
/**
* A predictable expression is one where an external user can predict
* A predictable instruction is one where an external user can predict
* the value. For example, a literal in the source code is considered
* predictable.
*/
// TODO: Change to use Instruction instead of Expr. Naive attempt breaks
// TaintedAllocationSize qltest.
private predicate predictable(Expr expr) {
expr instanceof Literal
or
exists(BinaryOperation binop | binop = expr |
predictable(binop.getLeftOperand()) and predictable(binop.getRightOperand())
)
or
exists(UnaryOperation unop | unop = expr | predictable(unop.getOperand()))
}
// TODO: remove when `predictable` has an `Instruction` parameter instead of `Expr`.
private predicate predictableInstruction(Instruction instr) {
predictable(DataFlow::instructionNode(instr).asExpr())
instr instanceof ConstantInstruction
or
instr instanceof StringConstantInstruction
or
// This could be a conversion on a string literal
predictableInstruction(instr.(UnaryInstruction).getUnary())
}
private class DefaultTaintTrackingCfg extends DataFlow::Configuration {

View File

@@ -7,7 +7,7 @@
* on each other without introducing mutual recursion among those configurations.
*/
private import DataFlowImplCommon
private import DataFlowImplCommon::Public
private import DataFlowImplSpecific::Private
import DataFlowImplSpecific::Public
@@ -1075,6 +1075,7 @@ private predicate flowCandFwd0(Node node, boolean fromArg, AccessPathFront apf,
flowCandFwd(mid, fromArg, _, config) and
store(mid, f, node) and
nodeCand(node, unbind(config)) and
readStoreCand(f, unbind(config)) and
apf.headUsesContent(f)
)
or
@@ -1175,12 +1176,12 @@ private predicate flowCand0(Node node, boolean toReturn, AccessPathFront apf, Co
exists(Content f, AccessPathFront apf0 |
flowCandStore(node, f, toReturn, apf0, config) and
apf0.headUsesContent(f) and
consCand(f, apf, unbind(config))
consCand(f, apf, config)
)
or
exists(Content f, AccessPathFront apf0 |
flowCandRead(node, f, toReturn, apf0, config) and
consCandFwd(f, apf0, unbind(config)) and
consCandFwd(f, apf0, config) and
apf.headUsesContent(f)
)
}
@@ -1221,8 +1222,8 @@ private newtype TAccessPath =
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
* element of the list and its length are tracked. If data flows from a source to
* Conceptually a list of `Content`s followed by a `Type`, but only the first two
* elements 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.
@@ -1260,7 +1261,7 @@ abstract private class AccessPath extends TAccessPath {
private class AccessPathNil extends AccessPath, TNil {
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(" : " + ppReprType(t)))
exists(DataFlowType t | this = TNil(t) | result = concat(": " + ppReprType(t)))
}
override AccessPathFront getFront() {
@@ -1276,7 +1277,7 @@ private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
result = "[" + f.toString() + "]" + concat(" : " + ppReprType(t))
)
}
@@ -1293,8 +1294,8 @@ 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() + ")"
then result = "[" + f1.toString() + ", " + f2.toString() + "]"
else result = "[" + f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")]"
)
}
@@ -1625,7 +1626,7 @@ abstract class PathNode extends TPathNode {
this instanceof PathNodeSink and result = ""
or
exists(string s | s = this.(PathNodeMid).getAp().toString() |
if s = "" then result = "" else result = " [" + s + "]"
if s = "" then result = "" else result = " " + s
)
}
@@ -2070,7 +2071,7 @@ private module FlowExploration {
private class PartialAccessPathNil extends PartialAccessPath, TPartialNil {
override string toString() {
exists(DataFlowType t | this = TPartialNil(t) | result = concat(" : " + ppReprType(t)))
exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t)))
}
override AccessPathFront getFront() {
@@ -2082,8 +2083,8 @@ private module FlowExploration {
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() + ")"
then result = "[" + f.toString() + "]"
else result = "[" + f.toString() + ", ... (" + len.toString() + ")]"
)
}
@@ -2160,7 +2161,7 @@ private module FlowExploration {
private string ppAp() {
exists(string s | s = this.(PartialPathNodePriv).getAp().toString() |
if s = "" then result = "" else result = " [" + s + "]"
if s = "" then result = "" else result = " " + s
)
}

View File

@@ -7,7 +7,7 @@
* on each other without introducing mutual recursion among those configurations.
*/
private import DataFlowImplCommon
private import DataFlowImplCommon::Public
private import DataFlowImplSpecific::Private
import DataFlowImplSpecific::Public
@@ -1075,6 +1075,7 @@ private predicate flowCandFwd0(Node node, boolean fromArg, AccessPathFront apf,
flowCandFwd(mid, fromArg, _, config) and
store(mid, f, node) and
nodeCand(node, unbind(config)) and
readStoreCand(f, unbind(config)) and
apf.headUsesContent(f)
)
or
@@ -1175,12 +1176,12 @@ private predicate flowCand0(Node node, boolean toReturn, AccessPathFront apf, Co
exists(Content f, AccessPathFront apf0 |
flowCandStore(node, f, toReturn, apf0, config) and
apf0.headUsesContent(f) and
consCand(f, apf, unbind(config))
consCand(f, apf, config)
)
or
exists(Content f, AccessPathFront apf0 |
flowCandRead(node, f, toReturn, apf0, config) and
consCandFwd(f, apf0, unbind(config)) and
consCandFwd(f, apf0, config) and
apf.headUsesContent(f)
)
}
@@ -1221,8 +1222,8 @@ private newtype TAccessPath =
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
* element of the list and its length are tracked. If data flows from a source to
* Conceptually a list of `Content`s followed by a `Type`, but only the first two
* elements 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.
@@ -1260,7 +1261,7 @@ abstract private class AccessPath extends TAccessPath {
private class AccessPathNil extends AccessPath, TNil {
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(" : " + ppReprType(t)))
exists(DataFlowType t | this = TNil(t) | result = concat(": " + ppReprType(t)))
}
override AccessPathFront getFront() {
@@ -1276,7 +1277,7 @@ private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
result = "[" + f.toString() + "]" + concat(" : " + ppReprType(t))
)
}
@@ -1293,8 +1294,8 @@ 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() + ")"
then result = "[" + f1.toString() + ", " + f2.toString() + "]"
else result = "[" + f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")]"
)
}
@@ -1625,7 +1626,7 @@ abstract class PathNode extends TPathNode {
this instanceof PathNodeSink and result = ""
or
exists(string s | s = this.(PathNodeMid).getAp().toString() |
if s = "" then result = "" else result = " [" + s + "]"
if s = "" then result = "" else result = " " + s
)
}
@@ -2070,7 +2071,7 @@ private module FlowExploration {
private class PartialAccessPathNil extends PartialAccessPath, TPartialNil {
override string toString() {
exists(DataFlowType t | this = TPartialNil(t) | result = concat(" : " + ppReprType(t)))
exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t)))
}
override AccessPathFront getFront() {
@@ -2082,8 +2083,8 @@ private module FlowExploration {
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() + ")"
then result = "[" + f.toString() + "]"
else result = "[" + f.toString() + ", ... (" + len.toString() + ")]"
)
}
@@ -2160,7 +2161,7 @@ private module FlowExploration {
private string ppAp() {
exists(string s | s = this.(PartialPathNodePriv).getAp().toString() |
if s = "" then result = "" else result = " [" + s + "]"
if s = "" then result = "" else result = " " + s
)
}

View File

@@ -7,7 +7,7 @@
* on each other without introducing mutual recursion among those configurations.
*/
private import DataFlowImplCommon
private import DataFlowImplCommon::Public
private import DataFlowImplSpecific::Private
import DataFlowImplSpecific::Public
@@ -1075,6 +1075,7 @@ private predicate flowCandFwd0(Node node, boolean fromArg, AccessPathFront apf,
flowCandFwd(mid, fromArg, _, config) and
store(mid, f, node) and
nodeCand(node, unbind(config)) and
readStoreCand(f, unbind(config)) and
apf.headUsesContent(f)
)
or
@@ -1175,12 +1176,12 @@ private predicate flowCand0(Node node, boolean toReturn, AccessPathFront apf, Co
exists(Content f, AccessPathFront apf0 |
flowCandStore(node, f, toReturn, apf0, config) and
apf0.headUsesContent(f) and
consCand(f, apf, unbind(config))
consCand(f, apf, config)
)
or
exists(Content f, AccessPathFront apf0 |
flowCandRead(node, f, toReturn, apf0, config) and
consCandFwd(f, apf0, unbind(config)) and
consCandFwd(f, apf0, config) and
apf.headUsesContent(f)
)
}
@@ -1221,8 +1222,8 @@ private newtype TAccessPath =
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
* element of the list and its length are tracked. If data flows from a source to
* Conceptually a list of `Content`s followed by a `Type`, but only the first two
* elements 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.
@@ -1260,7 +1261,7 @@ abstract private class AccessPath extends TAccessPath {
private class AccessPathNil extends AccessPath, TNil {
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(" : " + ppReprType(t)))
exists(DataFlowType t | this = TNil(t) | result = concat(": " + ppReprType(t)))
}
override AccessPathFront getFront() {
@@ -1276,7 +1277,7 @@ private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
result = "[" + f.toString() + "]" + concat(" : " + ppReprType(t))
)
}
@@ -1293,8 +1294,8 @@ 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() + ")"
then result = "[" + f1.toString() + ", " + f2.toString() + "]"
else result = "[" + f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")]"
)
}
@@ -1625,7 +1626,7 @@ abstract class PathNode extends TPathNode {
this instanceof PathNodeSink and result = ""
or
exists(string s | s = this.(PathNodeMid).getAp().toString() |
if s = "" then result = "" else result = " [" + s + "]"
if s = "" then result = "" else result = " " + s
)
}
@@ -2070,7 +2071,7 @@ private module FlowExploration {
private class PartialAccessPathNil extends PartialAccessPath, TPartialNil {
override string toString() {
exists(DataFlowType t | this = TPartialNil(t) | result = concat(" : " + ppReprType(t)))
exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t)))
}
override AccessPathFront getFront() {
@@ -2082,8 +2083,8 @@ private module FlowExploration {
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() + ")"
then result = "[" + f.toString() + "]"
else result = "[" + f.toString() + ", ... (" + len.toString() + ")]"
)
}
@@ -2160,7 +2161,7 @@ private module FlowExploration {
private string ppAp() {
exists(string s | s = this.(PartialPathNodePriv).getAp().toString() |
if s = "" then result = "" else result = " [" + s + "]"
if s = "" then result = "" else result = " " + s
)
}

View File

@@ -7,7 +7,7 @@
* on each other without introducing mutual recursion among those configurations.
*/
private import DataFlowImplCommon
private import DataFlowImplCommon::Public
private import DataFlowImplSpecific::Private
import DataFlowImplSpecific::Public
@@ -1075,6 +1075,7 @@ private predicate flowCandFwd0(Node node, boolean fromArg, AccessPathFront apf,
flowCandFwd(mid, fromArg, _, config) and
store(mid, f, node) and
nodeCand(node, unbind(config)) and
readStoreCand(f, unbind(config)) and
apf.headUsesContent(f)
)
or
@@ -1175,12 +1176,12 @@ private predicate flowCand0(Node node, boolean toReturn, AccessPathFront apf, Co
exists(Content f, AccessPathFront apf0 |
flowCandStore(node, f, toReturn, apf0, config) and
apf0.headUsesContent(f) and
consCand(f, apf, unbind(config))
consCand(f, apf, config)
)
or
exists(Content f, AccessPathFront apf0 |
flowCandRead(node, f, toReturn, apf0, config) and
consCandFwd(f, apf0, unbind(config)) and
consCandFwd(f, apf0, config) and
apf.headUsesContent(f)
)
}
@@ -1221,8 +1222,8 @@ private newtype TAccessPath =
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
* element of the list and its length are tracked. If data flows from a source to
* Conceptually a list of `Content`s followed by a `Type`, but only the first two
* elements 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.
@@ -1260,7 +1261,7 @@ abstract private class AccessPath extends TAccessPath {
private class AccessPathNil extends AccessPath, TNil {
override string toString() {
exists(DataFlowType t | this = TNil(t) | result = concat(" : " + ppReprType(t)))
exists(DataFlowType t | this = TNil(t) | result = concat(": " + ppReprType(t)))
}
override AccessPathFront getFront() {
@@ -1276,7 +1277,7 @@ private class AccessPathConsNil extends AccessPathCons, TConsNil {
override string toString() {
exists(Content f, DataFlowType t | this = TConsNil(f, t) |
// The `concat` becomes "" if `ppReprType` has no result.
result = f.toString() + concat(" : " + ppReprType(t))
result = "[" + f.toString() + "]" + concat(" : " + ppReprType(t))
)
}
@@ -1293,8 +1294,8 @@ 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() + ")"
then result = "[" + f1.toString() + ", " + f2.toString() + "]"
else result = "[" + f1.toString() + ", " + f2.toString() + ", ... (" + len.toString() + ")]"
)
}
@@ -1625,7 +1626,7 @@ abstract class PathNode extends TPathNode {
this instanceof PathNodeSink and result = ""
or
exists(string s | s = this.(PathNodeMid).getAp().toString() |
if s = "" then result = "" else result = " [" + s + "]"
if s = "" then result = "" else result = " " + s
)
}
@@ -2070,7 +2071,7 @@ private module FlowExploration {
private class PartialAccessPathNil extends PartialAccessPath, TPartialNil {
override string toString() {
exists(DataFlowType t | this = TPartialNil(t) | result = concat(" : " + ppReprType(t)))
exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t)))
}
override AccessPathFront getFront() {
@@ -2082,8 +2083,8 @@ private module FlowExploration {
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() + ")"
then result = "[" + f.toString() + "]"
else result = "[" + f.toString() + ", ... (" + len.toString() + ")]"
)
}
@@ -2160,7 +2161,7 @@ private module FlowExploration {
private string ppAp() {
exists(string s | s = this.(PartialPathNodePriv).getAp().toString() |
if s = "" then result = "" else result = " [" + s + "]"
if s = "" then result = "" else result = " " + s
)
}

View File

@@ -1,6 +1,7 @@
private import implementations.IdentityFunction
private import implementations.Inet
private import implementations.Memcpy
private import implementations.Memset
private import implementations.Printf
private import implementations.Pure
private import implementations.Strcat

View File

@@ -0,0 +1,41 @@
import semmle.code.cpp.Function
import semmle.code.cpp.models.interfaces.ArrayFunction
import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Alias
/**
* The standard function `memset` and its assorted variants
*/
class MemsetFunction extends ArrayFunction, DataFlowFunction, AliasFunction {
MemsetFunction() {
hasGlobalName("memset") or
hasGlobalName("wmemset") or
hasGlobalName("bzero") or
hasGlobalName("__builtin_memset") or
hasGlobalName("__builtin_memset_chk") or
hasQualifiedName("std", "memset") or
hasQualifiedName("std", "wmemset")
}
override predicate hasArrayOutput(int bufParam) { bufParam = 0 }
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(0) and
output.isReturnValue()
}
override predicate hasArrayWithVariableSize(int bufParam, int countParam) {
bufParam = 0 and
(if hasGlobalName("bzero") then countParam = 1 else countParam = 2)
}
override predicate parameterNeverEscapes(int index) { hasGlobalName("bzero") and index = 0 }
override predicate parameterEscapesOnlyViaReturn(int index) {
not hasGlobalName("bzero") and index = 0
}
override predicate parameterIsAlwaysReturned(int index) {
not hasGlobalName("bzero") and index = 0
}
}

View File

@@ -521,18 +521,21 @@ params(
overrides(int new: @function ref, int old: @function ref);
#keyset[id, type_id]
membervariables(
unique int id: @membervariable,
int id: @membervariable,
int type_id: @type ref,
string name: string ref
);
#keyset[id, type_id]
globalvariables(
unique int id: @globalvariable,
int id: @globalvariable,
int type_id: @type ref,
string name: string ref
);
#keyset[id, type_id]
localvariables(
int id: @localvariable,
int type_id: @type ref,
@@ -1061,10 +1064,12 @@ compgenerated(unique int id: @element ref);
* destructed in reverse construction order, so for a given `element`
* these should be called from highest to lowest `i`.
*/
#keyset[element, destructor_call]
#keyset[element, i]
synthetic_destructor_call(
int element: @element ref,
int i: int ref,
unique int destructor_call: @routineexpr ref
int destructor_call: @routineexpr ref
);
namespaces(

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
int x = int();
float y = float();
double z = double();
/* This produces a getValueText() of 0 for R() in line 9, which is debatable. */
struct R {};
struct S {
S() : S(R()) { }
S(R) { }
};
S s;

View File

@@ -0,0 +1,4 @@
| constants.cpp:2:9:2:13 | 0 | int() |
| constants.cpp:3:11:3:17 | 0.0 | float() |
| constants.cpp:4:12:4:19 | 0.0 | double() |
| constants.cpp:9:11:9:13 | 0 | 0 |

View File

@@ -0,0 +1,4 @@
import cpp
from Expr e
select e, e.getValueText()

View File

@@ -235,3 +235,92 @@
| taint.cpp:258:7:258:12 | call to source | taint.cpp:255:35:255:35 | c | |
| taint.cpp:258:7:258:12 | call to source | taint.cpp:258:3:258:14 | ... = ... | |
| taint.cpp:260:10:260:10 | ref arg w | taint.cpp:261:7:261:7 | w | |
| taint.cpp:266:12:266:12 | x | taint.cpp:268:9:268:9 | x | |
| taint.cpp:275:6:275:11 | call to source | taint.cpp:275:2:275:13 | ... = ... | |
| taint.cpp:275:6:275:11 | call to source | taint.cpp:280:7:280:7 | t | |
| taint.cpp:275:6:275:11 | call to source | taint.cpp:285:9:285:9 | t | |
| taint.cpp:275:6:275:11 | call to source | taint.cpp:286:12:286:12 | t | |
| taint.cpp:275:6:275:11 | call to source | taint.cpp:289:7:289:7 | t | |
| taint.cpp:276:6:276:6 | 0 | taint.cpp:276:2:276:6 | ... = ... | |
| taint.cpp:276:6:276:6 | 0 | taint.cpp:281:7:281:7 | x | |
| taint.cpp:277:6:277:6 | 0 | taint.cpp:277:2:277:6 | ... = ... | |
| taint.cpp:277:6:277:6 | 0 | taint.cpp:282:7:282:7 | y | |
| taint.cpp:278:6:278:6 | 0 | taint.cpp:278:2:278:6 | ... = ... | |
| taint.cpp:278:6:278:6 | 0 | taint.cpp:283:7:283:7 | z | |
| taint.cpp:278:6:278:6 | 0 | taint.cpp:287:9:287:9 | z | |
| taint.cpp:285:6:285:7 | call to id | taint.cpp:285:2:285:10 | ... = ... | |
| taint.cpp:285:6:285:7 | call to id | taint.cpp:290:7:290:7 | x | |
| taint.cpp:286:6:286:7 | call to id | taint.cpp:286:2:286:14 | ... = ... | |
| taint.cpp:286:6:286:7 | call to id | taint.cpp:291:7:291:7 | y | |
| taint.cpp:287:6:287:7 | call to id | taint.cpp:287:2:287:10 | ... = ... | |
| taint.cpp:287:6:287:7 | call to id | taint.cpp:292:7:292:7 | z | |
| taint.cpp:297:29:297:29 | b | taint.cpp:297:29:297:29 | b | |
| taint.cpp:297:29:297:29 | b | taint.cpp:299:6:299:6 | b | |
| taint.cpp:299:6:299:6 | b | taint.cpp:297:21:297:21 | a | |
| taint.cpp:299:6:299:6 | b | taint.cpp:299:2:299:6 | ... = ... | |
| taint.cpp:302:28:302:28 | b | taint.cpp:304:6:304:6 | b | |
| taint.cpp:304:6:304:6 | b | taint.cpp:302:21:302:21 | a | |
| taint.cpp:304:6:304:6 | b | taint.cpp:304:2:304:6 | ... = ... | |
| taint.cpp:307:21:307:21 | a | taint.cpp:309:3:309:3 | a | |
| taint.cpp:307:28:307:28 | b | taint.cpp:309:7:309:7 | b | |
| taint.cpp:309:3:309:3 | a | taint.cpp:309:2:309:3 | * ... | TAINT |
| taint.cpp:309:7:309:7 | b | taint.cpp:309:2:309:7 | ... = ... | |
| taint.cpp:312:21:312:21 | a | taint.cpp:317:3:317:3 | a | |
| taint.cpp:312:28:312:28 | b | taint.cpp:316:6:316:6 | b | |
| taint.cpp:316:6:316:6 | b | taint.cpp:316:6:316:10 | ... + ... | TAINT |
| taint.cpp:316:6:316:10 | ... + ... | taint.cpp:316:2:316:10 | ... = ... | |
| taint.cpp:316:6:316:10 | ... + ... | taint.cpp:317:7:317:7 | c | |
| taint.cpp:316:10:316:10 | 1 | taint.cpp:316:6:316:10 | ... + ... | TAINT |
| taint.cpp:317:3:317:3 | a | taint.cpp:317:2:317:3 | * ... | TAINT |
| taint.cpp:317:7:317:7 | c | taint.cpp:317:2:317:7 | ... = ... | |
| taint.cpp:320:23:320:23 | a | taint.cpp:322:6:322:6 | a | |
| taint.cpp:320:31:320:31 | b | taint.cpp:323:6:323:6 | b | |
| taint.cpp:322:6:322:6 | a | taint.cpp:322:6:322:10 | ... + ... | TAINT |
| taint.cpp:322:6:322:10 | ... + ... | taint.cpp:320:23:320:23 | a | |
| taint.cpp:322:6:322:10 | ... + ... | taint.cpp:322:2:322:10 | ... = ... | |
| taint.cpp:322:10:322:10 | 1 | taint.cpp:322:6:322:10 | ... + ... | TAINT |
| taint.cpp:323:6:323:6 | b | taint.cpp:323:6:323:10 | ... + ... | TAINT |
| taint.cpp:323:6:323:10 | ... + ... | taint.cpp:320:31:320:31 | b | |
| taint.cpp:323:6:323:10 | ... + ... | taint.cpp:323:2:323:10 | ... = ... | |
| taint.cpp:323:10:323:10 | 1 | taint.cpp:323:6:323:10 | ... + ... | TAINT |
| taint.cpp:330:6:330:11 | call to source | taint.cpp:330:2:330:13 | ... = ... | |
| taint.cpp:330:6:330:11 | call to source | taint.cpp:337:7:337:7 | t | |
| taint.cpp:330:6:330:11 | call to source | taint.cpp:344:15:344:15 | t | |
| taint.cpp:330:6:330:11 | call to source | taint.cpp:345:15:345:15 | t | |
| taint.cpp:330:6:330:11 | call to source | taint.cpp:346:16:346:16 | t | |
| taint.cpp:330:6:330:11 | call to source | taint.cpp:347:16:347:16 | t | |
| taint.cpp:330:6:330:11 | call to source | taint.cpp:348:17:348:17 | t | |
| taint.cpp:330:6:330:11 | call to source | taint.cpp:350:7:350:7 | t | |
| taint.cpp:331:6:331:6 | 0 | taint.cpp:331:2:331:6 | ... = ... | |
| taint.cpp:331:6:331:6 | 0 | taint.cpp:338:7:338:7 | a | |
| taint.cpp:331:6:331:6 | 0 | taint.cpp:344:12:344:12 | a | |
| taint.cpp:331:6:331:6 | 0 | taint.cpp:351:7:351:7 | a | |
| taint.cpp:332:6:332:6 | 0 | taint.cpp:332:2:332:6 | ... = ... | |
| taint.cpp:332:6:332:6 | 0 | taint.cpp:339:7:339:7 | b | |
| taint.cpp:332:6:332:6 | 0 | taint.cpp:345:12:345:12 | b | |
| taint.cpp:332:6:332:6 | 0 | taint.cpp:352:7:352:7 | b | |
| taint.cpp:333:6:333:6 | 0 | taint.cpp:333:2:333:6 | ... = ... | |
| taint.cpp:333:6:333:6 | 0 | taint.cpp:340:7:340:7 | c | |
| taint.cpp:333:6:333:6 | 0 | taint.cpp:346:13:346:13 | c | |
| taint.cpp:333:6:333:6 | 0 | taint.cpp:353:7:353:7 | c | |
| taint.cpp:334:6:334:6 | 0 | taint.cpp:334:2:334:6 | ... = ... | |
| taint.cpp:334:6:334:6 | 0 | taint.cpp:341:7:341:7 | d | |
| taint.cpp:334:6:334:6 | 0 | taint.cpp:347:13:347:13 | d | |
| taint.cpp:334:6:334:6 | 0 | taint.cpp:354:7:354:7 | d | |
| taint.cpp:335:6:335:6 | 0 | taint.cpp:335:2:335:6 | ... = ... | |
| taint.cpp:335:6:335:6 | 0 | taint.cpp:342:7:342:7 | e | |
| taint.cpp:335:6:335:6 | 0 | taint.cpp:348:14:348:14 | e | |
| taint.cpp:335:6:335:6 | 0 | taint.cpp:355:7:355:7 | e | |
| taint.cpp:344:12:344:12 | ref arg a | taint.cpp:351:7:351:7 | a | |
| taint.cpp:344:15:344:15 | ref arg t | taint.cpp:345:15:345:15 | t | |
| taint.cpp:344:15:344:15 | ref arg t | taint.cpp:346:16:346:16 | t | |
| taint.cpp:344:15:344:15 | ref arg t | taint.cpp:347:16:347:16 | t | |
| taint.cpp:344:15:344:15 | ref arg t | taint.cpp:348:17:348:17 | t | |
| taint.cpp:344:15:344:15 | ref arg t | taint.cpp:350:7:350:7 | t | |
| taint.cpp:345:12:345:12 | ref arg b | taint.cpp:352:7:352:7 | b | |
| taint.cpp:346:12:346:13 | ref arg & ... | taint.cpp:353:7:353:7 | c | |
| taint.cpp:346:13:346:13 | c | taint.cpp:346:12:346:13 | & ... | |
| taint.cpp:347:12:347:13 | ref arg & ... | taint.cpp:354:7:354:7 | d | |
| taint.cpp:347:13:347:13 | d | taint.cpp:347:12:347:13 | & ... | |
| taint.cpp:348:14:348:14 | ref arg e | taint.cpp:355:7:355:7 | e | |
| taint.cpp:348:17:348:17 | ref arg t | taint.cpp:350:7:350:7 | t | |

View File

@@ -260,3 +260,97 @@ void test_lambdas()
e(t, u, w);
sink(w); // tainted
}
// --- taint through return value ---
int id(int x)
{
return x;
}
void test_return()
{
int x, y, z, t;
t = source();
x = 0;
y = 0;
z = 0;
sink(t); // tainted
sink(x);
sink(y);
sink(z);
x = id(t);
y = id(id(t));
z = id(z);
sink(t); // tainted
sink(x); // tainted
sink(y); // tainted
sink(z);
}
// --- taint through parameters ---
void myAssign1(int &a, int &b)
{
a = b;
}
void myAssign2(int &a, int b)
{
a = b;
}
void myAssign3(int *a, int b)
{
*a = b;
}
void myAssign4(int *a, int b)
{
int c;
c = b + 1;
*a = c;
}
void myNotAssign(int &a, int &b)
{
a = a + 1;
b = b + 1;
}
void test_outparams()
{
int t, a, b, c, d, e;
t = source();
a = 0;
b = 0;
c = 0;
d = 0;
e = 0;
sink(t); // tainted
sink(a);
sink(b);
sink(c);
sink(d);
sink(e);
myAssign1(a, t);
myAssign2(b, t);
myAssign3(&c, t);
myAssign4(&d, t);
myNotAssign(e, t);
sink(t); // tainted
sink(a); // tainted
sink(b); // tainted
sink(c); // tainted [NOT DETECTED]
sink(d); // tainted [NOT DETECTED]
sink(e);
}

View File

@@ -29,3 +29,11 @@
| taint.cpp:250:8:250:8 | a | taint.cpp:223:10:223:15 | call to source |
| taint.cpp:256:8:256:8 | a | taint.cpp:223:10:223:15 | call to source |
| taint.cpp:261:7:261:7 | w | taint.cpp:258:7:258:12 | call to source |
| taint.cpp:280:7:280:7 | t | taint.cpp:275:6:275:11 | call to source |
| taint.cpp:289:7:289:7 | t | taint.cpp:275:6:275:11 | call to source |
| taint.cpp:290:7:290:7 | x | taint.cpp:275:6:275:11 | call to source |
| taint.cpp:291:7:291:7 | y | taint.cpp:275:6:275:11 | call to source |
| taint.cpp:337:7:337:7 | t | taint.cpp:330:6:330:11 | call to source |
| taint.cpp:350:7:350:7 | t | taint.cpp:330:6:330:11 | call to source |
| taint.cpp:351:7:351:7 | a | taint.cpp:330:6:330:11 | call to source |
| taint.cpp:352:7:352:7 | b | taint.cpp:330:6:330:11 | call to source |

View File

@@ -22,3 +22,6 @@
| taint.cpp:250:8:250:8 | taint.cpp:223:10:223:15 | AST only |
| taint.cpp:256:8:256:8 | taint.cpp:223:10:223:15 | AST only |
| taint.cpp:261:7:261:7 | taint.cpp:258:7:258:12 | AST only |
| taint.cpp:350:7:350:7 | taint.cpp:330:6:330:11 | AST only |
| taint.cpp:351:7:351:7 | taint.cpp:330:6:330:11 | AST only |
| taint.cpp:352:7:352:7 | taint.cpp:330:6:330:11 | AST only |

View File

@@ -9,3 +9,8 @@
| taint.cpp:167:8:167:13 | Call: call to source | taint.cpp:167:8:167:13 | Call: call to source |
| taint.cpp:168:8:168:14 | Load: tainted | taint.cpp:164:19:164:24 | Call: call to source |
| taint.cpp:210:7:210:7 | Load: x | taint.cpp:207:6:207:11 | Call: call to source |
| taint.cpp:280:7:280:7 | Load: t | taint.cpp:275:6:275:11 | Call: call to source |
| taint.cpp:289:7:289:7 | Load: t | taint.cpp:275:6:275:11 | Call: call to source |
| taint.cpp:290:7:290:7 | Load: x | taint.cpp:275:6:275:11 | Call: call to source |
| taint.cpp:291:7:291:7 | Load: y | taint.cpp:275:6:275:11 | Call: call to source |
| taint.cpp:337:7:337:7 | Load: t | taint.cpp:330:6:330:11 | Call: call to source |