Merge branch 'main' into redundantImport

This commit is contained in:
Erik Krogh Kristensen
2022-04-26 14:24:51 +02:00
889 changed files with 9741 additions and 3014 deletions

View File

@@ -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

View File

@@ -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.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* The `semmle.code.cpp.security.SensitiveExprs` library has been enhanced with some additional rules for detecting credentials.

View File

@@ -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.

View 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.

View File

@@ -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)`.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* More Windows pool allocation functions are now detected as `AllocationFunction`s.

View 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.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.0.13
lastReleaseVersion: 0.1.0

View File

@@ -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

View File

@@ -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

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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 {

View File

@@ -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()

View File

@@ -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.
*

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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()

View File

@@ -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 {

View File

@@ -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.
*

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -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.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* The `cpp/unused-local-variable` no longer ignores functions that include lambda expressions capturing trivially copyable objects.

View File

@@ -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.

View 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.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.0.13
lastReleaseVersion: 0.1.0

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 0.1.0-dev
version: 0.1.1-dev
groups:
- cpp
- queries

View File

@@ -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 | { ... } |

View File

@@ -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 ... |

View File

@@ -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. |

View File

@@ -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 |

View File

@@ -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 | |

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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)... |

View File

@@ -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 |

View File

@@ -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 (...) ... |

View File

@@ -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 |

View File

@@ -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

View File

@@ -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)));

View File

@@ -1,4 +1,4 @@
// semmle-extractor-options: -std=c++14
class MyClass
{
public:

View File

@@ -105,3 +105,8 @@ _Noreturn void f15();
int f16() {
f15(); // GOOD
}
int f17() {
if (__builtin_expect(1, 0))
__builtin_unreachable(); // GOOD
}

View File

@@ -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 | |

View File

@@ -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 | ; |

View File

@@ -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 | ; |

View File

@@ -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 ...: |

View File

@@ -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 ...: |

View File

@@ -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 ...: |

View File

@@ -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

View File

@@ -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 ...: |

View File

@@ -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 ...: |