mirror of
https://github.com/github/codeql.git
synced 2025-12-18 01:33:15 +01:00
Merge branch 'main' into redundantImport
This commit is contained in:
@@ -1,3 +1,17 @@
|
||||
## 0.1.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* The recently added flow-state versions of `isBarrierIn`, `isBarrierOut`, `isSanitizerIn`, and `isSanitizerOut` in the data flow and taint tracking libraries have been removed.
|
||||
|
||||
### New Features
|
||||
|
||||
* A new library `semmle.code.cpp.security.PrivateData` has been added. The new library heuristically detects variables and functions dealing with sensitive private data, such as e-mail addresses and credit card numbers.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The `semmle.code.cpp.security.SensitiveExprs` library has been enhanced with some additional rules for detecting credentials.
|
||||
|
||||
## 0.0.13
|
||||
|
||||
## 0.0.12
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* A new library `semmle.code.cpp.security.PrivateData` has been added. The new library heuristically detects variables and functions dealing with sensitive private data, such as e-mail addresses and credit card numbers.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The `semmle.code.cpp.security.SensitiveExprs` library has been enhanced with some additional rules for detecting credentials.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
The recently added flow-state versions of `isBarrierIn`, `isBarrierOut`, `isSanitizerIn`, and `isSanitizerOut` in the data flow and taint tracking libraries have been removed.
|
||||
4
cpp/ql/lib/change-notes/2022-04-22-no-size-array.md
Normal file
4
cpp/ql/lib/change-notes/2022-04-22-no-size-array.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The `semmle.code.cpp.commons.Buffer` library has been enhanced to handle array members of classes that do not specify a size.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
The signature of `allowImplicitRead` on `DataFlow::Configuration` and `TaintTracking::Configuration` has changed from `allowImplicitRead(DataFlow::Node node, DataFlow::Content c)` to `allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c)`.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* More Windows pool allocation functions are now detected as `AllocationFunction`s.
|
||||
13
cpp/ql/lib/change-notes/released/0.1.0.md
Normal file
13
cpp/ql/lib/change-notes/released/0.1.0.md
Normal file
@@ -0,0 +1,13 @@
|
||||
## 0.1.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* The recently added flow-state versions of `isBarrierIn`, `isBarrierOut`, `isSanitizerIn`, and `isSanitizerOut` in the data flow and taint tracking libraries have been removed.
|
||||
|
||||
### New Features
|
||||
|
||||
* A new library `semmle.code.cpp.security.PrivateData` has been added. The new library heuristically detects variables and functions dealing with sensitive private data, such as e-mail addresses and credit card numbers.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The `semmle.code.cpp.security.SensitiveExprs` library has been enhanced with some additional rules for detecting credentials.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.13
|
||||
lastReleaseVersion: 0.1.0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.1.0-dev
|
||||
version: 0.1.1-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -10,11 +10,18 @@ import semmle.code.cpp.dataflow.DataFlow
|
||||
* char data[1]; // v
|
||||
* };
|
||||
* ```
|
||||
* This requires that `v` is an array of size 0 or 1.
|
||||
* or
|
||||
* ```
|
||||
* struct myStruct { // c
|
||||
* int amount;
|
||||
* char data[]; // v
|
||||
* };
|
||||
* ```
|
||||
* This requires that `v` is an array of size 0 or 1, or that the array has no size.
|
||||
*/
|
||||
predicate memberMayBeVarSize(Class c, MemberVariable v) {
|
||||
c = v.getDeclaringType() and
|
||||
v.getUnspecifiedType().(ArrayType).getArraySize() <= 1
|
||||
exists(ArrayType t | t = v.getUnspecifiedType() | not t.getArraySize() > 1)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -40,13 +47,18 @@ int getBufferSize(Expr bufferExpr, Element why) {
|
||||
result = why.(Expr).getType().(ArrayType).getSize() and
|
||||
not exists(bufferVar.getUnspecifiedType().(ArrayType).getSize())
|
||||
or
|
||||
exists(Class parentClass, VariableAccess parentPtr |
|
||||
exists(Class parentClass, VariableAccess parentPtr, int bufferSize |
|
||||
// buffer is the parentPtr->bufferVar of a 'variable size struct'
|
||||
memberMayBeVarSize(parentClass, bufferVar) and
|
||||
why = bufferVar and
|
||||
parentPtr = bufferExpr.(VariableAccess).getQualifier() and
|
||||
parentPtr.getTarget().getUnspecifiedType().(PointerType).getBaseType() = parentClass and
|
||||
result = getBufferSize(parentPtr, _) + bufferVar.getType().getSize() - parentClass.getSize()
|
||||
(
|
||||
if exists(bufferVar.getType().getSize())
|
||||
then bufferSize = bufferVar.getType().getSize()
|
||||
else bufferSize = 0
|
||||
) and
|
||||
result = getBufferSize(parentPtr, _) + bufferSize - parentClass.getSize()
|
||||
)
|
||||
)
|
||||
or
|
||||
|
||||
@@ -116,7 +116,7 @@ abstract class Configuration extends string {
|
||||
* Holds if an arbitrary number of implicit read steps of content `c` may be
|
||||
* taken at `node`.
|
||||
*/
|
||||
predicate allowImplicitRead(Node node, Content c) { none() }
|
||||
predicate allowImplicitRead(Node node, ContentSet c) { none() }
|
||||
|
||||
/**
|
||||
* Gets the virtual dispatch branching limit when calculating field flow.
|
||||
@@ -485,8 +485,9 @@ private predicate additionalJumpStateStep(
|
||||
)
|
||||
}
|
||||
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
read(node1.asNode(), c, node2.asNode()) and
|
||||
pragma[nomagic]
|
||||
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
|
||||
readSet(node1.asNode(), c, node2.asNode()) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
@@ -496,6 +497,25 @@ private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration conf
|
||||
)
|
||||
}
|
||||
|
||||
// inline to reduce fan-out via `getAReadContent`
|
||||
pragma[inline]
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
exists(ContentSet cs |
|
||||
readSet(node1, cs, node2, config) and
|
||||
c = cs.getAReadContent()
|
||||
)
|
||||
}
|
||||
|
||||
// inline to reduce fan-out via `getAReadContent`
|
||||
pragma[inline]
|
||||
private predicate clearsContentEx(NodeEx n, Content c) {
|
||||
exists(ContentSet cs |
|
||||
clearsContentCached(n.asNode(), cs) and
|
||||
c = cs.getAReadContent()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
@@ -573,9 +593,9 @@ private module Stage1 {
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config)
|
||||
exists(ContentSet c |
|
||||
fwdFlowReadSet(c, node, cc, config) and
|
||||
fwdFlowConsCandSet(c, _, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
@@ -599,10 +619,10 @@ private module Stage1 {
|
||||
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowRead(Content c, NodeEx node, Cc cc, Configuration config) {
|
||||
private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) {
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
read(mid, c, node, config)
|
||||
readSet(mid, c, node, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -620,6 +640,16 @@ private module Stage1 {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `cs` may be interpreted in a read as the target of some store
|
||||
* into `c`, in the flow covered by `fwdFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) {
|
||||
fwdFlowConsCand(c, config) and
|
||||
c = cs.getAReadContent()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) {
|
||||
exists(RetNodeEx ret |
|
||||
@@ -712,9 +742,9 @@ private module Stage1 {
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(NodeEx mid, Content c |
|
||||
read(node, c, mid, config) and
|
||||
fwdFlowConsCand(c, pragma[only_bind_into](config)) and
|
||||
exists(NodeEx mid, ContentSet c |
|
||||
readSet(node, c, mid, config) and
|
||||
fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and
|
||||
revFlow(mid, toReturn, pragma[only_bind_into](config))
|
||||
)
|
||||
or
|
||||
@@ -740,10 +770,10 @@ private module Stage1 {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate revFlowConsCand(Content c, Configuration config) {
|
||||
exists(NodeEx mid, NodeEx node |
|
||||
exists(NodeEx mid, NodeEx node, ContentSet cs |
|
||||
fwdFlow(node, pragma[only_bind_into](config)) and
|
||||
read(node, c, mid, config) and
|
||||
fwdFlowConsCand(c, pragma[only_bind_into](config)) and
|
||||
readSet(node, cs, mid, config) and
|
||||
fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and
|
||||
revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -762,6 +792,7 @@ private module Stage1 {
|
||||
* Holds if `c` is the target of both a read and a store in the flow covered
|
||||
* by `revFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
revFlowConsCand(c, conf) and
|
||||
revFlowStore(c, _, _, conf)
|
||||
@@ -860,9 +891,9 @@ private module Stage1 {
|
||||
|
||||
pragma[nomagic]
|
||||
predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) {
|
||||
revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
|
||||
revFlow(n2, pragma[only_bind_into](config)) and
|
||||
read(n1, c, n2, pragma[only_bind_into](config))
|
||||
revFlowIsReadAndStored(pragma[only_bind_into](c), pragma[only_bind_into](config)) and
|
||||
read(n1, c, n2, pragma[only_bind_into](config)) and
|
||||
revFlow(n2, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -872,7 +903,10 @@ private module Stage1 {
|
||||
predicate revFlow(
|
||||
NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlow(node, toReturn, config) and exists(state) and exists(returnAp) and exists(ap)
|
||||
revFlow(node, toReturn, pragma[only_bind_into](config)) and
|
||||
exists(state) and
|
||||
exists(returnAp) and
|
||||
exists(ap)
|
||||
}
|
||||
|
||||
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
|
||||
@@ -1149,7 +1183,7 @@ private module Stage2 {
|
||||
|
||||
bindingset[node, state, ap, config]
|
||||
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
PrevStage::revFlowState(state, config) and
|
||||
PrevStage::revFlowState(state, pragma[only_bind_into](config)) and
|
||||
exists(ap) and
|
||||
not stateBarrier(node, state, config)
|
||||
}
|
||||
@@ -1574,7 +1608,7 @@ private module Stage2 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -1729,9 +1763,9 @@ private module LocalFlowBigStep {
|
||||
or
|
||||
node.asNode() instanceof OutNodeExt
|
||||
or
|
||||
store(_, _, node, _, config)
|
||||
Stage2::storeStepCand(_, _, _, node, _, config)
|
||||
or
|
||||
read(_, _, node, config)
|
||||
Stage2::readStepCand(_, _, node, config)
|
||||
or
|
||||
node instanceof FlowCheckNode
|
||||
or
|
||||
@@ -1752,8 +1786,8 @@ private module LocalFlowBigStep {
|
||||
additionalJumpStep(node, next, config) or
|
||||
flowIntoCallNodeCand1(_, node, next, config) or
|
||||
flowOutOfCallNodeCand1(_, node, next, config) or
|
||||
store(node, _, next, _, config) or
|
||||
read(node, _, next, config)
|
||||
Stage2::storeStepCand(node, _, _, next, _, config) or
|
||||
Stage2::readStepCand(node, _, next, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
|
||||
@@ -1926,7 +1960,24 @@ private module Stage3 {
|
||||
private predicate flowIntoCall = flowIntoCallNodeCand2/5;
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clear(NodeEx node, Ap ap) { ap.isClearedAt(node.asNode()) }
|
||||
private predicate clearSet(NodeEx node, ContentSet c, Configuration config) {
|
||||
PrevStage::revFlow(node, config) and
|
||||
clearsContentCached(node.asNode(), c)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clearContent(NodeEx node, Content c, Configuration config) {
|
||||
exists(ContentSet cs |
|
||||
PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and
|
||||
c = cs.getAReadContent() and
|
||||
clearSet(node, cs, pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clear(NodeEx node, Ap ap, Configuration config) {
|
||||
clearContent(node, ap.getHead().getContent(), config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode }
|
||||
@@ -1935,7 +1986,7 @@ private module Stage3 {
|
||||
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
exists(state) and
|
||||
exists(config) and
|
||||
not clear(node, ap) and
|
||||
not clear(node, ap, config) and
|
||||
if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()
|
||||
}
|
||||
|
||||
@@ -2363,7 +2414,7 @@ private module Stage3 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -3190,7 +3241,7 @@ private module Stage4 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -4202,7 +4253,7 @@ private module Subpaths {
|
||||
exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() |
|
||||
localFlowBigStep(n1, _, n2, _, _, _, _, _) or
|
||||
store(n1, _, n2, _, _) or
|
||||
read(n1, _, n2, _)
|
||||
readSet(n1, _, n2, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4557,7 +4608,7 @@ private module FlowExploration {
|
||||
or
|
||||
exists(PartialPathNodeRev mid |
|
||||
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
|
||||
not clearsContentCached(node.asNode(), ap.getHead()) and
|
||||
not clearsContentEx(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
not stateBarrier(node, state, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
@@ -4573,7 +4624,7 @@ private module FlowExploration {
|
||||
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
|
||||
not fullBarrier(node, config) and
|
||||
not stateBarrier(node, state, config) and
|
||||
not clearsContentCached(node.asNode(), ap.getHead().getContent()) and
|
||||
not clearsContentEx(node, ap.getHead().getContent()) and
|
||||
if node.asNode() instanceof CastingNode
|
||||
then compatibleTypes(node.getDataFlowType(), ap.getType())
|
||||
else any()
|
||||
|
||||
@@ -116,7 +116,7 @@ abstract class Configuration extends string {
|
||||
* Holds if an arbitrary number of implicit read steps of content `c` may be
|
||||
* taken at `node`.
|
||||
*/
|
||||
predicate allowImplicitRead(Node node, Content c) { none() }
|
||||
predicate allowImplicitRead(Node node, ContentSet c) { none() }
|
||||
|
||||
/**
|
||||
* Gets the virtual dispatch branching limit when calculating field flow.
|
||||
@@ -485,8 +485,9 @@ private predicate additionalJumpStateStep(
|
||||
)
|
||||
}
|
||||
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
read(node1.asNode(), c, node2.asNode()) and
|
||||
pragma[nomagic]
|
||||
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
|
||||
readSet(node1.asNode(), c, node2.asNode()) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
@@ -496,6 +497,25 @@ private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration conf
|
||||
)
|
||||
}
|
||||
|
||||
// inline to reduce fan-out via `getAReadContent`
|
||||
pragma[inline]
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
exists(ContentSet cs |
|
||||
readSet(node1, cs, node2, config) and
|
||||
c = cs.getAReadContent()
|
||||
)
|
||||
}
|
||||
|
||||
// inline to reduce fan-out via `getAReadContent`
|
||||
pragma[inline]
|
||||
private predicate clearsContentEx(NodeEx n, Content c) {
|
||||
exists(ContentSet cs |
|
||||
clearsContentCached(n.asNode(), cs) and
|
||||
c = cs.getAReadContent()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
@@ -573,9 +593,9 @@ private module Stage1 {
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config)
|
||||
exists(ContentSet c |
|
||||
fwdFlowReadSet(c, node, cc, config) and
|
||||
fwdFlowConsCandSet(c, _, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
@@ -599,10 +619,10 @@ private module Stage1 {
|
||||
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowRead(Content c, NodeEx node, Cc cc, Configuration config) {
|
||||
private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) {
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
read(mid, c, node, config)
|
||||
readSet(mid, c, node, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -620,6 +640,16 @@ private module Stage1 {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `cs` may be interpreted in a read as the target of some store
|
||||
* into `c`, in the flow covered by `fwdFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) {
|
||||
fwdFlowConsCand(c, config) and
|
||||
c = cs.getAReadContent()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) {
|
||||
exists(RetNodeEx ret |
|
||||
@@ -712,9 +742,9 @@ private module Stage1 {
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(NodeEx mid, Content c |
|
||||
read(node, c, mid, config) and
|
||||
fwdFlowConsCand(c, pragma[only_bind_into](config)) and
|
||||
exists(NodeEx mid, ContentSet c |
|
||||
readSet(node, c, mid, config) and
|
||||
fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and
|
||||
revFlow(mid, toReturn, pragma[only_bind_into](config))
|
||||
)
|
||||
or
|
||||
@@ -740,10 +770,10 @@ private module Stage1 {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate revFlowConsCand(Content c, Configuration config) {
|
||||
exists(NodeEx mid, NodeEx node |
|
||||
exists(NodeEx mid, NodeEx node, ContentSet cs |
|
||||
fwdFlow(node, pragma[only_bind_into](config)) and
|
||||
read(node, c, mid, config) and
|
||||
fwdFlowConsCand(c, pragma[only_bind_into](config)) and
|
||||
readSet(node, cs, mid, config) and
|
||||
fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and
|
||||
revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -762,6 +792,7 @@ private module Stage1 {
|
||||
* Holds if `c` is the target of both a read and a store in the flow covered
|
||||
* by `revFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
revFlowConsCand(c, conf) and
|
||||
revFlowStore(c, _, _, conf)
|
||||
@@ -860,9 +891,9 @@ private module Stage1 {
|
||||
|
||||
pragma[nomagic]
|
||||
predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) {
|
||||
revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
|
||||
revFlow(n2, pragma[only_bind_into](config)) and
|
||||
read(n1, c, n2, pragma[only_bind_into](config))
|
||||
revFlowIsReadAndStored(pragma[only_bind_into](c), pragma[only_bind_into](config)) and
|
||||
read(n1, c, n2, pragma[only_bind_into](config)) and
|
||||
revFlow(n2, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -872,7 +903,10 @@ private module Stage1 {
|
||||
predicate revFlow(
|
||||
NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlow(node, toReturn, config) and exists(state) and exists(returnAp) and exists(ap)
|
||||
revFlow(node, toReturn, pragma[only_bind_into](config)) and
|
||||
exists(state) and
|
||||
exists(returnAp) and
|
||||
exists(ap)
|
||||
}
|
||||
|
||||
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
|
||||
@@ -1149,7 +1183,7 @@ private module Stage2 {
|
||||
|
||||
bindingset[node, state, ap, config]
|
||||
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
PrevStage::revFlowState(state, config) and
|
||||
PrevStage::revFlowState(state, pragma[only_bind_into](config)) and
|
||||
exists(ap) and
|
||||
not stateBarrier(node, state, config)
|
||||
}
|
||||
@@ -1574,7 +1608,7 @@ private module Stage2 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -1729,9 +1763,9 @@ private module LocalFlowBigStep {
|
||||
or
|
||||
node.asNode() instanceof OutNodeExt
|
||||
or
|
||||
store(_, _, node, _, config)
|
||||
Stage2::storeStepCand(_, _, _, node, _, config)
|
||||
or
|
||||
read(_, _, node, config)
|
||||
Stage2::readStepCand(_, _, node, config)
|
||||
or
|
||||
node instanceof FlowCheckNode
|
||||
or
|
||||
@@ -1752,8 +1786,8 @@ private module LocalFlowBigStep {
|
||||
additionalJumpStep(node, next, config) or
|
||||
flowIntoCallNodeCand1(_, node, next, config) or
|
||||
flowOutOfCallNodeCand1(_, node, next, config) or
|
||||
store(node, _, next, _, config) or
|
||||
read(node, _, next, config)
|
||||
Stage2::storeStepCand(node, _, _, next, _, config) or
|
||||
Stage2::readStepCand(node, _, next, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
|
||||
@@ -1926,7 +1960,24 @@ private module Stage3 {
|
||||
private predicate flowIntoCall = flowIntoCallNodeCand2/5;
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clear(NodeEx node, Ap ap) { ap.isClearedAt(node.asNode()) }
|
||||
private predicate clearSet(NodeEx node, ContentSet c, Configuration config) {
|
||||
PrevStage::revFlow(node, config) and
|
||||
clearsContentCached(node.asNode(), c)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clearContent(NodeEx node, Content c, Configuration config) {
|
||||
exists(ContentSet cs |
|
||||
PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and
|
||||
c = cs.getAReadContent() and
|
||||
clearSet(node, cs, pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clear(NodeEx node, Ap ap, Configuration config) {
|
||||
clearContent(node, ap.getHead().getContent(), config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode }
|
||||
@@ -1935,7 +1986,7 @@ private module Stage3 {
|
||||
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
exists(state) and
|
||||
exists(config) and
|
||||
not clear(node, ap) and
|
||||
not clear(node, ap, config) and
|
||||
if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()
|
||||
}
|
||||
|
||||
@@ -2363,7 +2414,7 @@ private module Stage3 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -3190,7 +3241,7 @@ private module Stage4 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -4202,7 +4253,7 @@ private module Subpaths {
|
||||
exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() |
|
||||
localFlowBigStep(n1, _, n2, _, _, _, _, _) or
|
||||
store(n1, _, n2, _, _) or
|
||||
read(n1, _, n2, _)
|
||||
readSet(n1, _, n2, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4557,7 +4608,7 @@ private module FlowExploration {
|
||||
or
|
||||
exists(PartialPathNodeRev mid |
|
||||
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
|
||||
not clearsContentCached(node.asNode(), ap.getHead()) and
|
||||
not clearsContentEx(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
not stateBarrier(node, state, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
@@ -4573,7 +4624,7 @@ private module FlowExploration {
|
||||
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
|
||||
not fullBarrier(node, config) and
|
||||
not stateBarrier(node, state, config) and
|
||||
not clearsContentCached(node.asNode(), ap.getHead().getContent()) and
|
||||
not clearsContentEx(node, ap.getHead().getContent()) and
|
||||
if node.asNode() instanceof CastingNode
|
||||
then compatibleTypes(node.getDataFlowType(), ap.getType())
|
||||
else any()
|
||||
|
||||
@@ -116,7 +116,7 @@ abstract class Configuration extends string {
|
||||
* Holds if an arbitrary number of implicit read steps of content `c` may be
|
||||
* taken at `node`.
|
||||
*/
|
||||
predicate allowImplicitRead(Node node, Content c) { none() }
|
||||
predicate allowImplicitRead(Node node, ContentSet c) { none() }
|
||||
|
||||
/**
|
||||
* Gets the virtual dispatch branching limit when calculating field flow.
|
||||
@@ -485,8 +485,9 @@ private predicate additionalJumpStateStep(
|
||||
)
|
||||
}
|
||||
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
read(node1.asNode(), c, node2.asNode()) and
|
||||
pragma[nomagic]
|
||||
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
|
||||
readSet(node1.asNode(), c, node2.asNode()) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
@@ -496,6 +497,25 @@ private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration conf
|
||||
)
|
||||
}
|
||||
|
||||
// inline to reduce fan-out via `getAReadContent`
|
||||
pragma[inline]
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
exists(ContentSet cs |
|
||||
readSet(node1, cs, node2, config) and
|
||||
c = cs.getAReadContent()
|
||||
)
|
||||
}
|
||||
|
||||
// inline to reduce fan-out via `getAReadContent`
|
||||
pragma[inline]
|
||||
private predicate clearsContentEx(NodeEx n, Content c) {
|
||||
exists(ContentSet cs |
|
||||
clearsContentCached(n.asNode(), cs) and
|
||||
c = cs.getAReadContent()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
@@ -573,9 +593,9 @@ private module Stage1 {
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config)
|
||||
exists(ContentSet c |
|
||||
fwdFlowReadSet(c, node, cc, config) and
|
||||
fwdFlowConsCandSet(c, _, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
@@ -599,10 +619,10 @@ private module Stage1 {
|
||||
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowRead(Content c, NodeEx node, Cc cc, Configuration config) {
|
||||
private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) {
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
read(mid, c, node, config)
|
||||
readSet(mid, c, node, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -620,6 +640,16 @@ private module Stage1 {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `cs` may be interpreted in a read as the target of some store
|
||||
* into `c`, in the flow covered by `fwdFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) {
|
||||
fwdFlowConsCand(c, config) and
|
||||
c = cs.getAReadContent()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) {
|
||||
exists(RetNodeEx ret |
|
||||
@@ -712,9 +742,9 @@ private module Stage1 {
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(NodeEx mid, Content c |
|
||||
read(node, c, mid, config) and
|
||||
fwdFlowConsCand(c, pragma[only_bind_into](config)) and
|
||||
exists(NodeEx mid, ContentSet c |
|
||||
readSet(node, c, mid, config) and
|
||||
fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and
|
||||
revFlow(mid, toReturn, pragma[only_bind_into](config))
|
||||
)
|
||||
or
|
||||
@@ -740,10 +770,10 @@ private module Stage1 {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate revFlowConsCand(Content c, Configuration config) {
|
||||
exists(NodeEx mid, NodeEx node |
|
||||
exists(NodeEx mid, NodeEx node, ContentSet cs |
|
||||
fwdFlow(node, pragma[only_bind_into](config)) and
|
||||
read(node, c, mid, config) and
|
||||
fwdFlowConsCand(c, pragma[only_bind_into](config)) and
|
||||
readSet(node, cs, mid, config) and
|
||||
fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and
|
||||
revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -762,6 +792,7 @@ private module Stage1 {
|
||||
* Holds if `c` is the target of both a read and a store in the flow covered
|
||||
* by `revFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
revFlowConsCand(c, conf) and
|
||||
revFlowStore(c, _, _, conf)
|
||||
@@ -860,9 +891,9 @@ private module Stage1 {
|
||||
|
||||
pragma[nomagic]
|
||||
predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) {
|
||||
revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
|
||||
revFlow(n2, pragma[only_bind_into](config)) and
|
||||
read(n1, c, n2, pragma[only_bind_into](config))
|
||||
revFlowIsReadAndStored(pragma[only_bind_into](c), pragma[only_bind_into](config)) and
|
||||
read(n1, c, n2, pragma[only_bind_into](config)) and
|
||||
revFlow(n2, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -872,7 +903,10 @@ private module Stage1 {
|
||||
predicate revFlow(
|
||||
NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlow(node, toReturn, config) and exists(state) and exists(returnAp) and exists(ap)
|
||||
revFlow(node, toReturn, pragma[only_bind_into](config)) and
|
||||
exists(state) and
|
||||
exists(returnAp) and
|
||||
exists(ap)
|
||||
}
|
||||
|
||||
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
|
||||
@@ -1149,7 +1183,7 @@ private module Stage2 {
|
||||
|
||||
bindingset[node, state, ap, config]
|
||||
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
PrevStage::revFlowState(state, config) and
|
||||
PrevStage::revFlowState(state, pragma[only_bind_into](config)) and
|
||||
exists(ap) and
|
||||
not stateBarrier(node, state, config)
|
||||
}
|
||||
@@ -1574,7 +1608,7 @@ private module Stage2 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -1729,9 +1763,9 @@ private module LocalFlowBigStep {
|
||||
or
|
||||
node.asNode() instanceof OutNodeExt
|
||||
or
|
||||
store(_, _, node, _, config)
|
||||
Stage2::storeStepCand(_, _, _, node, _, config)
|
||||
or
|
||||
read(_, _, node, config)
|
||||
Stage2::readStepCand(_, _, node, config)
|
||||
or
|
||||
node instanceof FlowCheckNode
|
||||
or
|
||||
@@ -1752,8 +1786,8 @@ private module LocalFlowBigStep {
|
||||
additionalJumpStep(node, next, config) or
|
||||
flowIntoCallNodeCand1(_, node, next, config) or
|
||||
flowOutOfCallNodeCand1(_, node, next, config) or
|
||||
store(node, _, next, _, config) or
|
||||
read(node, _, next, config)
|
||||
Stage2::storeStepCand(node, _, _, next, _, config) or
|
||||
Stage2::readStepCand(node, _, next, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
|
||||
@@ -1926,7 +1960,24 @@ private module Stage3 {
|
||||
private predicate flowIntoCall = flowIntoCallNodeCand2/5;
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clear(NodeEx node, Ap ap) { ap.isClearedAt(node.asNode()) }
|
||||
private predicate clearSet(NodeEx node, ContentSet c, Configuration config) {
|
||||
PrevStage::revFlow(node, config) and
|
||||
clearsContentCached(node.asNode(), c)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clearContent(NodeEx node, Content c, Configuration config) {
|
||||
exists(ContentSet cs |
|
||||
PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and
|
||||
c = cs.getAReadContent() and
|
||||
clearSet(node, cs, pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clear(NodeEx node, Ap ap, Configuration config) {
|
||||
clearContent(node, ap.getHead().getContent(), config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode }
|
||||
@@ -1935,7 +1986,7 @@ private module Stage3 {
|
||||
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
exists(state) and
|
||||
exists(config) and
|
||||
not clear(node, ap) and
|
||||
not clear(node, ap, config) and
|
||||
if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()
|
||||
}
|
||||
|
||||
@@ -2363,7 +2414,7 @@ private module Stage3 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -3190,7 +3241,7 @@ private module Stage4 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -4202,7 +4253,7 @@ private module Subpaths {
|
||||
exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() |
|
||||
localFlowBigStep(n1, _, n2, _, _, _, _, _) or
|
||||
store(n1, _, n2, _, _) or
|
||||
read(n1, _, n2, _)
|
||||
readSet(n1, _, n2, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4557,7 +4608,7 @@ private module FlowExploration {
|
||||
or
|
||||
exists(PartialPathNodeRev mid |
|
||||
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
|
||||
not clearsContentCached(node.asNode(), ap.getHead()) and
|
||||
not clearsContentEx(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
not stateBarrier(node, state, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
@@ -4573,7 +4624,7 @@ private module FlowExploration {
|
||||
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
|
||||
not fullBarrier(node, config) and
|
||||
not stateBarrier(node, state, config) and
|
||||
not clearsContentCached(node.asNode(), ap.getHead().getContent()) and
|
||||
not clearsContentEx(node, ap.getHead().getContent()) and
|
||||
if node.asNode() instanceof CastingNode
|
||||
then compatibleTypes(node.getDataFlowType(), ap.getType())
|
||||
else any()
|
||||
|
||||
@@ -116,7 +116,7 @@ abstract class Configuration extends string {
|
||||
* Holds if an arbitrary number of implicit read steps of content `c` may be
|
||||
* taken at `node`.
|
||||
*/
|
||||
predicate allowImplicitRead(Node node, Content c) { none() }
|
||||
predicate allowImplicitRead(Node node, ContentSet c) { none() }
|
||||
|
||||
/**
|
||||
* Gets the virtual dispatch branching limit when calculating field flow.
|
||||
@@ -485,8 +485,9 @@ private predicate additionalJumpStateStep(
|
||||
)
|
||||
}
|
||||
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
read(node1.asNode(), c, node2.asNode()) and
|
||||
pragma[nomagic]
|
||||
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
|
||||
readSet(node1.asNode(), c, node2.asNode()) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
@@ -496,6 +497,25 @@ private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration conf
|
||||
)
|
||||
}
|
||||
|
||||
// inline to reduce fan-out via `getAReadContent`
|
||||
pragma[inline]
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
exists(ContentSet cs |
|
||||
readSet(node1, cs, node2, config) and
|
||||
c = cs.getAReadContent()
|
||||
)
|
||||
}
|
||||
|
||||
// inline to reduce fan-out via `getAReadContent`
|
||||
pragma[inline]
|
||||
private predicate clearsContentEx(NodeEx n, Content c) {
|
||||
exists(ContentSet cs |
|
||||
clearsContentCached(n.asNode(), cs) and
|
||||
c = cs.getAReadContent()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
@@ -573,9 +593,9 @@ private module Stage1 {
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config)
|
||||
exists(ContentSet c |
|
||||
fwdFlowReadSet(c, node, cc, config) and
|
||||
fwdFlowConsCandSet(c, _, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
@@ -599,10 +619,10 @@ private module Stage1 {
|
||||
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowRead(Content c, NodeEx node, Cc cc, Configuration config) {
|
||||
private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) {
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
read(mid, c, node, config)
|
||||
readSet(mid, c, node, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -620,6 +640,16 @@ private module Stage1 {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `cs` may be interpreted in a read as the target of some store
|
||||
* into `c`, in the flow covered by `fwdFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) {
|
||||
fwdFlowConsCand(c, config) and
|
||||
c = cs.getAReadContent()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) {
|
||||
exists(RetNodeEx ret |
|
||||
@@ -712,9 +742,9 @@ private module Stage1 {
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(NodeEx mid, Content c |
|
||||
read(node, c, mid, config) and
|
||||
fwdFlowConsCand(c, pragma[only_bind_into](config)) and
|
||||
exists(NodeEx mid, ContentSet c |
|
||||
readSet(node, c, mid, config) and
|
||||
fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and
|
||||
revFlow(mid, toReturn, pragma[only_bind_into](config))
|
||||
)
|
||||
or
|
||||
@@ -740,10 +770,10 @@ private module Stage1 {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate revFlowConsCand(Content c, Configuration config) {
|
||||
exists(NodeEx mid, NodeEx node |
|
||||
exists(NodeEx mid, NodeEx node, ContentSet cs |
|
||||
fwdFlow(node, pragma[only_bind_into](config)) and
|
||||
read(node, c, mid, config) and
|
||||
fwdFlowConsCand(c, pragma[only_bind_into](config)) and
|
||||
readSet(node, cs, mid, config) and
|
||||
fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and
|
||||
revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -762,6 +792,7 @@ private module Stage1 {
|
||||
* Holds if `c` is the target of both a read and a store in the flow covered
|
||||
* by `revFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
revFlowConsCand(c, conf) and
|
||||
revFlowStore(c, _, _, conf)
|
||||
@@ -860,9 +891,9 @@ private module Stage1 {
|
||||
|
||||
pragma[nomagic]
|
||||
predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) {
|
||||
revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
|
||||
revFlow(n2, pragma[only_bind_into](config)) and
|
||||
read(n1, c, n2, pragma[only_bind_into](config))
|
||||
revFlowIsReadAndStored(pragma[only_bind_into](c), pragma[only_bind_into](config)) and
|
||||
read(n1, c, n2, pragma[only_bind_into](config)) and
|
||||
revFlow(n2, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -872,7 +903,10 @@ private module Stage1 {
|
||||
predicate revFlow(
|
||||
NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlow(node, toReturn, config) and exists(state) and exists(returnAp) and exists(ap)
|
||||
revFlow(node, toReturn, pragma[only_bind_into](config)) and
|
||||
exists(state) and
|
||||
exists(returnAp) and
|
||||
exists(ap)
|
||||
}
|
||||
|
||||
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
|
||||
@@ -1149,7 +1183,7 @@ private module Stage2 {
|
||||
|
||||
bindingset[node, state, ap, config]
|
||||
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
PrevStage::revFlowState(state, config) and
|
||||
PrevStage::revFlowState(state, pragma[only_bind_into](config)) and
|
||||
exists(ap) and
|
||||
not stateBarrier(node, state, config)
|
||||
}
|
||||
@@ -1574,7 +1608,7 @@ private module Stage2 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -1729,9 +1763,9 @@ private module LocalFlowBigStep {
|
||||
or
|
||||
node.asNode() instanceof OutNodeExt
|
||||
or
|
||||
store(_, _, node, _, config)
|
||||
Stage2::storeStepCand(_, _, _, node, _, config)
|
||||
or
|
||||
read(_, _, node, config)
|
||||
Stage2::readStepCand(_, _, node, config)
|
||||
or
|
||||
node instanceof FlowCheckNode
|
||||
or
|
||||
@@ -1752,8 +1786,8 @@ private module LocalFlowBigStep {
|
||||
additionalJumpStep(node, next, config) or
|
||||
flowIntoCallNodeCand1(_, node, next, config) or
|
||||
flowOutOfCallNodeCand1(_, node, next, config) or
|
||||
store(node, _, next, _, config) or
|
||||
read(node, _, next, config)
|
||||
Stage2::storeStepCand(node, _, _, next, _, config) or
|
||||
Stage2::readStepCand(node, _, next, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
|
||||
@@ -1926,7 +1960,24 @@ private module Stage3 {
|
||||
private predicate flowIntoCall = flowIntoCallNodeCand2/5;
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clear(NodeEx node, Ap ap) { ap.isClearedAt(node.asNode()) }
|
||||
private predicate clearSet(NodeEx node, ContentSet c, Configuration config) {
|
||||
PrevStage::revFlow(node, config) and
|
||||
clearsContentCached(node.asNode(), c)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clearContent(NodeEx node, Content c, Configuration config) {
|
||||
exists(ContentSet cs |
|
||||
PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and
|
||||
c = cs.getAReadContent() and
|
||||
clearSet(node, cs, pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clear(NodeEx node, Ap ap, Configuration config) {
|
||||
clearContent(node, ap.getHead().getContent(), config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode }
|
||||
@@ -1935,7 +1986,7 @@ private module Stage3 {
|
||||
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
exists(state) and
|
||||
exists(config) and
|
||||
not clear(node, ap) and
|
||||
not clear(node, ap, config) and
|
||||
if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()
|
||||
}
|
||||
|
||||
@@ -2363,7 +2414,7 @@ private module Stage3 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -3190,7 +3241,7 @@ private module Stage4 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -4202,7 +4253,7 @@ private module Subpaths {
|
||||
exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() |
|
||||
localFlowBigStep(n1, _, n2, _, _, _, _, _) or
|
||||
store(n1, _, n2, _, _) or
|
||||
read(n1, _, n2, _)
|
||||
readSet(n1, _, n2, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4557,7 +4608,7 @@ private module FlowExploration {
|
||||
or
|
||||
exists(PartialPathNodeRev mid |
|
||||
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
|
||||
not clearsContentCached(node.asNode(), ap.getHead()) and
|
||||
not clearsContentEx(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
not stateBarrier(node, state, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
@@ -4573,7 +4624,7 @@ private module FlowExploration {
|
||||
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
|
||||
not fullBarrier(node, config) and
|
||||
not stateBarrier(node, state, config) and
|
||||
not clearsContentCached(node.asNode(), ap.getHead().getContent()) and
|
||||
not clearsContentEx(node, ap.getHead().getContent()) and
|
||||
if node.asNode() instanceof CastingNode
|
||||
then compatibleTypes(node.getDataFlowType(), ap.getType())
|
||||
else any()
|
||||
|
||||
@@ -326,7 +326,7 @@ private module Cached {
|
||||
predicate jumpStepCached(Node node1, Node node2) { jumpStep(node1, node2) }
|
||||
|
||||
cached
|
||||
predicate clearsContentCached(Node n, Content c) { clearsContent(n, c) }
|
||||
predicate clearsContentCached(Node n, ContentSet c) { clearsContent(n, c) }
|
||||
|
||||
cached
|
||||
predicate isUnreachableInCallCached(Node n, DataFlowCall call) { isUnreachableInCall(n, call) }
|
||||
@@ -373,7 +373,7 @@ private module Cached {
|
||||
// For reads, `x.f`, we want to check that the tracked type after the read (which
|
||||
// is obtained by popping the head of the access path stack) is compatible with
|
||||
// the type of `x.f`.
|
||||
read(_, _, n)
|
||||
readSet(_, _, n)
|
||||
}
|
||||
|
||||
cached
|
||||
@@ -469,7 +469,7 @@ private module Cached {
|
||||
// read
|
||||
exists(Node mid |
|
||||
parameterValueFlowCand(p, mid, false) and
|
||||
read(mid, _, node) and
|
||||
readSet(mid, _, node) and
|
||||
read = true
|
||||
)
|
||||
or
|
||||
@@ -657,8 +657,10 @@ private module Cached {
|
||||
* Holds if `arg` flows to `out` through a call using only
|
||||
* value-preserving steps and a single read step, not taking call
|
||||
* contexts into account, thus representing a getter-step.
|
||||
*
|
||||
* This predicate is exposed for testing only.
|
||||
*/
|
||||
predicate getterStep(ArgNode arg, Content c, Node out) {
|
||||
predicate getterStep(ArgNode arg, ContentSet c, Node out) {
|
||||
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out)
|
||||
}
|
||||
|
||||
@@ -781,28 +783,30 @@ private module Cached {
|
||||
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
|
||||
}
|
||||
|
||||
cached
|
||||
predicate readSet(Node node1, ContentSet c, Node node2) { readStep(node1, c, node2) }
|
||||
|
||||
private predicate store(
|
||||
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
|
||||
) {
|
||||
storeStep(node1, c, node2) and
|
||||
contentType = getNodeDataFlowType(node1) and
|
||||
containerType = getNodeDataFlowType(node2)
|
||||
or
|
||||
exists(Node n1, Node n2 |
|
||||
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
|
||||
n2 = node2.(PostUpdateNode).getPreUpdateNode()
|
||||
|
|
||||
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
|
||||
exists(ContentSet cs | c = cs.getAStoreContent() |
|
||||
storeStep(node1, cs, node2) and
|
||||
contentType = getNodeDataFlowType(node1) and
|
||||
containerType = getNodeDataFlowType(node2)
|
||||
or
|
||||
read(n2, c, n1) and
|
||||
contentType = getNodeDataFlowType(n1) and
|
||||
containerType = getNodeDataFlowType(n2)
|
||||
exists(Node n1, Node n2 |
|
||||
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
|
||||
n2 = node2.(PostUpdateNode).getPreUpdateNode()
|
||||
|
|
||||
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, cs, contentType), n1)
|
||||
or
|
||||
readSet(n2, cs, n1) and
|
||||
contentType = getNodeDataFlowType(n1) and
|
||||
containerType = getNodeDataFlowType(n2)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate read(Node node1, Content c, Node node2) { readStep(node1, c, node2) }
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` via a direct assignment to
|
||||
* `f`.
|
||||
@@ -932,16 +936,16 @@ class CastingNode extends Node {
|
||||
}
|
||||
|
||||
private predicate readStepWithTypes(
|
||||
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
|
||||
Node n1, DataFlowType container, ContentSet c, Node n2, DataFlowType content
|
||||
) {
|
||||
read(n1, c, n2) and
|
||||
readSet(n1, c, n2) and
|
||||
container = getNodeDataFlowType(n1) and
|
||||
content = getNodeDataFlowType(n2)
|
||||
}
|
||||
|
||||
private newtype TReadStepTypesOption =
|
||||
TReadStepTypesNone() or
|
||||
TReadStepTypesSome(DataFlowType container, Content c, DataFlowType content) {
|
||||
TReadStepTypesSome(DataFlowType container, ContentSet c, DataFlowType content) {
|
||||
readStepWithTypes(_, container, c, _, content)
|
||||
}
|
||||
|
||||
@@ -950,7 +954,7 @@ private class ReadStepTypesOption extends TReadStepTypesOption {
|
||||
|
||||
DataFlowType getContainerType() { this = TReadStepTypesSome(result, _, _) }
|
||||
|
||||
Content getContent() { this = TReadStepTypesSome(_, result, _) }
|
||||
ContentSet getContent() { this = TReadStepTypesSome(_, result, _) }
|
||||
|
||||
DataFlowType getContentType() { this = TReadStepTypesSome(_, _, result) }
|
||||
|
||||
@@ -1325,8 +1329,6 @@ abstract class AccessPathFront extends TAccessPathFront {
|
||||
abstract boolean toBoolNonEmpty();
|
||||
|
||||
TypedContent getHead() { this = TFrontHead(result) }
|
||||
|
||||
predicate isClearedAt(Node n) { clearsContentCached(n, this.getHead().getContent()) }
|
||||
}
|
||||
|
||||
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
|
||||
|
||||
@@ -116,7 +116,7 @@ abstract class Configuration extends string {
|
||||
* Holds if an arbitrary number of implicit read steps of content `c` may be
|
||||
* taken at `node`.
|
||||
*/
|
||||
predicate allowImplicitRead(Node node, Content c) { none() }
|
||||
predicate allowImplicitRead(Node node, ContentSet c) { none() }
|
||||
|
||||
/**
|
||||
* Gets the virtual dispatch branching limit when calculating field flow.
|
||||
@@ -485,8 +485,9 @@ private predicate additionalJumpStateStep(
|
||||
)
|
||||
}
|
||||
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
read(node1.asNode(), c, node2.asNode()) and
|
||||
pragma[nomagic]
|
||||
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
|
||||
readSet(node1.asNode(), c, node2.asNode()) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
@@ -496,6 +497,25 @@ private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration conf
|
||||
)
|
||||
}
|
||||
|
||||
// inline to reduce fan-out via `getAReadContent`
|
||||
pragma[inline]
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
exists(ContentSet cs |
|
||||
readSet(node1, cs, node2, config) and
|
||||
c = cs.getAReadContent()
|
||||
)
|
||||
}
|
||||
|
||||
// inline to reduce fan-out via `getAReadContent`
|
||||
pragma[inline]
|
||||
private predicate clearsContentEx(NodeEx n, Content c) {
|
||||
exists(ContentSet cs |
|
||||
clearsContentCached(n.asNode(), cs) and
|
||||
c = cs.getAReadContent()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
@@ -573,9 +593,9 @@ private module Stage1 {
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config)
|
||||
exists(ContentSet c |
|
||||
fwdFlowReadSet(c, node, cc, config) and
|
||||
fwdFlowConsCandSet(c, _, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
@@ -599,10 +619,10 @@ private module Stage1 {
|
||||
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowRead(Content c, NodeEx node, Cc cc, Configuration config) {
|
||||
private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) {
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
read(mid, c, node, config)
|
||||
readSet(mid, c, node, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -620,6 +640,16 @@ private module Stage1 {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `cs` may be interpreted in a read as the target of some store
|
||||
* into `c`, in the flow covered by `fwdFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) {
|
||||
fwdFlowConsCand(c, config) and
|
||||
c = cs.getAReadContent()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) {
|
||||
exists(RetNodeEx ret |
|
||||
@@ -712,9 +742,9 @@ private module Stage1 {
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(NodeEx mid, Content c |
|
||||
read(node, c, mid, config) and
|
||||
fwdFlowConsCand(c, pragma[only_bind_into](config)) and
|
||||
exists(NodeEx mid, ContentSet c |
|
||||
readSet(node, c, mid, config) and
|
||||
fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and
|
||||
revFlow(mid, toReturn, pragma[only_bind_into](config))
|
||||
)
|
||||
or
|
||||
@@ -740,10 +770,10 @@ private module Stage1 {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate revFlowConsCand(Content c, Configuration config) {
|
||||
exists(NodeEx mid, NodeEx node |
|
||||
exists(NodeEx mid, NodeEx node, ContentSet cs |
|
||||
fwdFlow(node, pragma[only_bind_into](config)) and
|
||||
read(node, c, mid, config) and
|
||||
fwdFlowConsCand(c, pragma[only_bind_into](config)) and
|
||||
readSet(node, cs, mid, config) and
|
||||
fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and
|
||||
revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -762,6 +792,7 @@ private module Stage1 {
|
||||
* Holds if `c` is the target of both a read and a store in the flow covered
|
||||
* by `revFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
revFlowConsCand(c, conf) and
|
||||
revFlowStore(c, _, _, conf)
|
||||
@@ -860,9 +891,9 @@ private module Stage1 {
|
||||
|
||||
pragma[nomagic]
|
||||
predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) {
|
||||
revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
|
||||
revFlow(n2, pragma[only_bind_into](config)) and
|
||||
read(n1, c, n2, pragma[only_bind_into](config))
|
||||
revFlowIsReadAndStored(pragma[only_bind_into](c), pragma[only_bind_into](config)) and
|
||||
read(n1, c, n2, pragma[only_bind_into](config)) and
|
||||
revFlow(n2, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -872,7 +903,10 @@ private module Stage1 {
|
||||
predicate revFlow(
|
||||
NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlow(node, toReturn, config) and exists(state) and exists(returnAp) and exists(ap)
|
||||
revFlow(node, toReturn, pragma[only_bind_into](config)) and
|
||||
exists(state) and
|
||||
exists(returnAp) and
|
||||
exists(ap)
|
||||
}
|
||||
|
||||
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
|
||||
@@ -1149,7 +1183,7 @@ private module Stage2 {
|
||||
|
||||
bindingset[node, state, ap, config]
|
||||
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
PrevStage::revFlowState(state, config) and
|
||||
PrevStage::revFlowState(state, pragma[only_bind_into](config)) and
|
||||
exists(ap) and
|
||||
not stateBarrier(node, state, config)
|
||||
}
|
||||
@@ -1574,7 +1608,7 @@ private module Stage2 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -1729,9 +1763,9 @@ private module LocalFlowBigStep {
|
||||
or
|
||||
node.asNode() instanceof OutNodeExt
|
||||
or
|
||||
store(_, _, node, _, config)
|
||||
Stage2::storeStepCand(_, _, _, node, _, config)
|
||||
or
|
||||
read(_, _, node, config)
|
||||
Stage2::readStepCand(_, _, node, config)
|
||||
or
|
||||
node instanceof FlowCheckNode
|
||||
or
|
||||
@@ -1752,8 +1786,8 @@ private module LocalFlowBigStep {
|
||||
additionalJumpStep(node, next, config) or
|
||||
flowIntoCallNodeCand1(_, node, next, config) or
|
||||
flowOutOfCallNodeCand1(_, node, next, config) or
|
||||
store(node, _, next, _, config) or
|
||||
read(node, _, next, config)
|
||||
Stage2::storeStepCand(node, _, _, next, _, config) or
|
||||
Stage2::readStepCand(node, _, next, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
|
||||
@@ -1926,7 +1960,24 @@ private module Stage3 {
|
||||
private predicate flowIntoCall = flowIntoCallNodeCand2/5;
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clear(NodeEx node, Ap ap) { ap.isClearedAt(node.asNode()) }
|
||||
private predicate clearSet(NodeEx node, ContentSet c, Configuration config) {
|
||||
PrevStage::revFlow(node, config) and
|
||||
clearsContentCached(node.asNode(), c)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clearContent(NodeEx node, Content c, Configuration config) {
|
||||
exists(ContentSet cs |
|
||||
PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and
|
||||
c = cs.getAReadContent() and
|
||||
clearSet(node, cs, pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clear(NodeEx node, Ap ap, Configuration config) {
|
||||
clearContent(node, ap.getHead().getContent(), config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode }
|
||||
@@ -1935,7 +1986,7 @@ private module Stage3 {
|
||||
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
exists(state) and
|
||||
exists(config) and
|
||||
not clear(node, ap) and
|
||||
not clear(node, ap, config) and
|
||||
if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()
|
||||
}
|
||||
|
||||
@@ -2363,7 +2414,7 @@ private module Stage3 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -3190,7 +3241,7 @@ private module Stage4 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -4202,7 +4253,7 @@ private module Subpaths {
|
||||
exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() |
|
||||
localFlowBigStep(n1, _, n2, _, _, _, _, _) or
|
||||
store(n1, _, n2, _, _) or
|
||||
read(n1, _, n2, _)
|
||||
readSet(n1, _, n2, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4557,7 +4608,7 @@ private module FlowExploration {
|
||||
or
|
||||
exists(PartialPathNodeRev mid |
|
||||
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
|
||||
not clearsContentCached(node.asNode(), ap.getHead()) and
|
||||
not clearsContentEx(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
not stateBarrier(node, state, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
@@ -4573,7 +4624,7 @@ private module FlowExploration {
|
||||
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
|
||||
not fullBarrier(node, config) and
|
||||
not stateBarrier(node, state, config) and
|
||||
not clearsContentCached(node.asNode(), ap.getHead().getContent()) and
|
||||
not clearsContentEx(node, ap.getHead().getContent()) and
|
||||
if node.asNode() instanceof CastingNode
|
||||
then compatibleTypes(node.getDataFlowType(), ap.getType())
|
||||
else any()
|
||||
|
||||
@@ -821,6 +821,34 @@ private class CollectionContent extends Content, TCollectionContent {
|
||||
override string toString() { result = "<element>" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An entity that represents a set of `Content`s.
|
||||
*
|
||||
* The set may be interpreted differently depending on whether it is
|
||||
* stored into (`getAStoreContent`) or read from (`getAReadContent`).
|
||||
*/
|
||||
class ContentSet instanceof Content {
|
||||
/** Gets a content that may be stored into when storing into this set. */
|
||||
Content getAStoreContent() { result = this }
|
||||
|
||||
/** Gets a content that may be read from when reading from this set. */
|
||||
Content getAReadContent() { result = this }
|
||||
|
||||
/** Gets a textual representation of this content set. */
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
|
||||
super.hasLocationInfo(path, sl, sc, el, ec)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A guard that validates some expression.
|
||||
*
|
||||
|
||||
@@ -161,7 +161,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
this.isAdditionalTaintStep(node1, state1, node2, state2)
|
||||
}
|
||||
|
||||
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) {
|
||||
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
|
||||
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
|
||||
defaultImplicitTaintRead(node, c)
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
this.isAdditionalTaintStep(node1, state1, node2, state2)
|
||||
}
|
||||
|
||||
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) {
|
||||
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
|
||||
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
|
||||
defaultImplicitTaintRead(node, c)
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ abstract class Configuration extends string {
|
||||
* Holds if an arbitrary number of implicit read steps of content `c` may be
|
||||
* taken at `node`.
|
||||
*/
|
||||
predicate allowImplicitRead(Node node, Content c) { none() }
|
||||
predicate allowImplicitRead(Node node, ContentSet c) { none() }
|
||||
|
||||
/**
|
||||
* Gets the virtual dispatch branching limit when calculating field flow.
|
||||
@@ -485,8 +485,9 @@ private predicate additionalJumpStateStep(
|
||||
)
|
||||
}
|
||||
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
read(node1.asNode(), c, node2.asNode()) and
|
||||
pragma[nomagic]
|
||||
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
|
||||
readSet(node1.asNode(), c, node2.asNode()) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
@@ -496,6 +497,25 @@ private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration conf
|
||||
)
|
||||
}
|
||||
|
||||
// inline to reduce fan-out via `getAReadContent`
|
||||
pragma[inline]
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
exists(ContentSet cs |
|
||||
readSet(node1, cs, node2, config) and
|
||||
c = cs.getAReadContent()
|
||||
)
|
||||
}
|
||||
|
||||
// inline to reduce fan-out via `getAReadContent`
|
||||
pragma[inline]
|
||||
private predicate clearsContentEx(NodeEx n, Content c) {
|
||||
exists(ContentSet cs |
|
||||
clearsContentCached(n.asNode(), cs) and
|
||||
c = cs.getAReadContent()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
@@ -573,9 +593,9 @@ private module Stage1 {
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config)
|
||||
exists(ContentSet c |
|
||||
fwdFlowReadSet(c, node, cc, config) and
|
||||
fwdFlowConsCandSet(c, _, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
@@ -599,10 +619,10 @@ private module Stage1 {
|
||||
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowRead(Content c, NodeEx node, Cc cc, Configuration config) {
|
||||
private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) {
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
read(mid, c, node, config)
|
||||
readSet(mid, c, node, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -620,6 +640,16 @@ private module Stage1 {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `cs` may be interpreted in a read as the target of some store
|
||||
* into `c`, in the flow covered by `fwdFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) {
|
||||
fwdFlowConsCand(c, config) and
|
||||
c = cs.getAReadContent()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) {
|
||||
exists(RetNodeEx ret |
|
||||
@@ -712,9 +742,9 @@ private module Stage1 {
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(NodeEx mid, Content c |
|
||||
read(node, c, mid, config) and
|
||||
fwdFlowConsCand(c, pragma[only_bind_into](config)) and
|
||||
exists(NodeEx mid, ContentSet c |
|
||||
readSet(node, c, mid, config) and
|
||||
fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and
|
||||
revFlow(mid, toReturn, pragma[only_bind_into](config))
|
||||
)
|
||||
or
|
||||
@@ -740,10 +770,10 @@ private module Stage1 {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate revFlowConsCand(Content c, Configuration config) {
|
||||
exists(NodeEx mid, NodeEx node |
|
||||
exists(NodeEx mid, NodeEx node, ContentSet cs |
|
||||
fwdFlow(node, pragma[only_bind_into](config)) and
|
||||
read(node, c, mid, config) and
|
||||
fwdFlowConsCand(c, pragma[only_bind_into](config)) and
|
||||
readSet(node, cs, mid, config) and
|
||||
fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and
|
||||
revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -762,6 +792,7 @@ private module Stage1 {
|
||||
* Holds if `c` is the target of both a read and a store in the flow covered
|
||||
* by `revFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
revFlowConsCand(c, conf) and
|
||||
revFlowStore(c, _, _, conf)
|
||||
@@ -860,9 +891,9 @@ private module Stage1 {
|
||||
|
||||
pragma[nomagic]
|
||||
predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) {
|
||||
revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
|
||||
revFlow(n2, pragma[only_bind_into](config)) and
|
||||
read(n1, c, n2, pragma[only_bind_into](config))
|
||||
revFlowIsReadAndStored(pragma[only_bind_into](c), pragma[only_bind_into](config)) and
|
||||
read(n1, c, n2, pragma[only_bind_into](config)) and
|
||||
revFlow(n2, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -872,7 +903,10 @@ private module Stage1 {
|
||||
predicate revFlow(
|
||||
NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlow(node, toReturn, config) and exists(state) and exists(returnAp) and exists(ap)
|
||||
revFlow(node, toReturn, pragma[only_bind_into](config)) and
|
||||
exists(state) and
|
||||
exists(returnAp) and
|
||||
exists(ap)
|
||||
}
|
||||
|
||||
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
|
||||
@@ -1149,7 +1183,7 @@ private module Stage2 {
|
||||
|
||||
bindingset[node, state, ap, config]
|
||||
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
PrevStage::revFlowState(state, config) and
|
||||
PrevStage::revFlowState(state, pragma[only_bind_into](config)) and
|
||||
exists(ap) and
|
||||
not stateBarrier(node, state, config)
|
||||
}
|
||||
@@ -1574,7 +1608,7 @@ private module Stage2 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -1729,9 +1763,9 @@ private module LocalFlowBigStep {
|
||||
or
|
||||
node.asNode() instanceof OutNodeExt
|
||||
or
|
||||
store(_, _, node, _, config)
|
||||
Stage2::storeStepCand(_, _, _, node, _, config)
|
||||
or
|
||||
read(_, _, node, config)
|
||||
Stage2::readStepCand(_, _, node, config)
|
||||
or
|
||||
node instanceof FlowCheckNode
|
||||
or
|
||||
@@ -1752,8 +1786,8 @@ private module LocalFlowBigStep {
|
||||
additionalJumpStep(node, next, config) or
|
||||
flowIntoCallNodeCand1(_, node, next, config) or
|
||||
flowOutOfCallNodeCand1(_, node, next, config) or
|
||||
store(node, _, next, _, config) or
|
||||
read(node, _, next, config)
|
||||
Stage2::storeStepCand(node, _, _, next, _, config) or
|
||||
Stage2::readStepCand(node, _, next, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
|
||||
@@ -1926,7 +1960,24 @@ private module Stage3 {
|
||||
private predicate flowIntoCall = flowIntoCallNodeCand2/5;
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clear(NodeEx node, Ap ap) { ap.isClearedAt(node.asNode()) }
|
||||
private predicate clearSet(NodeEx node, ContentSet c, Configuration config) {
|
||||
PrevStage::revFlow(node, config) and
|
||||
clearsContentCached(node.asNode(), c)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clearContent(NodeEx node, Content c, Configuration config) {
|
||||
exists(ContentSet cs |
|
||||
PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and
|
||||
c = cs.getAReadContent() and
|
||||
clearSet(node, cs, pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clear(NodeEx node, Ap ap, Configuration config) {
|
||||
clearContent(node, ap.getHead().getContent(), config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode }
|
||||
@@ -1935,7 +1986,7 @@ private module Stage3 {
|
||||
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
exists(state) and
|
||||
exists(config) and
|
||||
not clear(node, ap) and
|
||||
not clear(node, ap, config) and
|
||||
if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()
|
||||
}
|
||||
|
||||
@@ -2363,7 +2414,7 @@ private module Stage3 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -3190,7 +3241,7 @@ private module Stage4 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -4202,7 +4253,7 @@ private module Subpaths {
|
||||
exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() |
|
||||
localFlowBigStep(n1, _, n2, _, _, _, _, _) or
|
||||
store(n1, _, n2, _, _) or
|
||||
read(n1, _, n2, _)
|
||||
readSet(n1, _, n2, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4557,7 +4608,7 @@ private module FlowExploration {
|
||||
or
|
||||
exists(PartialPathNodeRev mid |
|
||||
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
|
||||
not clearsContentCached(node.asNode(), ap.getHead()) and
|
||||
not clearsContentEx(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
not stateBarrier(node, state, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
@@ -4573,7 +4624,7 @@ private module FlowExploration {
|
||||
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
|
||||
not fullBarrier(node, config) and
|
||||
not stateBarrier(node, state, config) and
|
||||
not clearsContentCached(node.asNode(), ap.getHead().getContent()) and
|
||||
not clearsContentEx(node, ap.getHead().getContent()) and
|
||||
if node.asNode() instanceof CastingNode
|
||||
then compatibleTypes(node.getDataFlowType(), ap.getType())
|
||||
else any()
|
||||
|
||||
@@ -116,7 +116,7 @@ abstract class Configuration extends string {
|
||||
* Holds if an arbitrary number of implicit read steps of content `c` may be
|
||||
* taken at `node`.
|
||||
*/
|
||||
predicate allowImplicitRead(Node node, Content c) { none() }
|
||||
predicate allowImplicitRead(Node node, ContentSet c) { none() }
|
||||
|
||||
/**
|
||||
* Gets the virtual dispatch branching limit when calculating field flow.
|
||||
@@ -485,8 +485,9 @@ private predicate additionalJumpStateStep(
|
||||
)
|
||||
}
|
||||
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
read(node1.asNode(), c, node2.asNode()) and
|
||||
pragma[nomagic]
|
||||
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
|
||||
readSet(node1.asNode(), c, node2.asNode()) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
@@ -496,6 +497,25 @@ private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration conf
|
||||
)
|
||||
}
|
||||
|
||||
// inline to reduce fan-out via `getAReadContent`
|
||||
pragma[inline]
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
exists(ContentSet cs |
|
||||
readSet(node1, cs, node2, config) and
|
||||
c = cs.getAReadContent()
|
||||
)
|
||||
}
|
||||
|
||||
// inline to reduce fan-out via `getAReadContent`
|
||||
pragma[inline]
|
||||
private predicate clearsContentEx(NodeEx n, Content c) {
|
||||
exists(ContentSet cs |
|
||||
clearsContentCached(n.asNode(), cs) and
|
||||
c = cs.getAReadContent()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
@@ -573,9 +593,9 @@ private module Stage1 {
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config)
|
||||
exists(ContentSet c |
|
||||
fwdFlowReadSet(c, node, cc, config) and
|
||||
fwdFlowConsCandSet(c, _, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
@@ -599,10 +619,10 @@ private module Stage1 {
|
||||
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowRead(Content c, NodeEx node, Cc cc, Configuration config) {
|
||||
private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) {
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
read(mid, c, node, config)
|
||||
readSet(mid, c, node, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -620,6 +640,16 @@ private module Stage1 {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `cs` may be interpreted in a read as the target of some store
|
||||
* into `c`, in the flow covered by `fwdFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) {
|
||||
fwdFlowConsCand(c, config) and
|
||||
c = cs.getAReadContent()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) {
|
||||
exists(RetNodeEx ret |
|
||||
@@ -712,9 +742,9 @@ private module Stage1 {
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(NodeEx mid, Content c |
|
||||
read(node, c, mid, config) and
|
||||
fwdFlowConsCand(c, pragma[only_bind_into](config)) and
|
||||
exists(NodeEx mid, ContentSet c |
|
||||
readSet(node, c, mid, config) and
|
||||
fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and
|
||||
revFlow(mid, toReturn, pragma[only_bind_into](config))
|
||||
)
|
||||
or
|
||||
@@ -740,10 +770,10 @@ private module Stage1 {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate revFlowConsCand(Content c, Configuration config) {
|
||||
exists(NodeEx mid, NodeEx node |
|
||||
exists(NodeEx mid, NodeEx node, ContentSet cs |
|
||||
fwdFlow(node, pragma[only_bind_into](config)) and
|
||||
read(node, c, mid, config) and
|
||||
fwdFlowConsCand(c, pragma[only_bind_into](config)) and
|
||||
readSet(node, cs, mid, config) and
|
||||
fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and
|
||||
revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -762,6 +792,7 @@ private module Stage1 {
|
||||
* Holds if `c` is the target of both a read and a store in the flow covered
|
||||
* by `revFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
revFlowConsCand(c, conf) and
|
||||
revFlowStore(c, _, _, conf)
|
||||
@@ -860,9 +891,9 @@ private module Stage1 {
|
||||
|
||||
pragma[nomagic]
|
||||
predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) {
|
||||
revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
|
||||
revFlow(n2, pragma[only_bind_into](config)) and
|
||||
read(n1, c, n2, pragma[only_bind_into](config))
|
||||
revFlowIsReadAndStored(pragma[only_bind_into](c), pragma[only_bind_into](config)) and
|
||||
read(n1, c, n2, pragma[only_bind_into](config)) and
|
||||
revFlow(n2, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -872,7 +903,10 @@ private module Stage1 {
|
||||
predicate revFlow(
|
||||
NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlow(node, toReturn, config) and exists(state) and exists(returnAp) and exists(ap)
|
||||
revFlow(node, toReturn, pragma[only_bind_into](config)) and
|
||||
exists(state) and
|
||||
exists(returnAp) and
|
||||
exists(ap)
|
||||
}
|
||||
|
||||
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
|
||||
@@ -1149,7 +1183,7 @@ private module Stage2 {
|
||||
|
||||
bindingset[node, state, ap, config]
|
||||
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
PrevStage::revFlowState(state, config) and
|
||||
PrevStage::revFlowState(state, pragma[only_bind_into](config)) and
|
||||
exists(ap) and
|
||||
not stateBarrier(node, state, config)
|
||||
}
|
||||
@@ -1574,7 +1608,7 @@ private module Stage2 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -1729,9 +1763,9 @@ private module LocalFlowBigStep {
|
||||
or
|
||||
node.asNode() instanceof OutNodeExt
|
||||
or
|
||||
store(_, _, node, _, config)
|
||||
Stage2::storeStepCand(_, _, _, node, _, config)
|
||||
or
|
||||
read(_, _, node, config)
|
||||
Stage2::readStepCand(_, _, node, config)
|
||||
or
|
||||
node instanceof FlowCheckNode
|
||||
or
|
||||
@@ -1752,8 +1786,8 @@ private module LocalFlowBigStep {
|
||||
additionalJumpStep(node, next, config) or
|
||||
flowIntoCallNodeCand1(_, node, next, config) or
|
||||
flowOutOfCallNodeCand1(_, node, next, config) or
|
||||
store(node, _, next, _, config) or
|
||||
read(node, _, next, config)
|
||||
Stage2::storeStepCand(node, _, _, next, _, config) or
|
||||
Stage2::readStepCand(node, _, next, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
|
||||
@@ -1926,7 +1960,24 @@ private module Stage3 {
|
||||
private predicate flowIntoCall = flowIntoCallNodeCand2/5;
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clear(NodeEx node, Ap ap) { ap.isClearedAt(node.asNode()) }
|
||||
private predicate clearSet(NodeEx node, ContentSet c, Configuration config) {
|
||||
PrevStage::revFlow(node, config) and
|
||||
clearsContentCached(node.asNode(), c)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clearContent(NodeEx node, Content c, Configuration config) {
|
||||
exists(ContentSet cs |
|
||||
PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and
|
||||
c = cs.getAReadContent() and
|
||||
clearSet(node, cs, pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clear(NodeEx node, Ap ap, Configuration config) {
|
||||
clearContent(node, ap.getHead().getContent(), config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode }
|
||||
@@ -1935,7 +1986,7 @@ private module Stage3 {
|
||||
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
exists(state) and
|
||||
exists(config) and
|
||||
not clear(node, ap) and
|
||||
not clear(node, ap, config) and
|
||||
if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()
|
||||
}
|
||||
|
||||
@@ -2363,7 +2414,7 @@ private module Stage3 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -3190,7 +3241,7 @@ private module Stage4 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -4202,7 +4253,7 @@ private module Subpaths {
|
||||
exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() |
|
||||
localFlowBigStep(n1, _, n2, _, _, _, _, _) or
|
||||
store(n1, _, n2, _, _) or
|
||||
read(n1, _, n2, _)
|
||||
readSet(n1, _, n2, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4557,7 +4608,7 @@ private module FlowExploration {
|
||||
or
|
||||
exists(PartialPathNodeRev mid |
|
||||
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
|
||||
not clearsContentCached(node.asNode(), ap.getHead()) and
|
||||
not clearsContentEx(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
not stateBarrier(node, state, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
@@ -4573,7 +4624,7 @@ private module FlowExploration {
|
||||
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
|
||||
not fullBarrier(node, config) and
|
||||
not stateBarrier(node, state, config) and
|
||||
not clearsContentCached(node.asNode(), ap.getHead().getContent()) and
|
||||
not clearsContentEx(node, ap.getHead().getContent()) and
|
||||
if node.asNode() instanceof CastingNode
|
||||
then compatibleTypes(node.getDataFlowType(), ap.getType())
|
||||
else any()
|
||||
|
||||
@@ -116,7 +116,7 @@ abstract class Configuration extends string {
|
||||
* Holds if an arbitrary number of implicit read steps of content `c` may be
|
||||
* taken at `node`.
|
||||
*/
|
||||
predicate allowImplicitRead(Node node, Content c) { none() }
|
||||
predicate allowImplicitRead(Node node, ContentSet c) { none() }
|
||||
|
||||
/**
|
||||
* Gets the virtual dispatch branching limit when calculating field flow.
|
||||
@@ -485,8 +485,9 @@ private predicate additionalJumpStateStep(
|
||||
)
|
||||
}
|
||||
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
read(node1.asNode(), c, node2.asNode()) and
|
||||
pragma[nomagic]
|
||||
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
|
||||
readSet(node1.asNode(), c, node2.asNode()) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
@@ -496,6 +497,25 @@ private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration conf
|
||||
)
|
||||
}
|
||||
|
||||
// inline to reduce fan-out via `getAReadContent`
|
||||
pragma[inline]
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
exists(ContentSet cs |
|
||||
readSet(node1, cs, node2, config) and
|
||||
c = cs.getAReadContent()
|
||||
)
|
||||
}
|
||||
|
||||
// inline to reduce fan-out via `getAReadContent`
|
||||
pragma[inline]
|
||||
private predicate clearsContentEx(NodeEx n, Content c) {
|
||||
exists(ContentSet cs |
|
||||
clearsContentCached(n.asNode(), cs) and
|
||||
c = cs.getAReadContent()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
@@ -573,9 +593,9 @@ private module Stage1 {
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config)
|
||||
exists(ContentSet c |
|
||||
fwdFlowReadSet(c, node, cc, config) and
|
||||
fwdFlowConsCandSet(c, _, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
@@ -599,10 +619,10 @@ private module Stage1 {
|
||||
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowRead(Content c, NodeEx node, Cc cc, Configuration config) {
|
||||
private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) {
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
read(mid, c, node, config)
|
||||
readSet(mid, c, node, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -620,6 +640,16 @@ private module Stage1 {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `cs` may be interpreted in a read as the target of some store
|
||||
* into `c`, in the flow covered by `fwdFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) {
|
||||
fwdFlowConsCand(c, config) and
|
||||
c = cs.getAReadContent()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) {
|
||||
exists(RetNodeEx ret |
|
||||
@@ -712,9 +742,9 @@ private module Stage1 {
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(NodeEx mid, Content c |
|
||||
read(node, c, mid, config) and
|
||||
fwdFlowConsCand(c, pragma[only_bind_into](config)) and
|
||||
exists(NodeEx mid, ContentSet c |
|
||||
readSet(node, c, mid, config) and
|
||||
fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and
|
||||
revFlow(mid, toReturn, pragma[only_bind_into](config))
|
||||
)
|
||||
or
|
||||
@@ -740,10 +770,10 @@ private module Stage1 {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate revFlowConsCand(Content c, Configuration config) {
|
||||
exists(NodeEx mid, NodeEx node |
|
||||
exists(NodeEx mid, NodeEx node, ContentSet cs |
|
||||
fwdFlow(node, pragma[only_bind_into](config)) and
|
||||
read(node, c, mid, config) and
|
||||
fwdFlowConsCand(c, pragma[only_bind_into](config)) and
|
||||
readSet(node, cs, mid, config) and
|
||||
fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and
|
||||
revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -762,6 +792,7 @@ private module Stage1 {
|
||||
* Holds if `c` is the target of both a read and a store in the flow covered
|
||||
* by `revFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
revFlowConsCand(c, conf) and
|
||||
revFlowStore(c, _, _, conf)
|
||||
@@ -860,9 +891,9 @@ private module Stage1 {
|
||||
|
||||
pragma[nomagic]
|
||||
predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) {
|
||||
revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
|
||||
revFlow(n2, pragma[only_bind_into](config)) and
|
||||
read(n1, c, n2, pragma[only_bind_into](config))
|
||||
revFlowIsReadAndStored(pragma[only_bind_into](c), pragma[only_bind_into](config)) and
|
||||
read(n1, c, n2, pragma[only_bind_into](config)) and
|
||||
revFlow(n2, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -872,7 +903,10 @@ private module Stage1 {
|
||||
predicate revFlow(
|
||||
NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlow(node, toReturn, config) and exists(state) and exists(returnAp) and exists(ap)
|
||||
revFlow(node, toReturn, pragma[only_bind_into](config)) and
|
||||
exists(state) and
|
||||
exists(returnAp) and
|
||||
exists(ap)
|
||||
}
|
||||
|
||||
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
|
||||
@@ -1149,7 +1183,7 @@ private module Stage2 {
|
||||
|
||||
bindingset[node, state, ap, config]
|
||||
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
PrevStage::revFlowState(state, config) and
|
||||
PrevStage::revFlowState(state, pragma[only_bind_into](config)) and
|
||||
exists(ap) and
|
||||
not stateBarrier(node, state, config)
|
||||
}
|
||||
@@ -1574,7 +1608,7 @@ private module Stage2 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -1729,9 +1763,9 @@ private module LocalFlowBigStep {
|
||||
or
|
||||
node.asNode() instanceof OutNodeExt
|
||||
or
|
||||
store(_, _, node, _, config)
|
||||
Stage2::storeStepCand(_, _, _, node, _, config)
|
||||
or
|
||||
read(_, _, node, config)
|
||||
Stage2::readStepCand(_, _, node, config)
|
||||
or
|
||||
node instanceof FlowCheckNode
|
||||
or
|
||||
@@ -1752,8 +1786,8 @@ private module LocalFlowBigStep {
|
||||
additionalJumpStep(node, next, config) or
|
||||
flowIntoCallNodeCand1(_, node, next, config) or
|
||||
flowOutOfCallNodeCand1(_, node, next, config) or
|
||||
store(node, _, next, _, config) or
|
||||
read(node, _, next, config)
|
||||
Stage2::storeStepCand(node, _, _, next, _, config) or
|
||||
Stage2::readStepCand(node, _, next, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
|
||||
@@ -1926,7 +1960,24 @@ private module Stage3 {
|
||||
private predicate flowIntoCall = flowIntoCallNodeCand2/5;
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clear(NodeEx node, Ap ap) { ap.isClearedAt(node.asNode()) }
|
||||
private predicate clearSet(NodeEx node, ContentSet c, Configuration config) {
|
||||
PrevStage::revFlow(node, config) and
|
||||
clearsContentCached(node.asNode(), c)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clearContent(NodeEx node, Content c, Configuration config) {
|
||||
exists(ContentSet cs |
|
||||
PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and
|
||||
c = cs.getAReadContent() and
|
||||
clearSet(node, cs, pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clear(NodeEx node, Ap ap, Configuration config) {
|
||||
clearContent(node, ap.getHead().getContent(), config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode }
|
||||
@@ -1935,7 +1986,7 @@ private module Stage3 {
|
||||
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
exists(state) and
|
||||
exists(config) and
|
||||
not clear(node, ap) and
|
||||
not clear(node, ap, config) and
|
||||
if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()
|
||||
}
|
||||
|
||||
@@ -2363,7 +2414,7 @@ private module Stage3 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -3190,7 +3241,7 @@ private module Stage4 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -4202,7 +4253,7 @@ private module Subpaths {
|
||||
exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() |
|
||||
localFlowBigStep(n1, _, n2, _, _, _, _, _) or
|
||||
store(n1, _, n2, _, _) or
|
||||
read(n1, _, n2, _)
|
||||
readSet(n1, _, n2, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4557,7 +4608,7 @@ private module FlowExploration {
|
||||
or
|
||||
exists(PartialPathNodeRev mid |
|
||||
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
|
||||
not clearsContentCached(node.asNode(), ap.getHead()) and
|
||||
not clearsContentEx(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
not stateBarrier(node, state, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
@@ -4573,7 +4624,7 @@ private module FlowExploration {
|
||||
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
|
||||
not fullBarrier(node, config) and
|
||||
not stateBarrier(node, state, config) and
|
||||
not clearsContentCached(node.asNode(), ap.getHead().getContent()) and
|
||||
not clearsContentEx(node, ap.getHead().getContent()) and
|
||||
if node.asNode() instanceof CastingNode
|
||||
then compatibleTypes(node.getDataFlowType(), ap.getType())
|
||||
else any()
|
||||
|
||||
@@ -116,7 +116,7 @@ abstract class Configuration extends string {
|
||||
* Holds if an arbitrary number of implicit read steps of content `c` may be
|
||||
* taken at `node`.
|
||||
*/
|
||||
predicate allowImplicitRead(Node node, Content c) { none() }
|
||||
predicate allowImplicitRead(Node node, ContentSet c) { none() }
|
||||
|
||||
/**
|
||||
* Gets the virtual dispatch branching limit when calculating field flow.
|
||||
@@ -485,8 +485,9 @@ private predicate additionalJumpStateStep(
|
||||
)
|
||||
}
|
||||
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
read(node1.asNode(), c, node2.asNode()) and
|
||||
pragma[nomagic]
|
||||
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
|
||||
readSet(node1.asNode(), c, node2.asNode()) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
@@ -496,6 +497,25 @@ private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration conf
|
||||
)
|
||||
}
|
||||
|
||||
// inline to reduce fan-out via `getAReadContent`
|
||||
pragma[inline]
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
exists(ContentSet cs |
|
||||
readSet(node1, cs, node2, config) and
|
||||
c = cs.getAReadContent()
|
||||
)
|
||||
}
|
||||
|
||||
// inline to reduce fan-out via `getAReadContent`
|
||||
pragma[inline]
|
||||
private predicate clearsContentEx(NodeEx n, Content c) {
|
||||
exists(ContentSet cs |
|
||||
clearsContentCached(n.asNode(), cs) and
|
||||
c = cs.getAReadContent()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
@@ -573,9 +593,9 @@ private module Stage1 {
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config)
|
||||
exists(ContentSet c |
|
||||
fwdFlowReadSet(c, node, cc, config) and
|
||||
fwdFlowConsCandSet(c, _, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
@@ -599,10 +619,10 @@ private module Stage1 {
|
||||
private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowRead(Content c, NodeEx node, Cc cc, Configuration config) {
|
||||
private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) {
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
read(mid, c, node, config)
|
||||
readSet(mid, c, node, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -620,6 +640,16 @@ private module Stage1 {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `cs` may be interpreted in a read as the target of some store
|
||||
* into `c`, in the flow covered by `fwdFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) {
|
||||
fwdFlowConsCand(c, config) and
|
||||
c = cs.getAReadContent()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) {
|
||||
exists(RetNodeEx ret |
|
||||
@@ -712,9 +742,9 @@ private module Stage1 {
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(NodeEx mid, Content c |
|
||||
read(node, c, mid, config) and
|
||||
fwdFlowConsCand(c, pragma[only_bind_into](config)) and
|
||||
exists(NodeEx mid, ContentSet c |
|
||||
readSet(node, c, mid, config) and
|
||||
fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and
|
||||
revFlow(mid, toReturn, pragma[only_bind_into](config))
|
||||
)
|
||||
or
|
||||
@@ -740,10 +770,10 @@ private module Stage1 {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate revFlowConsCand(Content c, Configuration config) {
|
||||
exists(NodeEx mid, NodeEx node |
|
||||
exists(NodeEx mid, NodeEx node, ContentSet cs |
|
||||
fwdFlow(node, pragma[only_bind_into](config)) and
|
||||
read(node, c, mid, config) and
|
||||
fwdFlowConsCand(c, pragma[only_bind_into](config)) and
|
||||
readSet(node, cs, mid, config) and
|
||||
fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and
|
||||
revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -762,6 +792,7 @@ private module Stage1 {
|
||||
* Holds if `c` is the target of both a read and a store in the flow covered
|
||||
* by `revFlow`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate revFlowIsReadAndStored(Content c, Configuration conf) {
|
||||
revFlowConsCand(c, conf) and
|
||||
revFlowStore(c, _, _, conf)
|
||||
@@ -860,9 +891,9 @@ private module Stage1 {
|
||||
|
||||
pragma[nomagic]
|
||||
predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) {
|
||||
revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
|
||||
revFlow(n2, pragma[only_bind_into](config)) and
|
||||
read(n1, c, n2, pragma[only_bind_into](config))
|
||||
revFlowIsReadAndStored(pragma[only_bind_into](c), pragma[only_bind_into](config)) and
|
||||
read(n1, c, n2, pragma[only_bind_into](config)) and
|
||||
revFlow(n2, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -872,7 +903,10 @@ private module Stage1 {
|
||||
predicate revFlow(
|
||||
NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
|
||||
) {
|
||||
revFlow(node, toReturn, config) and exists(state) and exists(returnAp) and exists(ap)
|
||||
revFlow(node, toReturn, pragma[only_bind_into](config)) and
|
||||
exists(state) and
|
||||
exists(returnAp) and
|
||||
exists(ap)
|
||||
}
|
||||
|
||||
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
|
||||
@@ -1149,7 +1183,7 @@ private module Stage2 {
|
||||
|
||||
bindingset[node, state, ap, config]
|
||||
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
PrevStage::revFlowState(state, config) and
|
||||
PrevStage::revFlowState(state, pragma[only_bind_into](config)) and
|
||||
exists(ap) and
|
||||
not stateBarrier(node, state, config)
|
||||
}
|
||||
@@ -1574,7 +1608,7 @@ private module Stage2 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -1729,9 +1763,9 @@ private module LocalFlowBigStep {
|
||||
or
|
||||
node.asNode() instanceof OutNodeExt
|
||||
or
|
||||
store(_, _, node, _, config)
|
||||
Stage2::storeStepCand(_, _, _, node, _, config)
|
||||
or
|
||||
read(_, _, node, config)
|
||||
Stage2::readStepCand(_, _, node, config)
|
||||
or
|
||||
node instanceof FlowCheckNode
|
||||
or
|
||||
@@ -1752,8 +1786,8 @@ private module LocalFlowBigStep {
|
||||
additionalJumpStep(node, next, config) or
|
||||
flowIntoCallNodeCand1(_, node, next, config) or
|
||||
flowOutOfCallNodeCand1(_, node, next, config) or
|
||||
store(node, _, next, _, config) or
|
||||
read(node, _, next, config)
|
||||
Stage2::storeStepCand(node, _, _, next, _, config) or
|
||||
Stage2::readStepCand(node, _, next, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
|
||||
@@ -1926,7 +1960,24 @@ private module Stage3 {
|
||||
private predicate flowIntoCall = flowIntoCallNodeCand2/5;
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clear(NodeEx node, Ap ap) { ap.isClearedAt(node.asNode()) }
|
||||
private predicate clearSet(NodeEx node, ContentSet c, Configuration config) {
|
||||
PrevStage::revFlow(node, config) and
|
||||
clearsContentCached(node.asNode(), c)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clearContent(NodeEx node, Content c, Configuration config) {
|
||||
exists(ContentSet cs |
|
||||
PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and
|
||||
c = cs.getAReadContent() and
|
||||
clearSet(node, cs, pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate clear(NodeEx node, Ap ap, Configuration config) {
|
||||
clearContent(node, ap.getHead().getContent(), config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode }
|
||||
@@ -1935,7 +1986,7 @@ private module Stage3 {
|
||||
private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
|
||||
exists(state) and
|
||||
exists(config) and
|
||||
not clear(node, ap) and
|
||||
not clear(node, ap, config) and
|
||||
if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()
|
||||
}
|
||||
|
||||
@@ -2363,7 +2414,7 @@ private module Stage3 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -3190,7 +3241,7 @@ private module Stage4 {
|
||||
Configuration config
|
||||
) {
|
||||
exists(Ap ap2, Content c |
|
||||
store(node1, tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and
|
||||
revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
|
||||
revFlowConsCand(ap2, c, ap1, config)
|
||||
)
|
||||
@@ -4202,7 +4253,7 @@ private module Subpaths {
|
||||
exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() |
|
||||
localFlowBigStep(n1, _, n2, _, _, _, _, _) or
|
||||
store(n1, _, n2, _, _) or
|
||||
read(n1, _, n2, _)
|
||||
readSet(n1, _, n2, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4557,7 +4608,7 @@ private module FlowExploration {
|
||||
or
|
||||
exists(PartialPathNodeRev mid |
|
||||
revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
|
||||
not clearsContentCached(node.asNode(), ap.getHead()) and
|
||||
not clearsContentEx(node, ap.getHead()) and
|
||||
not fullBarrier(node, config) and
|
||||
not stateBarrier(node, state, config) and
|
||||
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
|
||||
@@ -4573,7 +4624,7 @@ private module FlowExploration {
|
||||
partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
|
||||
not fullBarrier(node, config) and
|
||||
not stateBarrier(node, state, config) and
|
||||
not clearsContentCached(node.asNode(), ap.getHead().getContent()) and
|
||||
not clearsContentEx(node, ap.getHead().getContent()) and
|
||||
if node.asNode() instanceof CastingNode
|
||||
then compatibleTypes(node.getDataFlowType(), ap.getType())
|
||||
else any()
|
||||
|
||||
@@ -326,7 +326,7 @@ private module Cached {
|
||||
predicate jumpStepCached(Node node1, Node node2) { jumpStep(node1, node2) }
|
||||
|
||||
cached
|
||||
predicate clearsContentCached(Node n, Content c) { clearsContent(n, c) }
|
||||
predicate clearsContentCached(Node n, ContentSet c) { clearsContent(n, c) }
|
||||
|
||||
cached
|
||||
predicate isUnreachableInCallCached(Node n, DataFlowCall call) { isUnreachableInCall(n, call) }
|
||||
@@ -373,7 +373,7 @@ private module Cached {
|
||||
// For reads, `x.f`, we want to check that the tracked type after the read (which
|
||||
// is obtained by popping the head of the access path stack) is compatible with
|
||||
// the type of `x.f`.
|
||||
read(_, _, n)
|
||||
readSet(_, _, n)
|
||||
}
|
||||
|
||||
cached
|
||||
@@ -469,7 +469,7 @@ private module Cached {
|
||||
// read
|
||||
exists(Node mid |
|
||||
parameterValueFlowCand(p, mid, false) and
|
||||
read(mid, _, node) and
|
||||
readSet(mid, _, node) and
|
||||
read = true
|
||||
)
|
||||
or
|
||||
@@ -657,8 +657,10 @@ private module Cached {
|
||||
* Holds if `arg` flows to `out` through a call using only
|
||||
* value-preserving steps and a single read step, not taking call
|
||||
* contexts into account, thus representing a getter-step.
|
||||
*
|
||||
* This predicate is exposed for testing only.
|
||||
*/
|
||||
predicate getterStep(ArgNode arg, Content c, Node out) {
|
||||
predicate getterStep(ArgNode arg, ContentSet c, Node out) {
|
||||
argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out)
|
||||
}
|
||||
|
||||
@@ -781,28 +783,30 @@ private module Cached {
|
||||
parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone())
|
||||
}
|
||||
|
||||
cached
|
||||
predicate readSet(Node node1, ContentSet c, Node node2) { readStep(node1, c, node2) }
|
||||
|
||||
private predicate store(
|
||||
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
|
||||
) {
|
||||
storeStep(node1, c, node2) and
|
||||
contentType = getNodeDataFlowType(node1) and
|
||||
containerType = getNodeDataFlowType(node2)
|
||||
or
|
||||
exists(Node n1, Node n2 |
|
||||
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
|
||||
n2 = node2.(PostUpdateNode).getPreUpdateNode()
|
||||
|
|
||||
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
|
||||
exists(ContentSet cs | c = cs.getAStoreContent() |
|
||||
storeStep(node1, cs, node2) and
|
||||
contentType = getNodeDataFlowType(node1) and
|
||||
containerType = getNodeDataFlowType(node2)
|
||||
or
|
||||
read(n2, c, n1) and
|
||||
contentType = getNodeDataFlowType(n1) and
|
||||
containerType = getNodeDataFlowType(n2)
|
||||
exists(Node n1, Node n2 |
|
||||
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
|
||||
n2 = node2.(PostUpdateNode).getPreUpdateNode()
|
||||
|
|
||||
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, cs, contentType), n1)
|
||||
or
|
||||
readSet(n2, cs, n1) and
|
||||
contentType = getNodeDataFlowType(n1) and
|
||||
containerType = getNodeDataFlowType(n2)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate read(Node node1, Content c, Node node2) { readStep(node1, c, node2) }
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` via a direct assignment to
|
||||
* `f`.
|
||||
@@ -932,16 +936,16 @@ class CastingNode extends Node {
|
||||
}
|
||||
|
||||
private predicate readStepWithTypes(
|
||||
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
|
||||
Node n1, DataFlowType container, ContentSet c, Node n2, DataFlowType content
|
||||
) {
|
||||
read(n1, c, n2) and
|
||||
readSet(n1, c, n2) and
|
||||
container = getNodeDataFlowType(n1) and
|
||||
content = getNodeDataFlowType(n2)
|
||||
}
|
||||
|
||||
private newtype TReadStepTypesOption =
|
||||
TReadStepTypesNone() or
|
||||
TReadStepTypesSome(DataFlowType container, Content c, DataFlowType content) {
|
||||
TReadStepTypesSome(DataFlowType container, ContentSet c, DataFlowType content) {
|
||||
readStepWithTypes(_, container, c, _, content)
|
||||
}
|
||||
|
||||
@@ -950,7 +954,7 @@ private class ReadStepTypesOption extends TReadStepTypesOption {
|
||||
|
||||
DataFlowType getContainerType() { this = TReadStepTypesSome(result, _, _) }
|
||||
|
||||
Content getContent() { this = TReadStepTypesSome(_, result, _) }
|
||||
ContentSet getContent() { this = TReadStepTypesSome(_, result, _) }
|
||||
|
||||
DataFlowType getContentType() { this = TReadStepTypesSome(_, _, result) }
|
||||
|
||||
@@ -1325,8 +1329,6 @@ abstract class AccessPathFront extends TAccessPathFront {
|
||||
abstract boolean toBoolNonEmpty();
|
||||
|
||||
TypedContent getHead() { this = TFrontHead(result) }
|
||||
|
||||
predicate isClearedAt(Node n) { clearsContentCached(n, this.getHead().getContent()) }
|
||||
}
|
||||
|
||||
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
|
||||
|
||||
@@ -1063,6 +1063,34 @@ private class CollectionContent extends Content, TCollectionContent {
|
||||
override string toString() { result = "<element>" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An entity that represents a set of `Content`s.
|
||||
*
|
||||
* The set may be interpreted differently depending on whether it is
|
||||
* stored into (`getAStoreContent`) or read from (`getAReadContent`).
|
||||
*/
|
||||
class ContentSet instanceof Content {
|
||||
/** Gets a content that may be stored into when storing into this set. */
|
||||
Content getAStoreContent() { result = this }
|
||||
|
||||
/** Gets a content that may be read from when reading from this set. */
|
||||
Content getAReadContent() { result = this }
|
||||
|
||||
/** Gets a textual representation of this content set. */
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
|
||||
super.hasLocationInfo(path, sl, sc, el, ec)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A guard that validates some instruction.
|
||||
*
|
||||
|
||||
@@ -161,7 +161,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
this.isAdditionalTaintStep(node1, state1, node2, state2)
|
||||
}
|
||||
|
||||
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) {
|
||||
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
|
||||
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
|
||||
defaultImplicitTaintRead(node, c)
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
this.isAdditionalTaintStep(node1, state1, node2, state2)
|
||||
}
|
||||
|
||||
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) {
|
||||
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
|
||||
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
|
||||
defaultImplicitTaintRead(node, c)
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
this.isAdditionalTaintStep(node1, state1, node2, state2)
|
||||
}
|
||||
|
||||
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) {
|
||||
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
|
||||
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
|
||||
defaultImplicitTaintRead(node, c)
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ private predicate isOpaqueType(Type type) {
|
||||
* Holds if an `IROpaqueType` with the specified `tag` and `byteSize` should exist.
|
||||
*/
|
||||
predicate hasOpaqueType(Type tag, int byteSize) {
|
||||
isOpaqueType(tag) and byteSize = getTypeSize(tag)
|
||||
isOpaqueType(tag) and byteSize = getTypeSize(tag.getUnspecifiedType())
|
||||
or
|
||||
tag instanceof UnknownType and Raw::needsUnknownOpaqueType(byteSize)
|
||||
}
|
||||
@@ -153,17 +153,18 @@ private IRType getIRTypeForPRValue(Type type) {
|
||||
exists(Type unspecifiedType | unspecifiedType = type.getUnspecifiedType() |
|
||||
isOpaqueType(unspecifiedType) and
|
||||
exists(IROpaqueType opaqueType | opaqueType = result |
|
||||
opaqueType.getByteSize() = getTypeSize(type) and
|
||||
opaqueType.getByteSize() = getTypeSize(unspecifiedType) and
|
||||
opaqueType.getTag() = unspecifiedType
|
||||
)
|
||||
or
|
||||
unspecifiedType instanceof BoolType and result.(IRBooleanType).getByteSize() = type.getSize()
|
||||
unspecifiedType instanceof BoolType and
|
||||
result.(IRBooleanType).getByteSize() = unspecifiedType.getSize()
|
||||
or
|
||||
isSignedIntegerType(unspecifiedType) and
|
||||
result.(IRSignedIntegerType).getByteSize() = type.getSize()
|
||||
result.(IRSignedIntegerType).getByteSize() = unspecifiedType.getSize()
|
||||
or
|
||||
isUnsignedIntegerType(unspecifiedType) and
|
||||
result.(IRUnsignedIntegerType).getByteSize() = type.getSize()
|
||||
result.(IRUnsignedIntegerType).getByteSize() = unspecifiedType.getSize()
|
||||
or
|
||||
exists(FloatingPointType floatType, IRFloatingPointType irFloatType |
|
||||
floatType = unspecifiedType and
|
||||
@@ -173,7 +174,8 @@ private IRType getIRTypeForPRValue(Type type) {
|
||||
irFloatType.getDomain() = floatType.getDomain()
|
||||
)
|
||||
or
|
||||
isPointerIshType(unspecifiedType) and result.(IRAddressType).getByteSize() = getTypeSize(type)
|
||||
isPointerIshType(unspecifiedType) and
|
||||
result.(IRAddressType).getByteSize() = getTypeSize(unspecifiedType)
|
||||
or
|
||||
unspecifiedType instanceof FunctionPointerIshType and
|
||||
result.(IRFunctionAddressType).getByteSize() = getTypeSize(type)
|
||||
|
||||
@@ -42,10 +42,13 @@ private class MallocAllocationFunction extends AllocationFunction {
|
||||
this.hasGlobalName([
|
||||
// --- Windows Memory Management for Windows Drivers
|
||||
"ExAllocatePool", // ExAllocatePool(type, size)
|
||||
"ExAllocatePool2", // ExAllocatePool2(flags, size, tag)
|
||||
"ExAllocatePool3", // ExAllocatePool3(flags, size, tag, extparams, extparamscount)
|
||||
"ExAllocatePoolWithTag", // ExAllocatePool(type, size, tag)
|
||||
"ExAllocatePoolWithTagPriority", // ExAllocatePoolWithTagPriority(type, size, tag, priority)
|
||||
"ExAllocatePoolWithQuota", // ExAllocatePoolWithQuota(type, size)
|
||||
"ExAllocatePoolWithQuotaTag", // ExAllocatePoolWithQuotaTag(type, size, tag)
|
||||
"ExAllocatePoolZero", // ExAllocatePoolZero(type, size, tag)
|
||||
"IoAllocateMdl", // IoAllocateMdl(address, size, flag, flag, irp)
|
||||
"IoAllocateErrorLogEntry", // IoAllocateErrorLogEntry(object, size)
|
||||
// --- Windows Global / Local legacy allocation
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
## 0.1.0
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The `cpp/cleartext-transmission` query now recognizes additional sources, for sensitive private data such as e-mail addresses and credit card numbers.
|
||||
* The `cpp/unused-local-variable` no longer ignores functions that include lambda expressions capturing trivially copyable objects.
|
||||
* The `cpp/command-line-injection` query now takes into account calling contexts across string concatenations. This removes false positives due to mismatched calling contexts before and after string concatenations.
|
||||
* A new query, "Potential exposure of sensitive system data to an unauthorized control sphere" (`cpp/potential-system-data-exposure`) has been added. This query is focused on exposure of information that is highly likely to be sensitive, whereas the similar query "Exposure of system data to an unauthorized control sphere" (`cpp/system-data-exposure`) is focused on exposure of information on a channel that is more likely to be intercepted by an attacker.
|
||||
|
||||
## 0.0.13
|
||||
|
||||
## 0.0.12
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* A new query, "Potential exposure of sensitive system data to an unauthorized control sphere" (`cpp/potential-system-data-exposure`) has been added. This query is focused on exposure of information that is highly likely to be sensitive, whereas the similar query "Exposure of system data to an unauthorized control sphere" (`cpp/system-data-exposure`) is focused on exposure of information on a channel that is more likely to be intercepted by an attacker.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The `cpp/command-line-injection` query now takes into account calling contexts across string concatenations. This removes false positives due to mismatched calling contexts before and after string concatenations.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The `cpp/unused-local-variable` no longer ignores functions that include lambda expressions capturing trivially copyable objects.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The `cpp/cleartext-transmission` query now recognizes additional sources, for sensitive private data such as e-mail addresses and credit card numbers.
|
||||
8
cpp/ql/src/change-notes/released/0.1.0.md
Normal file
8
cpp/ql/src/change-notes/released/0.1.0.md
Normal file
@@ -0,0 +1,8 @@
|
||||
## 0.1.0
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The `cpp/cleartext-transmission` query now recognizes additional sources, for sensitive private data such as e-mail addresses and credit card numbers.
|
||||
* The `cpp/unused-local-variable` no longer ignores functions that include lambda expressions capturing trivially copyable objects.
|
||||
* The `cpp/command-line-injection` query now takes into account calling contexts across string concatenations. This removes false positives due to mismatched calling contexts before and after string concatenations.
|
||||
* A new query, "Potential exposure of sensitive system data to an unauthorized control sphere" (`cpp/potential-system-data-exposure`) has been added. This query is focused on exposure of information that is highly likely to be sensitive, whereas the similar query "Exposure of system data to an unauthorized control sphere" (`cpp/system-data-exposure`) is focused on exposure of information on a channel that is more likely to be intercepted by an attacker.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.13
|
||||
lastReleaseVersion: 0.1.0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 0.1.0-dev
|
||||
version: 0.1.1-dev
|
||||
groups:
|
||||
- cpp
|
||||
- queries
|
||||
|
||||
@@ -31,4 +31,4 @@
|
||||
| test2 | 83 | if (...) ... | 74 | test2 |
|
||||
| test2 | 83 | if (...) ... | 84 | break; |
|
||||
| test2 | 83 | if (...) ... | 85 | if (...) ... |
|
||||
| test2 | 85 | if (...) ... | 0 | { ... } |
|
||||
| test2 | 85 | if (...) ... | 86 | { ... } |
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
| test | 44 | ... = ... | 42 | j |
|
||||
| test | 44 | ExprStmt | 44 | 10 |
|
||||
| test | 44 | w | 44 | ... = ... |
|
||||
| test | 47 | ... += ... | 50 | for(...;...;...) ... |
|
||||
| test | 47 | ... += ... | 50 | { ... } |
|
||||
| test | 47 | ExprStmt | 47 | z |
|
||||
| test | 47 | w | 47 | ... += ... |
|
||||
| test | 47 | z | 47 | w |
|
||||
@@ -133,6 +133,7 @@
|
||||
| test | 50 | j | 50 | ... ++ |
|
||||
| test | 50 | j | 50 | ... = ... |
|
||||
| test | 50 | label ...: | 50 | j |
|
||||
| test | 50 | { ... } | 50 | for(...;...;...) ... |
|
||||
| test | 50 | { ... } | 51 | ExprStmt |
|
||||
| test | 51 | 30 | 51 | y |
|
||||
| test | 51 | ... = ... | 52 | if (...) ... |
|
||||
@@ -181,10 +182,10 @@
|
||||
| test | 70 | ExprStmt | 70 | 40 |
|
||||
| test | 70 | w | 70 | ... = ... |
|
||||
| test | 71 | return ... | 71 | w |
|
||||
| test2 | 0 | { ... } | 86 | ExprStmt |
|
||||
| test2 | 74 | { ... } | 76 | declaration |
|
||||
| test2 | 76 | declaration | 77 | for(...;...;...) ... |
|
||||
| test2 | 76 | declaration | 77 | { ... } |
|
||||
| test2 | 77 | for(...;...;...) ... | 77 | { ... } |
|
||||
| test2 | 77 | { ... } | 77 | for(...;...;...) ... |
|
||||
| test2 | 77 | { ... } | 78 | ExprStmt |
|
||||
| test2 | 78 | 10 | 78 | b |
|
||||
| test2 | 78 | ... = ... | 79 | if (...) ... |
|
||||
@@ -211,11 +212,12 @@
|
||||
| test2 | 83 | if (...) ... | 83 | a |
|
||||
| test2 | 84 | break; | 87 | label ...: |
|
||||
| test2 | 85 | 20 | 85 | ... == ... |
|
||||
| test2 | 85 | ... == ... | 0 | { ... } |
|
||||
| test2 | 85 | ... == ... | 86 | { ... } |
|
||||
| test2 | 85 | a | 85 | 20 |
|
||||
| test2 | 85 | if (...) ... | 85 | a |
|
||||
| test2 | 86 | ExprStmt | 86 | c |
|
||||
| test2 | 86 | c | 86 | return ... |
|
||||
| test2 | 86 | { ... } | 86 | ExprStmt |
|
||||
| test2 | 87 | label ...: | 88 | ExprStmt |
|
||||
| test2 | 88 | ExprStmt | 88 | b |
|
||||
| test2 | 88 | b | 88 | return ... |
|
||||
|
||||
@@ -218,10 +218,10 @@ postWithInFlow
|
||||
| lambdas.cpp:20:11:20:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:20:11:20:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:20:11:20:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:23:3:23:3 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:23:3:23:14 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:23:3:23:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:23:3:23:14 | v [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:23:15:23:15 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:28:7:28:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:28:10:31:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:28:10:31:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
| initializers.cpp:18:8:18:15 | initializer for y | initializers.cpp:18:9:18:9 | x |
|
||||
| initializers.cpp:19:8:19:21 | initializer for z | initializers.cpp:19:9:19:9 | x |
|
||||
| initializers.cpp:23:8:23:9 | initializer for j | initializers.cpp:23:9:23:9 | i |
|
||||
| initializers.cpp:27:8:27:10 | initializer for aax | initializers.cpp:27:9:27:10 | ax |
|
||||
| initializers.cpp:27:9:27:10 | initializer for aax | initializers.cpp:27:9:27:10 | ax |
|
||||
| initializers.cpp:30:20:30:35 | initializer for myIntArray | initializers.cpp:30:22:30:22 | i |
|
||||
| template_static.cpp:9:24:9:24 | initializer for static_c | template_static.cpp:9:24:9:24 | c |
|
||||
| template_static.cpp:10:22:10:24 | initializer for static_v | template_static.cpp:10:24:10:24 | v |
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
| initializers.cpp:23:8:23:9 | initializer for j | |
|
||||
| initializers.cpp:25:3:25:3 | initializer for a | |
|
||||
| initializers.cpp:26:7:26:10 | initializer for ax | |
|
||||
| initializers.cpp:27:8:27:10 | initializer for aax | |
|
||||
| initializers.cpp:27:9:27:10 | initializer for aax | |
|
||||
| initializers.cpp:30:20:30:35 | initializer for myIntArray | |
|
||||
| initializers.cpp:31:3:31:15 | initializer for myObjectArray | |
|
||||
| template_static.cpp:2:15:2:15 | initializer for c | |
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
| file://:0:0:0:0 | There was an error during this compilation |
|
||||
| float128.cpp:1:39:1:39 | 128-bit floating-point types are not supported in this configuration |
|
||||
| float128.cpp:2:30:2:30 | 128-bit floating-point types are not supported in this configuration |
|
||||
| float128.cpp:2:30:2:30 | an attribute specifies a mode incompatible with '<error-type>' |
|
||||
| float128.cpp:2:41:2:41 | invalid combination of type specifiers |
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
| float128.cpp:1:50:1:60 | _Complex128 | file://:0:0:0:0 | <error-type> |
|
||||
| float128.cpp:2:41:2:49 | _Float128 | file://:0:0:0:0 | <error-type> |
|
||||
| float128.cpp:13:29:13:54 | __is_floating_point_helper<T> | float128.cpp:10:8:10:17 | false_type |
|
||||
| float128.cpp:14:19:14:51 | __is_floating_point_helper<float> | float128.cpp:11:8:11:16 | true_type |
|
||||
| float128.cpp:15:19:15:52 | __is_floating_point_helper<double> | float128.cpp:11:8:11:16 | true_type |
|
||||
|
||||
@@ -4833,9 +4833,6 @@
|
||||
| ir.cpp:1043:24:1043:24 | SideEffect | ~m1043_20 |
|
||||
| ir.cpp:1043:31:1043:31 | Address | &:r1043_9 |
|
||||
| ir.cpp:1043:36:1043:55 | Address | &:r1043_11 |
|
||||
| ir.cpp:1043:43:1043:43 | Address | &:r1043_16 |
|
||||
| ir.cpp:1043:43:1043:43 | Arg(this) | this:r1043_16 |
|
||||
| ir.cpp:1043:43:1043:43 | SideEffect | ~m1043_20 |
|
||||
| ir.cpp:1043:43:1043:54 | Address | &:r1043_22 |
|
||||
| ir.cpp:1043:43:1043:54 | Address | &:r1043_24 |
|
||||
| ir.cpp:1043:43:1043:54 | Address | &:r1043_25 |
|
||||
@@ -4856,8 +4853,11 @@
|
||||
| ir.cpp:1043:45:1043:49 | SideEffect | ~m1043_4 |
|
||||
| ir.cpp:1043:45:1043:49 | Unary | r1043_13 |
|
||||
| ir.cpp:1043:45:1043:49 | Unary | r1043_15 |
|
||||
| ir.cpp:1043:53:1043:53 | Load | ~m1043_20 |
|
||||
| ir.cpp:1043:53:1043:53 | Right | r1043_26 |
|
||||
| ir.cpp:1043:52:1043:52 | Address | &:r1043_16 |
|
||||
| ir.cpp:1043:52:1043:52 | Arg(this) | this:r1043_16 |
|
||||
| ir.cpp:1043:52:1043:52 | SideEffect | ~m1043_20 |
|
||||
| ir.cpp:1043:54:1043:54 | Load | ~m1043_20 |
|
||||
| ir.cpp:1043:54:1043:54 | Right | r1043_26 |
|
||||
| ir.cpp:1043:58:1043:58 | ChiPartial | partial:m1043_9 |
|
||||
| ir.cpp:1043:58:1043:58 | ChiTotal | total:m1043_3 |
|
||||
| ir.cpp:1043:58:1043:58 | StoreValue | r1043_8 |
|
||||
@@ -4972,9 +4972,6 @@
|
||||
| ir.cpp:1047:34:1047:34 | SideEffect | ~m1047_20 |
|
||||
| ir.cpp:1047:41:1047:41 | Address | &:r1047_9 |
|
||||
| ir.cpp:1047:46:1047:65 | Address | &:r1047_11 |
|
||||
| ir.cpp:1047:53:1047:53 | Address | &:r1047_16 |
|
||||
| ir.cpp:1047:53:1047:53 | Arg(this) | this:r1047_16 |
|
||||
| ir.cpp:1047:53:1047:53 | SideEffect | ~m1047_20 |
|
||||
| ir.cpp:1047:53:1047:64 | Address | &:r1047_23 |
|
||||
| ir.cpp:1047:53:1047:64 | Load | ~m1047_20 |
|
||||
| ir.cpp:1047:53:1047:64 | StoreValue | r1047_24 |
|
||||
@@ -4989,6 +4986,9 @@
|
||||
| ir.cpp:1047:55:1047:59 | SideEffect | ~m1047_4 |
|
||||
| ir.cpp:1047:55:1047:59 | Unary | r1047_13 |
|
||||
| ir.cpp:1047:55:1047:59 | Unary | r1047_15 |
|
||||
| ir.cpp:1047:62:1047:62 | Address | &:r1047_16 |
|
||||
| ir.cpp:1047:62:1047:62 | Arg(this) | this:r1047_16 |
|
||||
| ir.cpp:1047:62:1047:62 | SideEffect | ~m1047_20 |
|
||||
| ir.cpp:1047:63:1047:63 | Right | r1047_22 |
|
||||
| ir.cpp:1047:68:1047:68 | StoreValue | r1047_8 |
|
||||
| ir.cpp:1047:68:1047:68 | Unary | r1047_7 |
|
||||
@@ -5097,9 +5097,6 @@
|
||||
| ir.cpp:1051:39:1051:39 | SideEffect | ~m1051_20 |
|
||||
| ir.cpp:1051:46:1051:46 | Address | &:r1051_9 |
|
||||
| ir.cpp:1051:51:1051:70 | Address | &:r1051_11 |
|
||||
| ir.cpp:1051:58:1051:58 | Address | &:r1051_16 |
|
||||
| ir.cpp:1051:58:1051:58 | Arg(this) | this:r1051_16 |
|
||||
| ir.cpp:1051:58:1051:58 | SideEffect | ~m1051_20 |
|
||||
| ir.cpp:1051:58:1051:69 | Address | &:r1051_22 |
|
||||
| ir.cpp:1051:58:1051:69 | Address | &:r1051_24 |
|
||||
| ir.cpp:1051:58:1051:69 | Address | &:r1051_26 |
|
||||
@@ -5120,6 +5117,9 @@
|
||||
| ir.cpp:1051:60:1051:64 | SideEffect | ~m1051_4 |
|
||||
| ir.cpp:1051:60:1051:64 | Unary | r1051_13 |
|
||||
| ir.cpp:1051:60:1051:64 | Unary | r1051_15 |
|
||||
| ir.cpp:1051:67:1051:67 | Address | &:r1051_16 |
|
||||
| ir.cpp:1051:67:1051:67 | Arg(this) | this:r1051_16 |
|
||||
| ir.cpp:1051:67:1051:67 | SideEffect | ~m1051_20 |
|
||||
| ir.cpp:1051:73:1051:73 | ChiPartial | partial:m1051_9 |
|
||||
| ir.cpp:1051:73:1051:73 | ChiTotal | total:m1051_3 |
|
||||
| ir.cpp:1051:73:1051:73 | StoreValue | r1051_8 |
|
||||
@@ -5184,9 +5184,6 @@
|
||||
| ir.cpp:1054:49:1054:49 | SideEffect | ~m1054_20 |
|
||||
| ir.cpp:1054:56:1054:56 | Address | &:r1054_9 |
|
||||
| ir.cpp:1054:61:1054:88 | Address | &:r1054_11 |
|
||||
| ir.cpp:1054:68:1054:68 | Address | &:r1054_16 |
|
||||
| ir.cpp:1054:68:1054:68 | Arg(this) | this:r1054_16 |
|
||||
| ir.cpp:1054:68:1054:68 | SideEffect | ~m1054_20 |
|
||||
| ir.cpp:1054:68:1054:87 | Address | &:r1054_37 |
|
||||
| ir.cpp:1054:68:1054:87 | Load | ~m1054_20 |
|
||||
| ir.cpp:1054:68:1054:87 | StoreValue | r1054_38 |
|
||||
@@ -5201,6 +5198,9 @@
|
||||
| ir.cpp:1054:70:1054:74 | SideEffect | ~m1054_4 |
|
||||
| ir.cpp:1054:70:1054:74 | Unary | r1054_13 |
|
||||
| ir.cpp:1054:70:1054:74 | Unary | r1054_15 |
|
||||
| ir.cpp:1054:77:1054:77 | Address | &:r1054_16 |
|
||||
| ir.cpp:1054:77:1054:77 | Arg(this) | this:r1054_16 |
|
||||
| ir.cpp:1054:77:1054:77 | SideEffect | ~m1054_20 |
|
||||
| ir.cpp:1054:78:1054:82 | Address | &:r1054_22 |
|
||||
| ir.cpp:1054:78:1054:82 | Address | &:r1054_24 |
|
||||
| ir.cpp:1054:78:1054:82 | Left | r1054_25 |
|
||||
|
||||
@@ -156,10 +156,10 @@
|
||||
| captures.cpp:23:12:23:16 | x |
|
||||
| captures.cpp:23:12:23:16 | y |
|
||||
| captures.cpp:23:12:23:20 | ... + ... |
|
||||
| captures.cpp:23:16:23:16 | (reference dereference) |
|
||||
| captures.cpp:23:16:23:16 | definition of y |
|
||||
| captures.cpp:23:16:23:16 | y |
|
||||
| captures.cpp:23:16:23:16 | y |
|
||||
| captures.cpp:23:18:23:18 | (reference dereference) |
|
||||
| captures.cpp:23:20:23:20 | z |
|
||||
| captures.cpp:26:3:26:24 | return ... |
|
||||
| captures.cpp:26:10:26:17 | (const lambda [] type at line 22, col. 19)... |
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
| stmts.c:3:5:3:10 | declaration | true | true |
|
||||
| stmts.c:4:5:4:18 | declaration | true | true |
|
||||
| stmts.c:5:5:5:16 | declaration | false | true |
|
||||
| stmts.c:7:5:7:5 | { ... } | true | true |
|
||||
| stmts.c:7:5:14:5 | switch (...) ... | true | true |
|
||||
| stmts.c:7:15:14:5 | { ... } | true | true |
|
||||
| stmts.c:8:9:8:15 | case ...: | true | true |
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
| switch.c:2:5:2:5 | f | switch.c:2:14:12:1 | { ... } | switch.c:3:5:10:5 | switch (...) ... |
|
||||
| switch.c:2:5:2:5 | f | switch.c:2:14:12:1 | { ... } | switch.c:10:5:10:5 | label ...: |
|
||||
| switch.c:2:5:2:5 | f | switch.c:2:14:12:1 | { ... } | switch.c:3:5:3:5 | { ... } |
|
||||
| switch.c:2:5:2:5 | f | switch.c:2:14:12:1 | { ... } | switch.c:11:5:11:13 | return ... |
|
||||
| switch.c:14:6:14:6 | g | switch.c:14:15:52:1 | { ... } | switch.c:15:2:15:7 | declaration |
|
||||
| switch.c:14:6:14:6 | g | switch.c:14:15:52:1 | { ... } | switch.c:17:5:26:5 | switch (...) ... |
|
||||
| switch.c:14:6:14:6 | g | switch.c:14:15:52:1 | { ... } | switch.c:26:5:26:5 | label ...: |
|
||||
| switch.c:14:6:14:6 | g | switch.c:14:15:52:1 | { ... } | switch.c:17:5:17:5 | { ... } |
|
||||
| switch.c:14:6:14:6 | g | switch.c:14:15:52:1 | { ... } | switch.c:28:5:29:5 | switch (...) ... |
|
||||
| switch.c:14:6:14:6 | g | switch.c:14:15:52:1 | { ... } | switch.c:31:5:44:2 | switch (...) ... |
|
||||
| switch.c:14:6:14:6 | g | switch.c:14:15:52:1 | { ... } | switch.c:44:2:44:2 | label ...: |
|
||||
| switch.c:14:6:14:6 | g | switch.c:14:15:52:1 | { ... } | switch.c:31:5:31:5 | { ... } |
|
||||
| switch.c:14:6:14:6 | g | switch.c:14:15:52:1 | { ... } | switch.c:46:2:51:2 | switch (...) ... |
|
||||
| switch.c:14:6:14:6 | g | switch.c:14:15:52:1 | { ... } | switch.c:52:1:52:1 | return ... |
|
||||
| switch.cpp:4:5:4:5 | f | switch.cpp:4:14:9:1 | { ... } | switch.cpp:5:5:8:5 | switch (...) ... |
|
||||
|
||||
@@ -1,87 +1,89 @@
|
||||
| 10 | 1 | { ... } | 12 switch (...) ... |
|
||||
| 10 | 43 | f | <no successors> |
|
||||
| 12 | 2 | switch (...) ... | 12 cond |
|
||||
| 12 | 3 | cond | 12 { ... } |
|
||||
| 12 | 4 | { ... } | 13 case ...: |
|
||||
| 12 | 4 | { ... } | 16 case ...: |
|
||||
| 12 | 4 | { ... } | 18 case ...: |
|
||||
| 12 | 4 | { ... } | 21 case ...: |
|
||||
| 12 | 4 | { ... } | 22 case ...: |
|
||||
| 12 | 4 | { ... } | 24 case ...: |
|
||||
| 12 | 4 | { ... } | 25 default: |
|
||||
| 12 | 4 | { ... } | 26 case ...: |
|
||||
| 12 | 4 | { ... } | 28 case ...: |
|
||||
| 10 | 1 | { ... } | 12 { ... } |
|
||||
| 10 | 44 | f | <no successors> |
|
||||
| 12 | 2 | { ... } | 12 switch (...) ... |
|
||||
| 12 | 3 | switch (...) ... | 12 cond |
|
||||
| 12 | 4 | cond | 12 { ... } |
|
||||
| 12 | 5 | { ... } | 13 case ...: |
|
||||
| 12 | 5 | { ... } | 16 case ...: |
|
||||
| 12 | 5 | { ... } | 18 case ...: |
|
||||
| 12 | 5 | { ... } | 21 case ...: |
|
||||
| 12 | 5 | { ... } | 22 case ...: |
|
||||
| 12 | 5 | { ... } | 24 case ...: |
|
||||
| 12 | 5 | { ... } | 25 default: |
|
||||
| 12 | 5 | { ... } | 26 case ...: |
|
||||
| 12 | 5 | { ... } | 28 case ...: |
|
||||
| 13 | 1 | 1 | <no successors> |
|
||||
| 13 | 5 | case ...: | 14 ExprStmt |
|
||||
| 14 | 6 | ExprStmt | 14 111 |
|
||||
| 14 | 7 | 111 | 14 x |
|
||||
| 14 | 8 | x | 14 ... = ... |
|
||||
| 14 | 9 | ... = ... | 15 break; |
|
||||
| 15 | 10 | break; | 31 label ...: |
|
||||
| 13 | 6 | case ...: | 14 ExprStmt |
|
||||
| 14 | 7 | ExprStmt | 14 111 |
|
||||
| 14 | 8 | 111 | 14 x |
|
||||
| 14 | 9 | x | 14 ... = ... |
|
||||
| 14 | 10 | ... = ... | 15 break; |
|
||||
| 15 | 11 | break; | 31 label ...: |
|
||||
| 16 | 1 | 1 | <no successors> |
|
||||
| 16 | 1 | 2 | <no successors> |
|
||||
| 16 | 1 | ... + ... | <no successors> |
|
||||
| 16 | 5 | case ...: | 17 ExprStmt |
|
||||
| 17 | 6 | ExprStmt | 17 333 |
|
||||
| 17 | 7 | 333 | 17 x |
|
||||
| 17 | 8 | x | 17 ... = ... |
|
||||
| 17 | 9 | ... = ... | 18 case ...: |
|
||||
| 16 | 6 | case ...: | 17 ExprStmt |
|
||||
| 17 | 7 | ExprStmt | 17 333 |
|
||||
| 17 | 8 | 333 | 17 x |
|
||||
| 17 | 9 | x | 17 ... = ... |
|
||||
| 17 | 10 | ... = ... | 18 case ...: |
|
||||
| 18 | 1 | 4 | <no successors> |
|
||||
| 18 | 10 | case ...: | 19 ExprStmt |
|
||||
| 19 | 11 | ExprStmt | 19 444 |
|
||||
| 19 | 12 | 444 | 19 x |
|
||||
| 19 | 13 | x | 19 ... = ... |
|
||||
| 19 | 14 | ... = ... | 20 break; |
|
||||
| 20 | 15 | break; | 31 label ...: |
|
||||
| 18 | 11 | case ...: | 19 ExprStmt |
|
||||
| 19 | 12 | ExprStmt | 19 444 |
|
||||
| 19 | 13 | 444 | 19 x |
|
||||
| 19 | 14 | x | 19 ... = ... |
|
||||
| 19 | 15 | ... = ... | 20 break; |
|
||||
| 20 | 16 | break; | 31 label ...: |
|
||||
| 21 | 1 | 5 | <no successors> |
|
||||
| 21 | 5 | case ...: | 22 case ...: |
|
||||
| 21 | 6 | case ...: | 22 case ...: |
|
||||
| 22 | 1 | 6 | <no successors> |
|
||||
| 22 | 6 | case ...: | 23 ExprStmt |
|
||||
| 23 | 7 | ExprStmt | 23 777 |
|
||||
| 23 | 8 | 777 | 23 x |
|
||||
| 23 | 9 | x | 23 ... = ... |
|
||||
| 23 | 10 | ... = ... | 24 case ...: |
|
||||
| 22 | 7 | case ...: | 23 ExprStmt |
|
||||
| 23 | 8 | ExprStmt | 23 777 |
|
||||
| 23 | 9 | 777 | 23 x |
|
||||
| 23 | 10 | x | 23 ... = ... |
|
||||
| 23 | 11 | ... = ... | 24 case ...: |
|
||||
| 24 | 1 | 7 | <no successors> |
|
||||
| 24 | 11 | case ...: | 25 default: |
|
||||
| 25 | 12 | default: | 26 case ...: |
|
||||
| 24 | 12 | case ...: | 25 default: |
|
||||
| 25 | 13 | default: | 26 case ...: |
|
||||
| 26 | 1 | 8 | <no successors> |
|
||||
| 26 | 13 | case ...: | 27 ExprStmt |
|
||||
| 27 | 14 | ExprStmt | 27 888 |
|
||||
| 27 | 15 | 888 | 27 x |
|
||||
| 27 | 16 | x | 27 ... = ... |
|
||||
| 27 | 17 | ... = ... | 28 case ...: |
|
||||
| 26 | 14 | case ...: | 27 ExprStmt |
|
||||
| 27 | 15 | ExprStmt | 27 888 |
|
||||
| 27 | 16 | 888 | 27 x |
|
||||
| 27 | 17 | x | 27 ... = ... |
|
||||
| 27 | 18 | ... = ... | 28 case ...: |
|
||||
| 28 | 1 | 9 | <no successors> |
|
||||
| 28 | 18 | case ...: | 29 ExprStmt |
|
||||
| 29 | 19 | ExprStmt | 29 999 |
|
||||
| 29 | 20 | 999 | 29 x |
|
||||
| 29 | 21 | x | 29 ... = ... |
|
||||
| 29 | 22 | ... = ... | 30 break; |
|
||||
| 30 | 23 | break; | 31 label ...: |
|
||||
| 31 | 41 | label ...: | 33 return ... |
|
||||
| 33 | 42 | return ... | 10 f |
|
||||
| 36 | 1 | { ... } | 38 switch (...) ... |
|
||||
| 36 | 22 | g | <no successors> |
|
||||
| 38 | 2 | switch (...) ... | 38 cond |
|
||||
| 38 | 3 | cond | 38 { ... } |
|
||||
| 38 | 4 | { ... } | 39 case ...: |
|
||||
| 38 | 4 | { ... } | 42 case ...: |
|
||||
| 38 | 4 | { ... } | 45 label ...: |
|
||||
| 28 | 19 | case ...: | 29 ExprStmt |
|
||||
| 29 | 20 | ExprStmt | 29 999 |
|
||||
| 29 | 21 | 999 | 29 x |
|
||||
| 29 | 22 | x | 29 ... = ... |
|
||||
| 29 | 23 | ... = ... | 30 break; |
|
||||
| 30 | 24 | break; | 31 label ...: |
|
||||
| 31 | 42 | label ...: | 33 return ... |
|
||||
| 33 | 43 | return ... | 10 f |
|
||||
| 36 | 1 | { ... } | 38 { ... } |
|
||||
| 36 | 23 | g | <no successors> |
|
||||
| 38 | 2 | { ... } | 38 switch (...) ... |
|
||||
| 38 | 3 | switch (...) ... | 38 cond |
|
||||
| 38 | 4 | cond | 38 { ... } |
|
||||
| 38 | 5 | { ... } | 39 case ...: |
|
||||
| 38 | 5 | { ... } | 42 case ...: |
|
||||
| 38 | 5 | { ... } | 45 label ...: |
|
||||
| 39 | 1 | 1 | <no successors> |
|
||||
| 39 | 5 | case ...: | 40 ExprStmt |
|
||||
| 40 | 6 | ExprStmt | 40 111 |
|
||||
| 40 | 7 | 111 | 40 x |
|
||||
| 40 | 8 | x | 40 ... = ... |
|
||||
| 40 | 9 | ... = ... | 41 break; |
|
||||
| 41 | 10 | break; | 45 label ...: |
|
||||
| 39 | 6 | case ...: | 40 ExprStmt |
|
||||
| 40 | 7 | ExprStmt | 40 111 |
|
||||
| 40 | 8 | 111 | 40 x |
|
||||
| 40 | 9 | x | 40 ... = ... |
|
||||
| 40 | 10 | ... = ... | 41 break; |
|
||||
| 41 | 11 | break; | 45 label ...: |
|
||||
| 42 | 1 | 2 | <no successors> |
|
||||
| 42 | 5 | case ...: | 43 ExprStmt |
|
||||
| 43 | 6 | ExprStmt | 43 222 |
|
||||
| 43 | 7 | 222 | 43 x |
|
||||
| 43 | 8 | x | 43 ... = ... |
|
||||
| 43 | 9 | ... = ... | 45 label ...: |
|
||||
| 45 | 16 | label ...: | 46 ExprStmt |
|
||||
| 46 | 17 | ExprStmt | 46 999 |
|
||||
| 46 | 18 | 999 | 46 x |
|
||||
| 46 | 19 | x | 46 ... = ... |
|
||||
| 46 | 20 | ... = ... | 48 return ... |
|
||||
| 48 | 21 | return ... | 36 g |
|
||||
| 42 | 6 | case ...: | 43 ExprStmt |
|
||||
| 43 | 7 | ExprStmt | 43 222 |
|
||||
| 43 | 8 | 222 | 43 x |
|
||||
| 43 | 9 | x | 43 ... = ... |
|
||||
| 43 | 10 | ... = ... | 45 label ...: |
|
||||
| 45 | 17 | label ...: | 46 ExprStmt |
|
||||
| 46 | 18 | ExprStmt | 46 999 |
|
||||
| 46 | 19 | 999 | 46 x |
|
||||
| 46 | 20 | x | 46 ... = ... |
|
||||
| 46 | 21 | ... = ... | 48 return ... |
|
||||
| 48 | 22 | return ... | 36 g |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// semmle-extractor-options: --clang
|
||||
// semmle-extractor-options: --clang --edg --clang_version --edg 30500
|
||||
|
||||
#define vector(elcount, type) __attribute__((vector_size((elcount)*sizeof(type)))) type
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// semmle-extractor-options: --edg --clang --edg --clang_version --edg 30801
|
||||
// Compilable with: clang --std=c++0x -msse4.1 vector_types.cpp
|
||||
// (some bits also compilable with gcc)
|
||||
|
||||
int printf(...);
|
||||
|
||||
typedef float v4f __attribute__((vector_size(16)));
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
// semmle-extractor-options: -std=c++14
|
||||
class MyClass
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -105,3 +105,8 @@ _Noreturn void f15();
|
||||
int f16() {
|
||||
f15(); // GOOD
|
||||
}
|
||||
|
||||
int f17() {
|
||||
if (__builtin_expect(1, 0))
|
||||
__builtin_unreachable(); // GOOD
|
||||
}
|
||||
|
||||
@@ -1,138 +1,142 @@
|
||||
| f | false | 54 | 54 | f\ntest.c:2:5:2:5 |
|
||||
| f | false | 65 | 65 | 0\ntest.c:3:17:3:18 |
|
||||
| f | false | 66 | 66 | initializer for result\ntest.c:3:17:3:18 |
|
||||
| f | false | 69 | 69 | declaration\ntest.c:3:5:3:19 |
|
||||
| f | false | 71 | 71 | i\ntest.c:4:9:4:9 |
|
||||
| f | false | 75 | 75 | 0\ntest.c:4:14:4:14 |
|
||||
| f | false | 76 | 76 | ... != ...\ntest.c:4:9:4:14 |
|
||||
| f | false | 78 | 78 | result\ntest.c:5:9:5:14 |
|
||||
| f | false | 80 | 80 | ... ++\ntest.c:5:9:5:16 |
|
||||
| f | false | 82 | 82 | ExprStmt\ntest.c:5:9:5:17 |
|
||||
| f | false | 84 | 84 | i\ntest.c:6:16:6:16 |
|
||||
| f | false | 88 | 88 | 10\ntest.c:6:20:6:21 |
|
||||
| f | false | 89 | 89 | ... < ...\ntest.c:6:16:6:21 |
|
||||
| f | false | 91 | 91 | i\ntest.c:7:17:7:17 |
|
||||
| f | false | 93 | 93 | ... ++\ntest.c:7:17:7:19 |
|
||||
| f | false | 97 | 97 | 5\ntest.c:7:24:7:24 |
|
||||
| f | false | 98 | 98 | ... == ...\ntest.c:7:17:7:24 |
|
||||
| f | false | 100 | 100 | result\ntest.c:8:17:8:22 |
|
||||
| f | false | 104 | 104 | 7\ntest.c:8:26:8:26 |
|
||||
| f | false | 105 | 105 | ... = ...\ntest.c:8:17:8:26 |
|
||||
| f | false | 107 | 107 | ExprStmt\ntest.c:8:17:8:27 |
|
||||
| f | false | 109 | 109 | break;\ntest.c:9:17:9:22 |
|
||||
| f | false | 111 | 111 | { ... }\ntest.c:7:27:10:13 |
|
||||
| f | false | 113 | 113 | if (...) ... \ntest.c:7:13:10:13 |
|
||||
| f | false | 115 | 115 | { ... }\ntest.c:6:24:11:9 |
|
||||
| f | false | 117 | 117 | while (...) ...\ntest.c:6:9:11:9 |
|
||||
| f | false | 119 | 119 | label ...:\ntest.c:11:9:11:9 |
|
||||
| f | false | 121 | 121 | { ... }\ntest.c:4:17:12:5 |
|
||||
| f | false | 123 | 123 | if (...) ... \ntest.c:4:5:12:5 |
|
||||
| f | false | 125 | 125 | result\ntest.c:13:12:13:17 |
|
||||
| f | false | 127 | 127 | return ...\ntest.c:13:5:13:18 |
|
||||
| f | false | 129 | 129 | { ... }\ntest.c:2:14:14:1 |
|
||||
| f | true | 65 | 123 | |
|
||||
| f | true | 66 | 65 | |
|
||||
| f | true | 69 | 66 | |
|
||||
| f | true | 71 | 75 | |
|
||||
| f | true | 75 | 76 | |
|
||||
| f | true | 76 | 121 | T |
|
||||
| f | true | 76 | 127 | F |
|
||||
| f | true | 78 | 80 | |
|
||||
| f | true | 80 | 117 | |
|
||||
| f | true | 82 | 78 | |
|
||||
| f | true | 84 | 88 | |
|
||||
| f | true | 88 | 89 | |
|
||||
| f | true | 89 | 115 | T |
|
||||
| f | true | 89 | 119 | F |
|
||||
| f | true | 91 | 93 | |
|
||||
| f | true | 93 | 97 | |
|
||||
| f | true | 97 | 98 | |
|
||||
| f | true | 98 | 84 | F |
|
||||
| f | true | 98 | 111 | T |
|
||||
| f | true | 100 | 105 | |
|
||||
| f | true | 104 | 100 | |
|
||||
| f | true | 105 | 109 | |
|
||||
| f | true | 107 | 104 | |
|
||||
| f | true | 109 | 119 | |
|
||||
| f | true | 111 | 107 | |
|
||||
| f | true | 113 | 91 | |
|
||||
| f | true | 115 | 113 | |
|
||||
| f | true | 117 | 84 | |
|
||||
| f | true | 119 | 127 | |
|
||||
| f | true | 121 | 82 | |
|
||||
| f | true | 123 | 71 | |
|
||||
| f | true | 125 | 54 | |
|
||||
| f | true | 127 | 125 | |
|
||||
| f | true | 129 | 69 | |
|
||||
| f_for | false | 131 | 131 | f_for\ntest.c:16:6:16:10 |
|
||||
| f_for | false | 142 | 142 | 0\ntest.c:18:12:18:13 |
|
||||
| f_for | false | 143 | 143 | initializer for x\ntest.c:18:12:18:13 |
|
||||
| f_for | false | 146 | 146 | declaration\ntest.c:17:5:17:10 |
|
||||
| f_for | false | 148 | 148 | declaration\ntest.c:18:5:18:14 |
|
||||
| f_for | false | 150 | 150 | i\ntest.c:20:16:20:16 |
|
||||
| f_for | false | 154 | 154 | 10\ntest.c:20:20:20:21 |
|
||||
| f_for | false | 155 | 155 | ... < ...\ntest.c:20:16:20:21 |
|
||||
| f_for | false | 157 | 157 | i\ntest.c:21:13:21:13 |
|
||||
| f_for | false | 161 | 161 | 5\ntest.c:21:18:21:18 |
|
||||
| f_for | false | 162 | 162 | ... == ...\ntest.c:21:13:21:18 |
|
||||
| f_for | false | 164 | 164 | continue;\ntest.c:22:13:22:21 |
|
||||
| f_for | false | 166 | 166 | { ... }\ntest.c:21:21:23:9 |
|
||||
| f_for | false | 168 | 168 | if (...) ... \ntest.c:21:9:23:9 |
|
||||
| f_for | false | 170 | 170 | i\ntest.c:24:13:24:13 |
|
||||
| f_for | false | 174 | 174 | 7\ntest.c:24:18:24:18 |
|
||||
| f_for | false | 175 | 175 | ... == ...\ntest.c:24:13:24:18 |
|
||||
| f_for | false | 177 | 177 | break;\ntest.c:25:13:25:18 |
|
||||
| f_for | false | 179 | 179 | { ... }\ntest.c:24:21:26:9 |
|
||||
| f_for | false | 181 | 181 | if (...) ... \ntest.c:24:9:26:9 |
|
||||
| f_for | false | 183 | 183 | x\ntest.c:27:9:27:9 |
|
||||
| f_for | false | 185 | 185 | ... ++\ntest.c:27:9:27:11 |
|
||||
| f_for | false | 187 | 187 | ExprStmt\ntest.c:27:9:27:12 |
|
||||
| f_for | false | 189 | 189 | label ...:\ntest.c:20:5:20:5 |
|
||||
| f_for | false | 191 | 191 | { ... }\ntest.c:20:29:28:5 |
|
||||
| f_for | false | 193 | 193 | i\ntest.c:20:9:20:9 |
|
||||
| f_for | false | 197 | 197 | 0\ntest.c:20:13:20:13 |
|
||||
| f_for | false | 198 | 198 | ... = ...\ntest.c:20:9:20:13 |
|
||||
| f_for | false | 200 | 200 | ExprStmt\ntest.c:20:9:20:14 |
|
||||
| f_for | false | 202 | 202 | i\ntest.c:20:24:20:24 |
|
||||
| f_for | false | 204 | 204 | ... ++\ntest.c:20:24:20:26 |
|
||||
| f_for | false | 206 | 206 | for(...;...;...) ...\ntest.c:20:5:28:5 |
|
||||
| f_for | false | 208 | 208 | label ...:\ntest.c:28:5:28:5 |
|
||||
| f_for | false | 210 | 210 | return ...\ntest.c:29:1:29:1 |
|
||||
| f_for | false | 212 | 212 | { ... }\ntest.c:16:18:29:1 |
|
||||
| f_for | true | 142 | 206 | |
|
||||
| f_for | true | 143 | 142 | |
|
||||
| f_for | true | 146 | 148 | |
|
||||
| f_for | true | 148 | 143 | |
|
||||
| f_for | true | 150 | 154 | |
|
||||
| f_for | true | 154 | 155 | |
|
||||
| f_for | true | 155 | 191 | T |
|
||||
| f_for | true | 155 | 208 | F |
|
||||
| f_for | true | 157 | 161 | |
|
||||
| f_for | true | 161 | 162 | |
|
||||
| f_for | true | 162 | 166 | T |
|
||||
| f_for | true | 162 | 181 | F |
|
||||
| f_for | true | 164 | 189 | |
|
||||
| f_for | true | 166 | 164 | |
|
||||
| f_for | true | 168 | 157 | |
|
||||
| f_for | true | 170 | 174 | |
|
||||
| f_for | true | 174 | 175 | |
|
||||
| f_for | true | 175 | 179 | T |
|
||||
| f_for | true | 175 | 187 | F |
|
||||
| f_for | true | 177 | 208 | |
|
||||
| f_for | true | 179 | 177 | |
|
||||
| f_for | true | 181 | 170 | |
|
||||
| f_for | true | 183 | 185 | |
|
||||
| f_for | true | 185 | 189 | |
|
||||
| f_for | true | 187 | 183 | |
|
||||
| f_for | true | 189 | 202 | |
|
||||
| f_for | true | 191 | 168 | |
|
||||
| f_for | true | 193 | 198 | |
|
||||
| f_for | true | 197 | 193 | |
|
||||
| f_for | true | 198 | 150 | |
|
||||
| f_for | true | 200 | 197 | |
|
||||
| f_for | true | 202 | 204 | |
|
||||
| f_for | true | 204 | 150 | |
|
||||
| f_for | true | 206 | 200 | |
|
||||
| f_for | true | 208 | 210 | |
|
||||
| f_for | true | 210 | 131 | |
|
||||
| f_for | true | 212 | 146 | |
|
||||
| f | false | 205 | 205 | f\ntest.c:2:5:2:5 |
|
||||
| f | false | 213 | 213 | declaration\ntest.c:3:5:3:19 |
|
||||
| f | false | 218 | 218 | 0\ntest.c:3:17:3:18 |
|
||||
| f | false | 219 | 219 | initializer for result\ntest.c:3:17:3:18 |
|
||||
| f | false | 222 | 222 | if (...) ... \ntest.c:4:5:12:5 |
|
||||
| f | false | 224 | 224 | i\ntest.c:4:9:4:9 |
|
||||
| f | false | 228 | 228 | 0\ntest.c:4:14:4:14 |
|
||||
| f | false | 229 | 229 | ... != ...\ntest.c:4:9:4:14 |
|
||||
| f | false | 231 | 231 | ExprStmt\ntest.c:5:9:5:17 |
|
||||
| f | false | 233 | 233 | result\ntest.c:5:9:5:14 |
|
||||
| f | false | 235 | 235 | ... ++\ntest.c:5:9:5:16 |
|
||||
| f | false | 237 | 237 | while (...) ...\ntest.c:6:9:11:9 |
|
||||
| f | false | 239 | 239 | i\ntest.c:6:16:6:16 |
|
||||
| f | false | 243 | 243 | 10\ntest.c:6:20:6:21 |
|
||||
| f | false | 244 | 244 | ... < ...\ntest.c:6:16:6:21 |
|
||||
| f | false | 246 | 246 | if (...) ... \ntest.c:7:13:10:13 |
|
||||
| f | false | 248 | 248 | i\ntest.c:7:17:7:17 |
|
||||
| f | false | 250 | 250 | ... ++\ntest.c:7:17:7:19 |
|
||||
| f | false | 254 | 254 | 5\ntest.c:7:24:7:24 |
|
||||
| f | false | 255 | 255 | ... == ...\ntest.c:7:17:7:24 |
|
||||
| f | false | 257 | 257 | ExprStmt\ntest.c:8:17:8:27 |
|
||||
| f | false | 259 | 259 | result\ntest.c:8:17:8:22 |
|
||||
| f | false | 263 | 263 | 7\ntest.c:8:26:8:26 |
|
||||
| f | false | 264 | 264 | ... = ...\ntest.c:8:17:8:26 |
|
||||
| f | false | 266 | 266 | break;\ntest.c:9:17:9:22 |
|
||||
| f | false | 268 | 268 | { ... }\ntest.c:7:27:10:13 |
|
||||
| f | false | 270 | 270 | { ... }\ntest.c:6:24:11:9 |
|
||||
| f | false | 272 | 272 | label ...:\ntest.c:11:9:11:9 |
|
||||
| f | false | 274 | 274 | { ... }\ntest.c:6:9:6:9 |
|
||||
| f | false | 276 | 276 | { ... }\ntest.c:4:17:12:5 |
|
||||
| f | false | 278 | 278 | return ...\ntest.c:13:5:13:18 |
|
||||
| f | false | 280 | 280 | result\ntest.c:13:12:13:17 |
|
||||
| f | false | 282 | 282 | { ... }\ntest.c:2:14:14:1 |
|
||||
| f | true | 213 | 219 | |
|
||||
| f | true | 218 | 222 | |
|
||||
| f | true | 219 | 218 | |
|
||||
| f | true | 222 | 224 | |
|
||||
| f | true | 224 | 228 | |
|
||||
| f | true | 228 | 229 | |
|
||||
| f | true | 229 | 276 | T |
|
||||
| f | true | 229 | 278 | F |
|
||||
| f | true | 231 | 233 | |
|
||||
| f | true | 233 | 235 | |
|
||||
| f | true | 235 | 274 | |
|
||||
| f | true | 237 | 239 | |
|
||||
| f | true | 239 | 243 | |
|
||||
| f | true | 243 | 244 | |
|
||||
| f | true | 244 | 270 | T |
|
||||
| f | true | 244 | 272 | F |
|
||||
| f | true | 246 | 248 | |
|
||||
| f | true | 248 | 250 | |
|
||||
| f | true | 250 | 254 | |
|
||||
| f | true | 254 | 255 | |
|
||||
| f | true | 255 | 239 | F |
|
||||
| f | true | 255 | 268 | T |
|
||||
| f | true | 257 | 263 | |
|
||||
| f | true | 259 | 264 | |
|
||||
| f | true | 263 | 259 | |
|
||||
| f | true | 264 | 266 | |
|
||||
| f | true | 266 | 272 | |
|
||||
| f | true | 268 | 257 | |
|
||||
| f | true | 270 | 246 | |
|
||||
| f | true | 272 | 278 | |
|
||||
| f | true | 274 | 237 | |
|
||||
| f | true | 276 | 231 | |
|
||||
| f | true | 278 | 280 | |
|
||||
| f | true | 280 | 205 | |
|
||||
| f | true | 282 | 213 | |
|
||||
| f_for | false | 121 | 121 | f_for\ntest.c:16:6:16:10 |
|
||||
| f_for | false | 126 | 126 | declaration\ntest.c:17:5:17:10 |
|
||||
| f_for | false | 131 | 131 | declaration\ntest.c:18:5:18:14 |
|
||||
| f_for | false | 136 | 136 | 0\ntest.c:18:12:18:13 |
|
||||
| f_for | false | 137 | 137 | initializer for x\ntest.c:18:12:18:13 |
|
||||
| f_for | false | 140 | 140 | for(...;...;...) ...\ntest.c:20:5:28:5 |
|
||||
| f_for | false | 142 | 142 | i\ntest.c:20:16:20:16 |
|
||||
| f_for | false | 146 | 146 | 10\ntest.c:20:20:20:21 |
|
||||
| f_for | false | 147 | 147 | ... < ...\ntest.c:20:16:20:21 |
|
||||
| f_for | false | 149 | 149 | if (...) ... \ntest.c:21:9:23:9 |
|
||||
| f_for | false | 151 | 151 | i\ntest.c:21:13:21:13 |
|
||||
| f_for | false | 155 | 155 | 5\ntest.c:21:18:21:18 |
|
||||
| f_for | false | 156 | 156 | ... == ...\ntest.c:21:13:21:18 |
|
||||
| f_for | false | 158 | 158 | continue;\ntest.c:22:13:22:21 |
|
||||
| f_for | false | 160 | 160 | { ... }\ntest.c:21:21:23:9 |
|
||||
| f_for | false | 162 | 162 | if (...) ... \ntest.c:24:9:26:9 |
|
||||
| f_for | false | 164 | 164 | i\ntest.c:24:13:24:13 |
|
||||
| f_for | false | 168 | 168 | 7\ntest.c:24:18:24:18 |
|
||||
| f_for | false | 169 | 169 | ... == ...\ntest.c:24:13:24:18 |
|
||||
| f_for | false | 171 | 171 | break;\ntest.c:25:13:25:18 |
|
||||
| f_for | false | 173 | 173 | { ... }\ntest.c:24:21:26:9 |
|
||||
| f_for | false | 175 | 175 | ExprStmt\ntest.c:27:9:27:12 |
|
||||
| f_for | false | 177 | 177 | x\ntest.c:27:9:27:9 |
|
||||
| f_for | false | 179 | 179 | ... ++\ntest.c:27:9:27:11 |
|
||||
| f_for | false | 181 | 181 | label ...:\ntest.c:20:5:20:5 |
|
||||
| f_for | false | 183 | 183 | { ... }\ntest.c:20:29:28:5 |
|
||||
| f_for | false | 185 | 185 | ExprStmt\ntest.c:20:9:20:14 |
|
||||
| f_for | false | 187 | 187 | i\ntest.c:20:9:20:9 |
|
||||
| f_for | false | 191 | 191 | 0\ntest.c:20:13:20:13 |
|
||||
| f_for | false | 192 | 192 | ... = ...\ntest.c:20:9:20:13 |
|
||||
| f_for | false | 194 | 194 | i\ntest.c:20:24:20:24 |
|
||||
| f_for | false | 196 | 196 | ... ++\ntest.c:20:24:20:26 |
|
||||
| f_for | false | 198 | 198 | label ...:\ntest.c:28:5:28:5 |
|
||||
| f_for | false | 200 | 200 | { ... }\ntest.c:20:5:20:5 |
|
||||
| f_for | false | 201 | 201 | return ...\ntest.c:29:1:29:1 |
|
||||
| f_for | false | 203 | 203 | { ... }\ntest.c:16:18:29:1 |
|
||||
| f_for | true | 126 | 131 | |
|
||||
| f_for | true | 131 | 137 | |
|
||||
| f_for | true | 136 | 200 | |
|
||||
| f_for | true | 137 | 136 | |
|
||||
| f_for | true | 140 | 185 | |
|
||||
| f_for | true | 142 | 146 | |
|
||||
| f_for | true | 146 | 147 | |
|
||||
| f_for | true | 147 | 183 | T |
|
||||
| f_for | true | 147 | 198 | F |
|
||||
| f_for | true | 149 | 151 | |
|
||||
| f_for | true | 151 | 155 | |
|
||||
| f_for | true | 155 | 156 | |
|
||||
| f_for | true | 156 | 160 | T |
|
||||
| f_for | true | 156 | 162 | F |
|
||||
| f_for | true | 158 | 181 | |
|
||||
| f_for | true | 160 | 158 | |
|
||||
| f_for | true | 162 | 164 | |
|
||||
| f_for | true | 164 | 168 | |
|
||||
| f_for | true | 168 | 169 | |
|
||||
| f_for | true | 169 | 173 | T |
|
||||
| f_for | true | 169 | 175 | F |
|
||||
| f_for | true | 171 | 198 | |
|
||||
| f_for | true | 173 | 171 | |
|
||||
| f_for | true | 175 | 177 | |
|
||||
| f_for | true | 177 | 179 | |
|
||||
| f_for | true | 179 | 181 | |
|
||||
| f_for | true | 181 | 194 | |
|
||||
| f_for | true | 183 | 149 | |
|
||||
| f_for | true | 185 | 191 | |
|
||||
| f_for | true | 187 | 192 | |
|
||||
| f_for | true | 191 | 187 | |
|
||||
| f_for | true | 192 | 142 | |
|
||||
| f_for | true | 194 | 196 | |
|
||||
| f_for | true | 196 | 142 | |
|
||||
| f_for | true | 198 | 201 | |
|
||||
| f_for | true | 200 | 140 | |
|
||||
| f_for | true | 201 | 121 | |
|
||||
| f_for | true | 203 | 126 | |
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
| 0 | dostmt.c:8:22:14:1 | { ... } | 1 | dostmt.c:9:3:12:13 | do (...) ... |
|
||||
| 0 | dostmt.c:8:22:14:1 | { ... } | 1 | dostmt.c:9:3:9:3 | { ... } |
|
||||
| 1 | dostmt.c:9:3:9:3 | { ... } | 1 | dostmt.c:9:3:12:13 | do (...) ... |
|
||||
| 1 | dostmt.c:9:3:12:13 | do (...) ... | 1 | dostmt.c:9:6:12:3 | { ... } |
|
||||
| 1 | dostmt.c:9:6:12:3 | { ... } | 2 | dostmt.c:10:5:10:7 | label ...: |
|
||||
| 2 | dostmt.c:10:5:10:7 | label ...: | 2 | dostmt.c:10:8:10:8 | ; |
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
| 0 | dostmt.c:16:22:23:1 | { ... } | 1 | dostmt.c:17:3:21:13 | do (...) ... |
|
||||
| 0 | dostmt.c:16:22:23:1 | { ... } | 1 | dostmt.c:17:3:17:3 | { ... } |
|
||||
| 1 | dostmt.c:17:3:17:3 | { ... } | 1 | dostmt.c:17:3:21:13 | do (...) ... |
|
||||
| 1 | dostmt.c:17:3:21:13 | do (...) ... | 1 | dostmt.c:17:6:21:3 | { ... } |
|
||||
| 1 | dostmt.c:17:6:21:3 | { ... } | 2 | dostmt.c:18:5:18:7 | label ...: |
|
||||
| 2 | dostmt.c:18:5:18:7 | label ...: | 2 | dostmt.c:18:8:18:8 | ; |
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
| 0 | ifelsestmt.c:11:23:17:1 | { ... } | 1 | ifelsestmt.c:12:3:15:8 | if (...) ... |
|
||||
| 1 | ifelsestmt.c:12:3:15:8 | if (...) ... | 1 | ifelsestmt.c:12:6:12:6 | 0 |
|
||||
| 1 | ifelsestmt.c:12:6:12:6 | 0 | -1 | file://:0:0:0:0 | { ... } |
|
||||
| 1 | ifelsestmt.c:12:6:12:6 | 0 | 4 | ifelsestmt.c:15:5:15:5 | { ... } |
|
||||
| 2 | ifelsestmt.c:13:5:13:5 | { ... } | 2 | ifelsestmt.c:13:5:13:7 | label ...: |
|
||||
| 2 | ifelsestmt.c:13:5:13:7 | label ...: | 2 | ifelsestmt.c:13:8:13:8 | ; |
|
||||
| 2 | ifelsestmt.c:13:8:13:8 | ; | 5 | ifelsestmt.c:16:3:16:5 | label ...: |
|
||||
| 4 | ifelsestmt.c:15:5:15:5 | { ... } | 4 | ifelsestmt.c:15:5:15:7 | label ...: |
|
||||
| 4 | ifelsestmt.c:15:5:15:7 | label ...: | 4 | ifelsestmt.c:15:8:15:8 | ; |
|
||||
| 4 | ifelsestmt.c:15:8:15:8 | ; | 5 | ifelsestmt.c:16:3:16:5 | label ...: |
|
||||
| 5 | ifelsestmt.c:16:3:16:5 | label ...: | 5 | ifelsestmt.c:16:6:16:6 | ; |
|
||||
| 5 | ifelsestmt.c:16:6:16:6 | ; | 6 | ifelsestmt.c:17:1:17:1 | return ... |
|
||||
| 6 | ifelsestmt.c:17:1:17:1 | return ... | 0 | ifelsestmt.c:11:6:11:19 | always_false_2 |
|
||||
| -1 | file://:0:0:0:0 | { ... } | 2 | ifelsestmt.c:13:5:13:7 | label ...: |
|
||||
| -1 | file://:0:0:0:0 | { ... } | 4 | ifelsestmt.c:15:5:15:7 | label ...: |
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
| 0 | ifelsestmt.c:29:22:35:1 | { ... } | 1 | ifelsestmt.c:30:3:33:8 | if (...) ... |
|
||||
| 1 | ifelsestmt.c:30:3:33:8 | if (...) ... | 1 | ifelsestmt.c:30:6:30:6 | 1 |
|
||||
| 1 | ifelsestmt.c:30:6:30:6 | 1 | -1 | file://:0:0:0:0 | { ... } |
|
||||
| 1 | ifelsestmt.c:30:6:30:6 | 1 | 2 | ifelsestmt.c:31:5:31:5 | { ... } |
|
||||
| 2 | ifelsestmt.c:31:5:31:5 | { ... } | 2 | ifelsestmt.c:31:5:31:7 | label ...: |
|
||||
| 2 | ifelsestmt.c:31:5:31:7 | label ...: | 2 | ifelsestmt.c:31:8:31:8 | ; |
|
||||
| 2 | ifelsestmt.c:31:8:31:8 | ; | 5 | ifelsestmt.c:34:3:34:5 | label ...: |
|
||||
| 4 | ifelsestmt.c:33:5:33:5 | { ... } | 4 | ifelsestmt.c:33:5:33:7 | label ...: |
|
||||
| 4 | ifelsestmt.c:33:5:33:7 | label ...: | 4 | ifelsestmt.c:33:8:33:8 | ; |
|
||||
| 4 | ifelsestmt.c:33:8:33:8 | ; | 5 | ifelsestmt.c:34:3:34:5 | label ...: |
|
||||
| 5 | ifelsestmt.c:34:3:34:5 | label ...: | 5 | ifelsestmt.c:34:6:34:6 | ; |
|
||||
| 5 | ifelsestmt.c:34:6:34:6 | ; | 6 | ifelsestmt.c:35:1:35:1 | return ... |
|
||||
| 6 | ifelsestmt.c:35:1:35:1 | return ... | 0 | ifelsestmt.c:29:6:29:18 | always_true_2 |
|
||||
| -1 | file://:0:0:0:0 | { ... } | 2 | ifelsestmt.c:31:5:31:7 | label ...: |
|
||||
| -1 | file://:0:0:0:0 | { ... } | 4 | ifelsestmt.c:33:5:33:7 | label ...: |
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
| 0 | ifstmt.c:8:23:12:1 | { ... } | 1 | ifstmt.c:9:3:10:8 | if (...) ... |
|
||||
| 1 | ifstmt.c:9:3:10:8 | if (...) ... | 1 | ifstmt.c:9:6:9:6 | 0 |
|
||||
| 1 | ifstmt.c:9:6:9:6 | 0 | 3 | ifstmt.c:11:3:11:5 | label ...: |
|
||||
| 2 | ifstmt.c:10:5:10:5 | { ... } | 2 | ifstmt.c:10:5:10:7 | label ...: |
|
||||
| 2 | ifstmt.c:10:5:10:7 | label ...: | 2 | ifstmt.c:10:8:10:8 | ; |
|
||||
| 2 | ifstmt.c:10:8:10:8 | ; | 3 | ifstmt.c:11:3:11:5 | label ...: |
|
||||
| 3 | ifstmt.c:11:3:11:5 | label ...: | 3 | ifstmt.c:11:6:11:6 | ; |
|
||||
| 3 | ifstmt.c:11:6:11:6 | ; | 4 | ifstmt.c:12:1:12:1 | return ... |
|
||||
| 4 | ifstmt.c:12:1:12:1 | return ... | 0 | ifstmt.c:8:6:8:19 | always_false_2 |
|
||||
| -1 | file://:0:0:0:0 | { ... } | 2 | ifstmt.c:10:5:10:7 | label ...: |
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
| 0 | ifstmt.c:21:22:25:1 | { ... } | 1 | ifstmt.c:22:3:23:8 | if (...) ... |
|
||||
| 1 | ifstmt.c:22:3:23:8 | if (...) ... | 1 | ifstmt.c:22:6:22:6 | 1 |
|
||||
| 1 | ifstmt.c:22:6:22:6 | 1 | -1 | file://:0:0:0:0 | { ... } |
|
||||
| 1 | ifstmt.c:22:6:22:6 | 1 | 2 | ifstmt.c:23:5:23:5 | { ... } |
|
||||
| 2 | ifstmt.c:23:5:23:5 | { ... } | 2 | ifstmt.c:23:5:23:7 | label ...: |
|
||||
| 2 | ifstmt.c:23:5:23:7 | label ...: | 2 | ifstmt.c:23:8:23:8 | ; |
|
||||
| 2 | ifstmt.c:23:8:23:8 | ; | 3 | ifstmt.c:24:3:24:5 | label ...: |
|
||||
| 3 | ifstmt.c:24:3:24:5 | label ...: | 3 | ifstmt.c:24:6:24:6 | ; |
|
||||
| 3 | ifstmt.c:24:6:24:6 | ; | 4 | ifstmt.c:25:1:25:1 | return ... |
|
||||
| 4 | ifstmt.c:25:1:25:1 | return ... | 0 | ifstmt.c:21:6:21:18 | always_true_2 |
|
||||
| -1 | file://:0:0:0:0 | { ... } | 2 | ifstmt.c:23:5:23:7 | label ...: |
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
||||
| 0 | whilestmt.c:15:22:21:1 | { ... } | 1 | whilestmt.c:16:3:19:3 | while (...) ... |
|
||||
| 0 | whilestmt.c:15:22:21:1 | { ... } | 1 | whilestmt.c:16:3:16:3 | { ... } |
|
||||
| 1 | whilestmt.c:16:3:16:3 | { ... } | 1 | whilestmt.c:16:3:19:3 | while (...) ... |
|
||||
| 1 | whilestmt.c:16:3:19:3 | while (...) ... | 1 | whilestmt.c:16:9:16:9 | 1 |
|
||||
| 1 | whilestmt.c:16:9:16:9 | 1 | 1 | whilestmt.c:16:12:19:3 | { ... } |
|
||||
| 1 | whilestmt.c:16:12:19:3 | { ... } | 2 | whilestmt.c:17:5:17:7 | label ...: |
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
| 0 | whilestmt.c:23:22:30:1 | { ... } | 1 | whilestmt.c:24:3:28:3 | while (...) ... |
|
||||
| 0 | whilestmt.c:23:22:30:1 | { ... } | 1 | whilestmt.c:24:3:24:3 | { ... } |
|
||||
| 1 | whilestmt.c:24:3:24:3 | { ... } | 1 | whilestmt.c:24:3:28:3 | while (...) ... |
|
||||
| 1 | whilestmt.c:24:3:28:3 | while (...) ... | 1 | whilestmt.c:24:9:24:9 | 1 |
|
||||
| 1 | whilestmt.c:24:9:24:9 | 1 | 1 | whilestmt.c:24:12:28:3 | { ... } |
|
||||
| 1 | whilestmt.c:24:12:28:3 | { ... } | 2 | whilestmt.c:25:5:25:7 | label ...: |
|
||||
|
||||
Reference in New Issue
Block a user