Merge remote-tracking branch 'origin/main' into dbartol/mergeback-3.10

This commit is contained in:
Dave Bartolomeo
2023-07-06 10:00:46 -04:00
1654 changed files with 47750 additions and 21714 deletions

View File

@@ -2,3 +2,4 @@ name: codeql/cpp-downgrades
groups: cpp
downgrades: .
library: true
warnOnImplicitThis: true

View File

@@ -4,3 +4,4 @@ groups:
- examples
dependencies:
codeql/cpp-all: ${workspace}
warnOnImplicitThis: true

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Deleted the deprecated `getURL` predicate from the `Container`, `Folder`, and `File` classes. Use the `getLocation` predicate instead.

View File

@@ -34,14 +34,6 @@ class Container extends Locatable, @container {
*/
string getAbsolutePath() { none() } // overridden by subclasses
/**
* DEPRECATED: Use `getLocation` instead.
* Gets a URL representing the location of this container.
*
* For more information see [Providing URLs](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/#providing-urls).
*/
deprecated string getURL() { none() } // overridden by subclasses
/**
* Gets the relative path of this file or folder from the root folder of the
* analyzed source location. The relative path of the root folder itself is
@@ -183,12 +175,6 @@ class Folder extends Container, @folder {
}
override string getAPrimaryQlClass() { result = "Folder" }
/**
* DEPRECATED: Use `getLocation` instead.
* Gets the URL of this folder.
*/
deprecated override string getURL() { result = "file://" + this.getAbsolutePath() + ":0:0:0:0" }
}
/**
@@ -213,12 +199,6 @@ class File extends Container, @file {
result.hasLocationInfo(_, 0, 0, 0, 0)
}
/**
* DEPRECATED: Use `getLocation` instead.
* Gets the URL of this file.
*/
deprecated override string getURL() { result = "file://" + this.getAbsolutePath() + ":0:0:0:0" }
/** Holds if this file was compiled as C (at any point). */
predicate compiledAsC() { fileannotations(underlyingElement(this), 1, "compiled as c", "1") }

View File

@@ -460,7 +460,6 @@ module Impl<FullStateConfigSig Config> {
* The Boolean `cc` records whether the node is reached through an
* argument in a call.
*/
pragma[assume_small_delta]
private predicate fwdFlow(NodeEx node, Cc cc) {
sourceNode(node, _) and
if hasSourceCallCtx() then cc = true else cc = false
@@ -570,7 +569,6 @@ module Impl<FullStateConfigSig Config> {
/**
* Holds if `c` is the target of a store in the flow covered by `fwdFlow`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate fwdFlowConsCand(Content c) {
exists(NodeEx mid, NodeEx node |
@@ -1135,8 +1133,8 @@ module Impl<FullStateConfigSig Config> {
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow
);
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap);
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t);
bindingset[typ, contentType]
predicate typecheckStore(Typ typ, DataFlowType contentType);
@@ -1199,20 +1197,23 @@ module Impl<FullStateConfigSig Config> {
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
ApOption argAp, Typ t, Ap ap, ApApprox apa
) {
fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and
PrevStage::revFlow(node, state, apa) and
filter(node, state, t, ap)
fwdFlow1(node, state, cc, summaryCtx, argT, argAp, _, t, ap, apa)
}
pragma[inline]
additional predicate fwdFlow(
private predicate fwdFlow1(
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
ApOption argAp, Typ t, Ap ap
ApOption argAp, Typ t0, Typ t, Ap ap, ApApprox apa
) {
fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _)
fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t0, ap, apa) and
PrevStage::revFlow(node, state, apa) and
filter(node, state, t0, ap, t)
}
pragma[nomagic]
private predicate typeStrengthen(Typ t0, Ap ap, Typ t) {
fwdFlow1(_, _, _, _, _, _, t0, t, ap, _) and t0 != t
}
pragma[assume_small_delta]
pragma[nomagic]
private predicate fwdFlow0(
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
@@ -1339,6 +1340,11 @@ module Impl<FullStateConfigSig Config> {
private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) {
fwdFlowStore(_, t1, tail, c, t2, _, _, _, _, _, _) and
cons = apCons(c, t1, tail)
or
exists(Typ t0 |
typeStrengthen(t0, cons, t2) and
fwdFlowConsCand(t0, cons, c, t1, tail)
)
}
pragma[nomagic]
@@ -1359,7 +1365,7 @@ module Impl<FullStateConfigSig Config> {
ParamNodeOption summaryCtx, TypOption argT, ApOption argAp
) {
exists(ApHeadContent apc |
fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap) and
fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap, _) and
apc = getHeadContent(ap) and
readStepCand0(node1, apc, c, node2)
)
@@ -1520,14 +1526,14 @@ module Impl<FullStateConfigSig Config> {
NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap
) {
revFlow0(node, state, returnCtx, returnAp, ap) and
fwdFlow(node, state, _, _, _, _, _, ap)
fwdFlow(node, state, _, _, _, _, _, ap, _)
}
pragma[nomagic]
private predicate revFlow0(
NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap
) {
fwdFlow(node, state, _, _, _, _, _, ap) and
fwdFlow(node, state, _, _, _, _, _, ap, _) and
sinkNode(node, state) and
(
if hasSinkCallCtx()
@@ -1780,13 +1786,13 @@ module Impl<FullStateConfigSig Config> {
boolean fwd, int nodes, int fields, int conscand, int states, int tuples
) {
fwd = true and
nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _)) and
nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _, _)) and
fields = count(Content f0 | fwdConsCand(f0, _, _)) and
conscand = count(Content f0, Typ t, Ap ap | fwdConsCand(f0, t, ap)) and
states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _)) and
states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _, _)) and
tuples =
count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap))
ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap, _))
or
fwd = false and
nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and
@@ -1963,10 +1969,10 @@ module Impl<FullStateConfigSig Config> {
)
}
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
PrevStage::revFlowState(state) and
exists(t) and
t0 = t and
exists(ap) and
not stateBarrier(node, state) and
(
@@ -2012,7 +2018,8 @@ module Impl<FullStateConfigSig Config> {
FlowCheckNode() {
castNode(this.asNode()) or
clearsContentCached(this.asNode(), _) or
expectsContentCached(this.asNode(), _)
expectsContentCached(this.asNode(), _) or
neverSkipInPathGraph(this.asNode())
}
}
@@ -2197,8 +2204,8 @@ module Impl<FullStateConfigSig Config> {
import BooleanCallContext
predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, LocalCc lcc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
LocalCc lcc
) {
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and
exists(lcc)
@@ -2218,10 +2225,16 @@ module Impl<FullStateConfigSig Config> {
)
}
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
exists(state) and
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
// We can get away with not using type strengthening here, since we aren't
// going to use the tracked types in the construction of Stage 4 access
// paths. For Stage 4 and onwards, the tracked types must be consistent as
// the cons candidates including types are used to construct subsequent
// access path approximations.
t0 = t and
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t0) else any()) and
(
notExpectsContent(node)
or
@@ -2241,6 +2254,16 @@ module Impl<FullStateConfigSig Config> {
import MkStage<Stage2>::Stage<Stage3Param>
}
bindingset[node, t0]
private predicate strengthenType(NodeEx node, DataFlowType t0, DataFlowType t) {
if castingNodeEx(node)
then
exists(DataFlowType nt | nt = node.getDataFlowType() |
if typeStrongerThan(nt, t0) then t = nt else (compatibleTypes(nt, t0) and t = t0)
)
else t = t0
}
private module Stage4Param implements MkStage<Stage3>::StageParam {
private module PrevStage = Stage3;
@@ -2274,8 +2297,8 @@ module Impl<FullStateConfigSig Config> {
pragma[nomagic]
predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, LocalCc lcc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
LocalCc lcc
) {
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
@@ -2333,11 +2356,11 @@ module Impl<FullStateConfigSig Config> {
)
}
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
exists(state) and
not clear(node, ap) and
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
strengthenType(node, t0, t) and
(
notExpectsContent(node)
or
@@ -2365,7 +2388,7 @@ module Impl<FullStateConfigSig Config> {
exists(AccessPathFront apf |
Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and
Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _,
apf)
apf, _)
)
}
@@ -2579,8 +2602,8 @@ module Impl<FullStateConfigSig Config> {
import LocalCallContext
predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, LocalCc lcc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
LocalCc lcc
) {
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
@@ -2609,9 +2632,9 @@ module Impl<FullStateConfigSig Config> {
)
}
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
strengthenType(node, t0, t) and
exists(state) and
exists(ap)
}
@@ -2632,7 +2655,7 @@ module Impl<FullStateConfigSig Config> {
Stage5::parameterMayFlowThrough(p, _) and
Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0) and
Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), _,
TAccessPathApproxSome(apa), _, apa0)
TAccessPathApproxSome(apa), _, apa0, _)
)
}
@@ -2649,7 +2672,7 @@ module Impl<FullStateConfigSig Config> {
TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) {
exists(AccessPathApprox apa | ap.getApprox() = apa |
Stage5::parameterMayFlowThrough(p, apa) and
Stage5::fwdFlow(p, state, _, _, _, _, t, apa) and
Stage5::fwdFlow(p, state, _, _, Option<DataFlowType>::some(t), _, _, apa, _) and
Stage5::revFlow(p, state, _)
)
}
@@ -2751,7 +2774,6 @@ module Impl<FullStateConfigSig Config> {
/**
* Gets the number of `AccessPath`s that correspond to `apa`.
*/
pragma[assume_small_delta]
private int countAps(AccessPathApprox apa) {
evalUnfold(apa, false) and
result = 1 and
@@ -2770,7 +2792,6 @@ module Impl<FullStateConfigSig Config> {
* that it is expanded to a precise head-tail representation.
*/
language[monotonicAggregates]
pragma[assume_small_delta]
private int countPotentialAps(AccessPathApprox apa) {
apa instanceof AccessPathApproxNil and result = 1
or
@@ -2807,7 +2828,6 @@ module Impl<FullStateConfigSig Config> {
}
private newtype TPathNode =
pragma[assume_small_delta]
TPathNodeMid(
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap
) {
@@ -2820,9 +2840,7 @@ module Impl<FullStateConfigSig Config> {
ap = TAccessPathNil()
or
// ... or a step from an existing PathNode to another node.
pathStep(_, node, state, cc, sc, t, ap) and
Stage5::revFlow(node, state, ap.getApprox()) and
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any())
pathStep(_, node, state, cc, sc, t, ap)
} or
TPathNodeSink(NodeEx node, FlowState state) {
exists(PathNodeMid sink |
@@ -2894,7 +2912,6 @@ module Impl<FullStateConfigSig Config> {
override AccessPathFrontHead getFront() { result = TFrontHead(head_) }
pragma[assume_small_delta]
override AccessPathApproxCons getApprox() {
result = TConsNil(head_, t) and tail_ = TAccessPathNil()
or
@@ -2903,7 +2920,6 @@ module Impl<FullStateConfigSig Config> {
result = TCons1(head_, this.length())
}
pragma[assume_small_delta]
override int length() { result = 1 + tail_.length() }
private string toStringImpl(boolean needsSuffix) {
@@ -3340,13 +3356,23 @@ module Impl<FullStateConfigSig Config> {
ap = mid.getAp()
}
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t,
AccessPath ap
) {
exists(DataFlowType t0 |
pathStep0(mid, node, state, cc, sc, t0, ap) and
Stage5::revFlow(node, state, ap.getApprox()) and
strengthenType(node, t0, t)
)
}
/**
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep(
private predicate pathStep0(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t,
AccessPath ap
) {
@@ -3557,7 +3583,6 @@ module Impl<FullStateConfigSig Config> {
)
}
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathThroughCallable0(
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc,
@@ -3964,7 +3989,7 @@ module Impl<FullStateConfigSig Config> {
ap = TPartialNil() and
exists(explorationLimit())
or
partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
distSrc(node.getEnclosingCallable()) <= explorationLimit()
} or
TPartialPathNodeRev(
@@ -3990,11 +4015,20 @@ module Impl<FullStateConfigSig Config> {
}
pragma[nomagic]
private predicate partialPathNodeMk0(
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
private predicate partialPathStep(
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
) {
partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
partialPathStep1(mid, node, state, cc, sc1, sc2, sc3, sc4, _, t, ap)
}
pragma[nomagic]
private predicate partialPathStep1(
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t0, DataFlowType t,
PartialAccessPath ap
) {
partialPathStep0(mid, node, state, cc, sc1, sc2, sc3, sc4, t0, ap) and
not fullBarrier(node) and
not stateBarrier(node, state) and
not clearsContentEx(node, ap.getHead()) and
@@ -4002,9 +4036,14 @@ module Impl<FullStateConfigSig Config> {
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), t)
else any()
strengthenType(node, t0, t)
}
pragma[nomagic]
private predicate partialPathTypeStrengthen(
DataFlowType t0, PartialAccessPath ap, DataFlowType t
) {
partialPathStep1(_, _, _, _, _, _, _, _, t0, t, ap) and t0 != t
}
/**
@@ -4183,7 +4222,8 @@ module Impl<FullStateConfigSig Config> {
}
}
private predicate partialPathStep(
pragma[nomagic]
private predicate partialPathStep0(
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
) {
@@ -4309,6 +4349,11 @@ module Impl<FullStateConfigSig Config> {
DataFlowType t1, PartialAccessPath ap1, Content c, DataFlowType t2, PartialAccessPath ap2
) {
partialPathStoreStep(_, t1, ap1, c, _, t2, ap2)
or
exists(DataFlowType t0 |
partialPathTypeStrengthen(t0, ap2, t2) and
apConsFwd(t1, ap1, c, t0, ap2)
)
}
pragma[nomagic]

View File

@@ -187,7 +187,6 @@ private module LambdaFlow {
else any()
}
pragma[assume_small_delta]
pragma[nomagic]
predicate revLambdaFlow0(
DataFlowCall lambdaCall, LambdaCallKind kind, Node node, DataFlowType t, boolean toReturn,
@@ -274,7 +273,6 @@ private module LambdaFlow {
)
}
pragma[assume_small_delta]
pragma[nomagic]
predicate revLambdaFlowOut(
DataFlowCall lambdaCall, LambdaCallKind kind, TReturnPositionSimple pos, DataFlowType t,

View File

@@ -205,6 +205,8 @@ predicate clearsContent(Node n, Content c) {
*/
predicate expectsContent(Node n, ContentSet c) { none() }
predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() }
/** Gets the type of `n` used for type pruning. */
Type getNodeType(Node n) {
suppressUnusedNode(n) and
@@ -233,6 +235,12 @@ class CastNode extends Node {
CastNode() { none() } // stub implementation
}
/**
* Holds if `n` should never be skipped over in the `PathGraph` and in path
* explanations.
*/
predicate neverSkipInPathGraph(Node n) { none() }
class DataFlowCallable = Function;
class DataFlowExpr = Expr;

View File

@@ -460,7 +460,6 @@ module Impl<FullStateConfigSig Config> {
* The Boolean `cc` records whether the node is reached through an
* argument in a call.
*/
pragma[assume_small_delta]
private predicate fwdFlow(NodeEx node, Cc cc) {
sourceNode(node, _) and
if hasSourceCallCtx() then cc = true else cc = false
@@ -570,7 +569,6 @@ module Impl<FullStateConfigSig Config> {
/**
* Holds if `c` is the target of a store in the flow covered by `fwdFlow`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate fwdFlowConsCand(Content c) {
exists(NodeEx mid, NodeEx node |
@@ -1135,8 +1133,8 @@ module Impl<FullStateConfigSig Config> {
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow
);
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap);
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t);
bindingset[typ, contentType]
predicate typecheckStore(Typ typ, DataFlowType contentType);
@@ -1199,20 +1197,23 @@ module Impl<FullStateConfigSig Config> {
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
ApOption argAp, Typ t, Ap ap, ApApprox apa
) {
fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and
PrevStage::revFlow(node, state, apa) and
filter(node, state, t, ap)
fwdFlow1(node, state, cc, summaryCtx, argT, argAp, _, t, ap, apa)
}
pragma[inline]
additional predicate fwdFlow(
private predicate fwdFlow1(
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
ApOption argAp, Typ t, Ap ap
ApOption argAp, Typ t0, Typ t, Ap ap, ApApprox apa
) {
fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _)
fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t0, ap, apa) and
PrevStage::revFlow(node, state, apa) and
filter(node, state, t0, ap, t)
}
pragma[nomagic]
private predicate typeStrengthen(Typ t0, Ap ap, Typ t) {
fwdFlow1(_, _, _, _, _, _, t0, t, ap, _) and t0 != t
}
pragma[assume_small_delta]
pragma[nomagic]
private predicate fwdFlow0(
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
@@ -1339,6 +1340,11 @@ module Impl<FullStateConfigSig Config> {
private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) {
fwdFlowStore(_, t1, tail, c, t2, _, _, _, _, _, _) and
cons = apCons(c, t1, tail)
or
exists(Typ t0 |
typeStrengthen(t0, cons, t2) and
fwdFlowConsCand(t0, cons, c, t1, tail)
)
}
pragma[nomagic]
@@ -1359,7 +1365,7 @@ module Impl<FullStateConfigSig Config> {
ParamNodeOption summaryCtx, TypOption argT, ApOption argAp
) {
exists(ApHeadContent apc |
fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap) and
fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap, _) and
apc = getHeadContent(ap) and
readStepCand0(node1, apc, c, node2)
)
@@ -1520,14 +1526,14 @@ module Impl<FullStateConfigSig Config> {
NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap
) {
revFlow0(node, state, returnCtx, returnAp, ap) and
fwdFlow(node, state, _, _, _, _, _, ap)
fwdFlow(node, state, _, _, _, _, _, ap, _)
}
pragma[nomagic]
private predicate revFlow0(
NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap
) {
fwdFlow(node, state, _, _, _, _, _, ap) and
fwdFlow(node, state, _, _, _, _, _, ap, _) and
sinkNode(node, state) and
(
if hasSinkCallCtx()
@@ -1780,13 +1786,13 @@ module Impl<FullStateConfigSig Config> {
boolean fwd, int nodes, int fields, int conscand, int states, int tuples
) {
fwd = true and
nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _)) and
nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _, _)) and
fields = count(Content f0 | fwdConsCand(f0, _, _)) and
conscand = count(Content f0, Typ t, Ap ap | fwdConsCand(f0, t, ap)) and
states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _)) and
states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _, _)) and
tuples =
count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap))
ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap, _))
or
fwd = false and
nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and
@@ -1963,10 +1969,10 @@ module Impl<FullStateConfigSig Config> {
)
}
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
PrevStage::revFlowState(state) and
exists(t) and
t0 = t and
exists(ap) and
not stateBarrier(node, state) and
(
@@ -2012,7 +2018,8 @@ module Impl<FullStateConfigSig Config> {
FlowCheckNode() {
castNode(this.asNode()) or
clearsContentCached(this.asNode(), _) or
expectsContentCached(this.asNode(), _)
expectsContentCached(this.asNode(), _) or
neverSkipInPathGraph(this.asNode())
}
}
@@ -2197,8 +2204,8 @@ module Impl<FullStateConfigSig Config> {
import BooleanCallContext
predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, LocalCc lcc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
LocalCc lcc
) {
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and
exists(lcc)
@@ -2218,10 +2225,16 @@ module Impl<FullStateConfigSig Config> {
)
}
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
exists(state) and
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
// We can get away with not using type strengthening here, since we aren't
// going to use the tracked types in the construction of Stage 4 access
// paths. For Stage 4 and onwards, the tracked types must be consistent as
// the cons candidates including types are used to construct subsequent
// access path approximations.
t0 = t and
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t0) else any()) and
(
notExpectsContent(node)
or
@@ -2241,6 +2254,16 @@ module Impl<FullStateConfigSig Config> {
import MkStage<Stage2>::Stage<Stage3Param>
}
bindingset[node, t0]
private predicate strengthenType(NodeEx node, DataFlowType t0, DataFlowType t) {
if castingNodeEx(node)
then
exists(DataFlowType nt | nt = node.getDataFlowType() |
if typeStrongerThan(nt, t0) then t = nt else (compatibleTypes(nt, t0) and t = t0)
)
else t = t0
}
private module Stage4Param implements MkStage<Stage3>::StageParam {
private module PrevStage = Stage3;
@@ -2274,8 +2297,8 @@ module Impl<FullStateConfigSig Config> {
pragma[nomagic]
predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, LocalCc lcc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
LocalCc lcc
) {
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
@@ -2333,11 +2356,11 @@ module Impl<FullStateConfigSig Config> {
)
}
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
exists(state) and
not clear(node, ap) and
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
strengthenType(node, t0, t) and
(
notExpectsContent(node)
or
@@ -2365,7 +2388,7 @@ module Impl<FullStateConfigSig Config> {
exists(AccessPathFront apf |
Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and
Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _,
apf)
apf, _)
)
}
@@ -2579,8 +2602,8 @@ module Impl<FullStateConfigSig Config> {
import LocalCallContext
predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, LocalCc lcc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
LocalCc lcc
) {
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
@@ -2609,9 +2632,9 @@ module Impl<FullStateConfigSig Config> {
)
}
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
strengthenType(node, t0, t) and
exists(state) and
exists(ap)
}
@@ -2632,7 +2655,7 @@ module Impl<FullStateConfigSig Config> {
Stage5::parameterMayFlowThrough(p, _) and
Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0) and
Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), _,
TAccessPathApproxSome(apa), _, apa0)
TAccessPathApproxSome(apa), _, apa0, _)
)
}
@@ -2649,7 +2672,7 @@ module Impl<FullStateConfigSig Config> {
TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) {
exists(AccessPathApprox apa | ap.getApprox() = apa |
Stage5::parameterMayFlowThrough(p, apa) and
Stage5::fwdFlow(p, state, _, _, _, _, t, apa) and
Stage5::fwdFlow(p, state, _, _, Option<DataFlowType>::some(t), _, _, apa, _) and
Stage5::revFlow(p, state, _)
)
}
@@ -2751,7 +2774,6 @@ module Impl<FullStateConfigSig Config> {
/**
* Gets the number of `AccessPath`s that correspond to `apa`.
*/
pragma[assume_small_delta]
private int countAps(AccessPathApprox apa) {
evalUnfold(apa, false) and
result = 1 and
@@ -2770,7 +2792,6 @@ module Impl<FullStateConfigSig Config> {
* that it is expanded to a precise head-tail representation.
*/
language[monotonicAggregates]
pragma[assume_small_delta]
private int countPotentialAps(AccessPathApprox apa) {
apa instanceof AccessPathApproxNil and result = 1
or
@@ -2807,7 +2828,6 @@ module Impl<FullStateConfigSig Config> {
}
private newtype TPathNode =
pragma[assume_small_delta]
TPathNodeMid(
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap
) {
@@ -2820,9 +2840,7 @@ module Impl<FullStateConfigSig Config> {
ap = TAccessPathNil()
or
// ... or a step from an existing PathNode to another node.
pathStep(_, node, state, cc, sc, t, ap) and
Stage5::revFlow(node, state, ap.getApprox()) and
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any())
pathStep(_, node, state, cc, sc, t, ap)
} or
TPathNodeSink(NodeEx node, FlowState state) {
exists(PathNodeMid sink |
@@ -2894,7 +2912,6 @@ module Impl<FullStateConfigSig Config> {
override AccessPathFrontHead getFront() { result = TFrontHead(head_) }
pragma[assume_small_delta]
override AccessPathApproxCons getApprox() {
result = TConsNil(head_, t) and tail_ = TAccessPathNil()
or
@@ -2903,7 +2920,6 @@ module Impl<FullStateConfigSig Config> {
result = TCons1(head_, this.length())
}
pragma[assume_small_delta]
override int length() { result = 1 + tail_.length() }
private string toStringImpl(boolean needsSuffix) {
@@ -3340,13 +3356,23 @@ module Impl<FullStateConfigSig Config> {
ap = mid.getAp()
}
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t,
AccessPath ap
) {
exists(DataFlowType t0 |
pathStep0(mid, node, state, cc, sc, t0, ap) and
Stage5::revFlow(node, state, ap.getApprox()) and
strengthenType(node, t0, t)
)
}
/**
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep(
private predicate pathStep0(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t,
AccessPath ap
) {
@@ -3557,7 +3583,6 @@ module Impl<FullStateConfigSig Config> {
)
}
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathThroughCallable0(
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc,
@@ -3964,7 +3989,7 @@ module Impl<FullStateConfigSig Config> {
ap = TPartialNil() and
exists(explorationLimit())
or
partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
distSrc(node.getEnclosingCallable()) <= explorationLimit()
} or
TPartialPathNodeRev(
@@ -3990,11 +4015,20 @@ module Impl<FullStateConfigSig Config> {
}
pragma[nomagic]
private predicate partialPathNodeMk0(
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
private predicate partialPathStep(
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
) {
partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
partialPathStep1(mid, node, state, cc, sc1, sc2, sc3, sc4, _, t, ap)
}
pragma[nomagic]
private predicate partialPathStep1(
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t0, DataFlowType t,
PartialAccessPath ap
) {
partialPathStep0(mid, node, state, cc, sc1, sc2, sc3, sc4, t0, ap) and
not fullBarrier(node) and
not stateBarrier(node, state) and
not clearsContentEx(node, ap.getHead()) and
@@ -4002,9 +4036,14 @@ module Impl<FullStateConfigSig Config> {
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), t)
else any()
strengthenType(node, t0, t)
}
pragma[nomagic]
private predicate partialPathTypeStrengthen(
DataFlowType t0, PartialAccessPath ap, DataFlowType t
) {
partialPathStep1(_, _, _, _, _, _, _, _, t0, t, ap) and t0 != t
}
/**
@@ -4183,7 +4222,8 @@ module Impl<FullStateConfigSig Config> {
}
}
private predicate partialPathStep(
pragma[nomagic]
private predicate partialPathStep0(
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
) {
@@ -4309,6 +4349,11 @@ module Impl<FullStateConfigSig Config> {
DataFlowType t1, PartialAccessPath ap1, Content c, DataFlowType t2, PartialAccessPath ap2
) {
partialPathStoreStep(_, t1, ap1, c, _, t2, ap2)
or
exists(DataFlowType t0 |
partialPathTypeStrengthen(t0, ap2, t2) and
apConsFwd(t1, ap1, c, t0, ap2)
)
}
pragma[nomagic]

View File

@@ -187,7 +187,6 @@ private module LambdaFlow {
else any()
}
pragma[assume_small_delta]
pragma[nomagic]
predicate revLambdaFlow0(
DataFlowCall lambdaCall, LambdaCallKind kind, Node node, DataFlowType t, boolean toReturn,
@@ -274,7 +273,6 @@ private module LambdaFlow {
)
}
pragma[assume_small_delta]
pragma[nomagic]
predicate revLambdaFlowOut(
DataFlowCall lambdaCall, LambdaCallKind kind, TReturnPositionSimple pos, DataFlowType t,

View File

@@ -193,86 +193,89 @@ private class SingleUseOperandNode0 extends OperandNode0, TSingleUseOperandNode0
SingleUseOperandNode0() { this = TSingleUseOperandNode0(op) }
}
/**
* INTERNAL: Do not use.
*
* A node that represents the indirect value of an operand in the IR
* after `index` number of loads.
*
* Note: Unlike `RawIndirectOperand`, a value of type `IndirectOperand` may
* be an `OperandNode`.
*/
class IndirectOperand extends Node {
Operand operand;
int indirectionIndex;
IndirectOperand() {
this.(RawIndirectOperand).getOperand() = operand and
this.(RawIndirectOperand).getIndirectionIndex() = indirectionIndex
or
nodeHasOperand(this, Ssa::getIRRepresentationOfIndirectOperand(operand, indirectionIndex),
indirectionIndex - 1)
private module IndirectOperands {
/**
* INTERNAL: Do not use.
*
* A node that represents the indirect value of an operand in the IR
* after `index` number of loads.
*
* Note: Unlike `RawIndirectOperand`, a value of type `IndirectOperand` may
* be an `OperandNode`.
*/
abstract class IndirectOperand extends Node {
/** Gets the underlying operand and the underlying indirection index. */
abstract predicate hasOperandAndIndirectionIndex(Operand operand, int indirectionIndex);
}
/** Gets the underlying operand. */
Operand getOperand() { result = operand }
private class IndirectOperandFromRaw extends IndirectOperand instanceof RawIndirectOperand {
override predicate hasOperandAndIndirectionIndex(Operand operand, int indirectionIndex) {
operand = RawIndirectOperand.super.getOperand() and
indirectionIndex = RawIndirectOperand.super.getIndirectionIndex()
}
}
/** Gets the underlying indirection index. */
int getIndirectionIndex() { result = indirectionIndex }
private class IndirectOperandFromIRRepr extends IndirectOperand {
Operand operand;
int indirectionIndex;
/**
* Holds if this `IndirectOperand` is represented directly in the IR instead of
* a `RawIndirectionOperand` with operand `op` and indirection index `index`.
*/
predicate isIRRepresentationOf(Operand op, int index) {
this instanceof OperandNode and
(
op = operand and
index = indirectionIndex
)
IndirectOperandFromIRRepr() {
exists(Operand repr |
repr = Ssa::getIRRepresentationOfIndirectOperand(operand, indirectionIndex) and
nodeHasOperand(this, repr, indirectionIndex - 1)
)
}
override predicate hasOperandAndIndirectionIndex(Operand op, int index) {
op = operand and index = indirectionIndex
}
}
}
/**
* INTERNAL: Do not use.
*
* A node that represents the indirect value of an instruction in the IR
* after `index` number of loads.
*
* Note: Unlike `RawIndirectInstruction`, a value of type `IndirectInstruction` may
* be an `InstructionNode`.
*/
class IndirectInstruction extends Node {
Instruction instr;
int indirectionIndex;
import IndirectOperands
IndirectInstruction() {
this.(RawIndirectInstruction).getInstruction() = instr and
this.(RawIndirectInstruction).getIndirectionIndex() = indirectionIndex
or
nodeHasInstruction(this, Ssa::getIRRepresentationOfIndirectInstruction(instr, indirectionIndex),
indirectionIndex - 1)
private module IndirectInstructions {
/**
* INTERNAL: Do not use.
*
* A node that represents the indirect value of an instruction in the IR
* after `index` number of loads.
*
* Note: Unlike `RawIndirectInstruction`, a value of type `IndirectInstruction` may
* be an `InstructionNode`.
*/
abstract class IndirectInstruction extends Node {
/** Gets the underlying operand and the underlying indirection index. */
abstract predicate hasInstructionAndIndirectionIndex(Instruction instr, int index);
}
/** Gets the underlying instruction. */
Instruction getInstruction() { result = instr }
private class IndirectInstructionFromRaw extends IndirectInstruction instanceof RawIndirectInstruction
{
override predicate hasInstructionAndIndirectionIndex(Instruction instr, int index) {
instr = RawIndirectInstruction.super.getInstruction() and
index = RawIndirectInstruction.super.getIndirectionIndex()
}
}
/** Gets the underlying indirection index. */
int getIndirectionIndex() { result = indirectionIndex }
private class IndirectInstructionFromIRRepr extends IndirectInstruction {
Instruction instr;
int indirectionIndex;
/**
* Holds if this `IndirectInstruction` is represented directly in the IR instead of
* a `RawIndirectionInstruction` with instruction `i` and indirection index `index`.
*/
predicate isIRRepresentationOf(Instruction i, int index) {
this instanceof InstructionNode and
(
i = instr and
index = indirectionIndex
)
IndirectInstructionFromIRRepr() {
exists(Instruction repr |
repr = Ssa::getIRRepresentationOfIndirectInstruction(instr, indirectionIndex) and
nodeHasInstruction(this, repr, indirectionIndex - 1)
)
}
override predicate hasInstructionAndIndirectionIndex(Instruction i, int index) {
i = instr and index = indirectionIndex
}
}
}
import IndirectInstructions
/** Gets the callable in which this node occurs. */
DataFlowCallable nodeGetEnclosingCallable(Node n) { result = n.getEnclosingCallable() }
@@ -318,9 +321,11 @@ private class PrimaryArgumentNode extends ArgumentNode, OperandNode {
private class SideEffectArgumentNode extends ArgumentNode, SideEffectOperandNode {
override predicate argumentOf(DataFlowCall dfCall, ArgumentPosition pos) {
this.getCallInstruction() = dfCall and
pos.(IndirectionPosition).getArgumentIndex() = this.getArgumentIndex() and
pos.(IndirectionPosition).getIndirectionIndex() = super.getIndirectionIndex()
exists(int indirectionIndex |
pos = TIndirectionPosition(argumentIndex, pragma[only_bind_into](indirectionIndex)) and
this.getCallInstruction() = dfCall and
super.hasAddressOperandAndIndirectionIndex(_, pragma[only_bind_into](indirectionIndex))
)
}
}
@@ -648,13 +653,16 @@ predicate jumpStep(Node n1, Node n2) {
* Holds if data can flow from `node1` to `node2` via an assignment to `f`.
* Thus, `node2` references an object with a field `f` that contains the
* value of `node1`.
*
* The boolean `certain` is true if the destination address does not involve
* any pointer arithmetic, and false otherwise.
*/
predicate storeStep(Node node1, Content c, PostFieldUpdateNode node2) {
predicate storeStepImpl(Node node1, Content c, PostFieldUpdateNode node2, boolean certain) {
exists(int indirectionIndex1, int numberOfLoads, StoreInstruction store |
nodeHasInstruction(node1, store, pragma[only_bind_into](indirectionIndex1)) and
node2.getIndirectionIndex() = 1 and
numberOfLoadsFromOperand(node2.getFieldAddress(), store.getDestinationAddressOperand(),
numberOfLoads)
numberOfLoads, certain)
|
exists(FieldContent fc | fc = c |
fc.getField() = node2.getUpdatedField() and
@@ -668,21 +676,34 @@ predicate storeStep(Node node1, Content c, PostFieldUpdateNode node2) {
)
}
/**
* Holds if data can flow from `node1` to `node2` via an assignment to `f`.
* Thus, `node2` references an object with a field `f` that contains the
* value of `node1`.
*/
predicate storeStep(Node node1, Content c, PostFieldUpdateNode node2) {
storeStepImpl(node1, c, node2, _)
}
/**
* Holds if `operandFrom` flows to `operandTo` using a sequence of conversion-like
* operations and exactly `n` `LoadInstruction` operations.
*/
private predicate numberOfLoadsFromOperandRec(Operand operandFrom, Operand operandTo, int ind) {
private predicate numberOfLoadsFromOperandRec(
Operand operandFrom, Operand operandTo, int ind, boolean certain
) {
exists(Instruction load | Ssa::isDereference(load, operandFrom) |
operandTo = operandFrom and ind = 0
operandTo = operandFrom and ind = 0 and certain = true
or
numberOfLoadsFromOperand(load.getAUse(), operandTo, ind - 1)
numberOfLoadsFromOperand(load.getAUse(), operandTo, ind - 1, certain)
)
or
exists(Operand op, Instruction instr |
exists(Operand op, Instruction instr, boolean isPointerArith, boolean certain0 |
instr = op.getDef() and
conversionFlow(operandFrom, instr, _, _) and
numberOfLoadsFromOperand(op, operandTo, ind)
conversionFlow(operandFrom, instr, isPointerArith, _) and
numberOfLoadsFromOperand(op, operandTo, ind, certain0)
|
if isPointerArith = true then certain = false else certain = certain0
)
}
@@ -690,13 +711,16 @@ private predicate numberOfLoadsFromOperandRec(Operand operandFrom, Operand opera
* Holds if `operandFrom` flows to `operandTo` using a sequence of conversion-like
* operations and exactly `n` `LoadInstruction` operations.
*/
private predicate numberOfLoadsFromOperand(Operand operandFrom, Operand operandTo, int n) {
numberOfLoadsFromOperandRec(operandFrom, operandTo, n)
private predicate numberOfLoadsFromOperand(
Operand operandFrom, Operand operandTo, int n, boolean certain
) {
numberOfLoadsFromOperandRec(operandFrom, operandTo, n, certain)
or
not Ssa::isDereference(_, operandFrom) and
not conversionFlow(operandFrom, _, _, _) and
operandFrom = operandTo and
n = 0
n = 0 and
certain = true
}
// Needed to join on both an operand and an index at the same time.
@@ -726,7 +750,7 @@ predicate readStep(Node node1, Content c, Node node2) {
// The `1` here matches the `node2.getIndirectionIndex() = 1` conjunct
// in `storeStep`.
nodeHasOperand(node1, fa1.getObjectAddressOperand(), 1) and
numberOfLoadsFromOperand(fa1, operand, numberOfLoads)
numberOfLoadsFromOperand(fa1, operand, numberOfLoads, _)
|
exists(FieldContent fc | fc = c |
fc.getField() = fa1.getField() and
@@ -744,7 +768,33 @@ predicate readStep(Node node1, Content c, Node node2) {
* Holds if values stored inside content `c` are cleared at node `n`.
*/
predicate clearsContent(Node n, Content c) {
none() // stub implementation
n =
any(PostUpdateNode pun, Content d | d.impliesClearOf(c) and storeStepImpl(_, d, pun, true) | pun)
.getPreUpdateNode() and
(
// The crement operations and pointer addition and subtraction self-assign. We do not
// want to clear the contents if it is indirectly pointed at by any of these operations,
// as part of the contents might still be accessible afterwards. If there is no such
// indirection clearing the contents is safe.
not exists(Operand op, Cpp::Operation p |
n.(IndirectOperand).hasOperandAndIndirectionIndex(op, _) and
(
p instanceof Cpp::AssignPointerAddExpr or
p instanceof Cpp::AssignPointerSubExpr or
p instanceof Cpp::CrementOperation
)
|
p.getAnOperand() = op.getUse().getAst()
)
or
forex(PostUpdateNode pun, Content d |
pragma[only_bind_into](d).impliesClearOf(pragma[only_bind_into](c)) and
storeStepImpl(_, d, pun, true) and
pun.getPreUpdateNode() = n
|
c.getIndirectionIndex() = d.getIndirectionIndex()
)
)
}
/**
@@ -753,6 +803,8 @@ predicate clearsContent(Node n, Content c) {
*/
predicate expectsContent(Node n, ContentSet c) { none() }
predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() }
/** Gets the type of `n` used for type pruning. */
DataFlowType getNodeType(Node n) {
suppressUnusedNode(n) and
@@ -781,6 +833,12 @@ class CastNode extends Node {
CastNode() { none() } // stub implementation
}
/**
* Holds if `n` should never be skipped over in the `PathGraph` and in path
* explanations.
*/
predicate neverSkipInPathGraph(Node n) { none() }
/**
* A function that may contain code or a variable that may contain itself. When
* flow crosses from one _enclosing callable_ to another, the interprocedural
@@ -798,7 +856,73 @@ class DataFlowCall extends CallInstruction {
Function getEnclosingCallable() { result = this.getEnclosingFunction() }
}
predicate isUnreachableInCall(Node n, DataFlowCall call) { none() } // stub implementation
module IsUnreachableInCall {
private import semmle.code.cpp.ir.ValueNumbering
private import semmle.code.cpp.controlflow.IRGuards as G
private class ConstantIntegralTypeArgumentNode extends PrimaryArgumentNode {
int value;
ConstantIntegralTypeArgumentNode() {
value = op.getDef().(IntegerConstantInstruction).getValue().toInt()
}
int getValue() { result = value }
}
pragma[nomagic]
private predicate ensuresEq(Operand left, Operand right, int k, IRBlock block, boolean areEqual) {
any(G::IRGuardCondition guard).ensuresEq(left, right, k, block, areEqual)
}
pragma[nomagic]
private predicate ensuresLt(Operand left, Operand right, int k, IRBlock block, boolean areEqual) {
any(G::IRGuardCondition guard).ensuresLt(left, right, k, block, areEqual)
}
predicate isUnreachableInCall(Node n, DataFlowCall call) {
exists(
DirectParameterNode paramNode, ConstantIntegralTypeArgumentNode arg,
IntegerConstantInstruction constant, int k, Operand left, Operand right, IRBlock block
|
// arg flows into `paramNode`
DataFlowImplCommon::viableParamArg(call, paramNode, arg) and
left = constant.getAUse() and
right = valueNumber(paramNode.getInstruction()).getAUse() and
block = n.getBasicBlock()
|
// and there's a guard condition which ensures that the result of `left == right + k` is `areEqual`
exists(boolean areEqual |
ensuresEq(pragma[only_bind_into](left), pragma[only_bind_into](right),
pragma[only_bind_into](k), pragma[only_bind_into](block), areEqual)
|
// this block ensures that left = right + k, but it holds that `left != right + k`
areEqual = true and
constant.getValue().toInt() != arg.getValue() + k
or
// this block ensures that or `left != right + k`, but it holds that `left = right + k`
areEqual = false and
constant.getValue().toInt() = arg.getValue() + k
)
or
// or there's a guard condition which ensures that the result of `left < right + k` is `isLessThan`
exists(boolean isLessThan |
ensuresLt(pragma[only_bind_into](left), pragma[only_bind_into](right),
pragma[only_bind_into](k), pragma[only_bind_into](block), isLessThan)
|
isLessThan = true and
// this block ensures that `left < right + k`, but it holds that `left >= right + k`
constant.getValue().toInt() >= arg.getValue() + k
or
// this block ensures that `left >= right + k`, but it holds that `left < right + k`
isLessThan = false and
constant.getValue().toInt() < arg.getValue() + k
)
)
}
}
import IsUnreachableInCall
int accessPathLimit() { result = 5 }
@@ -837,7 +961,7 @@ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preserves
* One example would be to allow flow like `p.foo = p.bar;`, which is disallowed
* by default as a heuristic.
*/
predicate allowParameterReturnInSelf(ParameterNode p) { none() }
predicate allowParameterReturnInSelf(ParameterNode p) { p instanceof IndirectParameterNode }
private predicate fieldHasApproxName(Field f, string s) {
s = f.getName().charAt(0) and

View File

@@ -274,7 +274,7 @@ class Node extends TIRDataFlowNode {
* represents the value of `**x` going into `f`.
*/
Expr asIndirectArgument(int index) {
this.(SideEffectOperandNode).getIndirectionIndex() = index and
this.(SideEffectOperandNode).hasAddressOperandAndIndirectionIndex(_, index) and
result = this.(SideEffectOperandNode).getArgument()
}
@@ -317,7 +317,7 @@ class Node extends TIRDataFlowNode {
index = 0 and
result = this.(ExplicitParameterNode).getParameter()
or
this.(IndirectParameterNode).getIndirectionIndex() = index and
this.(IndirectParameterNode).hasInstructionAndIndirectionIndex(_, index) and
result = this.(IndirectParameterNode).getParameter()
}
@@ -577,15 +577,20 @@ class SsaPhiNode extends Node, TSsaPhiNode {
*
* A node representing a value after leaving a function.
*/
class SideEffectOperandNode extends Node, IndirectOperand {
class SideEffectOperandNode extends Node instanceof IndirectOperand {
CallInstruction call;
int argumentIndex;
SideEffectOperandNode() { operand = call.getArgumentOperand(argumentIndex) }
SideEffectOperandNode() {
IndirectOperand.super.hasOperandAndIndirectionIndex(call.getArgumentOperand(argumentIndex), _)
}
CallInstruction getCallInstruction() { result = call }
Operand getAddressOperand() { result = operand }
/** Gets the underlying operand and the underlying indirection index. */
predicate hasAddressOperandAndIndirectionIndex(Operand operand, int indirectionIndex) {
IndirectOperand.super.hasOperandAndIndirectionIndex(operand, indirectionIndex)
}
int getArgumentIndex() { result = argumentIndex }
@@ -665,10 +670,10 @@ class InitialGlobalValue extends Node, TInitialGlobalValue {
*
* A node representing an indirection of a parameter.
*/
class IndirectParameterNode extends Node, IndirectInstruction {
class IndirectParameterNode extends Node instanceof IndirectInstruction {
InitializeParameterInstruction init;
IndirectParameterNode() { this.getInstruction() = init }
IndirectParameterNode() { IndirectInstruction.super.hasInstructionAndIndirectionIndex(init, _) }
int getArgumentIndex() { init.hasIndex(result) }
@@ -677,7 +682,12 @@ class IndirectParameterNode extends Node, IndirectInstruction {
override Declaration getEnclosingCallable() { result = this.getFunction() }
override Declaration getFunction() { result = this.getInstruction().getEnclosingFunction() }
override Declaration getFunction() { result = init.getEnclosingFunction() }
/** Gets the underlying operand and the underlying indirection index. */
predicate hasInstructionAndIndirectionIndex(Instruction instr, int index) {
IndirectInstruction.super.hasInstructionAndIndirectionIndex(instr, index)
}
override Location getLocationImpl() { result = this.getParameter().getLocation() }
@@ -699,7 +709,8 @@ class IndirectReturnNode extends Node {
IndirectReturnNode() {
this instanceof FinalParameterNode
or
this.(IndirectOperand).getOperand() = any(ReturnValueInstruction ret).getReturnAddressOperand()
this.(IndirectOperand)
.hasOperandAndIndirectionIndex(any(ReturnValueInstruction ret).getReturnAddressOperand(), _)
}
override Declaration getEnclosingCallable() { result = this.getFunction() }
@@ -722,7 +733,7 @@ class IndirectReturnNode extends Node {
int getIndirectionIndex() {
result = this.(FinalParameterNode).getIndirectionIndex()
or
result = this.(IndirectOperand).getIndirectionIndex()
this.(IndirectOperand).hasOperandAndIndirectionIndex(_, result)
}
}
@@ -1106,7 +1117,8 @@ predicate exprNodeShouldBeInstruction(Node node, Expr e) {
/** Holds if `node` should be an `IndirectInstruction` that maps `node.asIndirectExpr()` to `e`. */
predicate indirectExprNodeShouldBeIndirectInstruction(IndirectInstruction node, Expr e) {
exists(Instruction instr |
instr = node.getInstruction() and not indirectExprNodeShouldBeIndirectOperand(_, e)
node.hasInstructionAndIndirectionIndex(instr, _) and
not indirectExprNodeShouldBeIndirectOperand(_, e)
|
e = instr.(VariableAddressInstruction).getAst().(Expr).getFullyConverted()
or
@@ -1307,8 +1319,8 @@ pragma[noinline]
private predicate indirectParameterNodeHasArgumentIndexAndIndex(
IndirectParameterNode node, int argumentIndex, int indirectionIndex
) {
node.getArgumentIndex() = argumentIndex and
node.getIndirectionIndex() = indirectionIndex
node.hasInstructionAndIndirectionIndex(_, indirectionIndex) and
node.getArgumentIndex() = argumentIndex
}
/** A synthetic parameter to model the pointed-to object of a pointer parameter. */
@@ -1479,18 +1491,14 @@ VariableNode variableNode(Variable v) {
*/
Node uninitializedNode(LocalVariable v) { none() }
pragma[noinline]
predicate hasOperandAndIndex(IndirectOperand indirectOperand, Operand operand, int indirectionIndex) {
indirectOperand.getOperand() = operand and
indirectOperand.getIndirectionIndex() = indirectionIndex
indirectOperand.hasOperandAndIndirectionIndex(operand, indirectionIndex)
}
pragma[noinline]
predicate hasInstructionAndIndex(
IndirectInstruction indirectInstr, Instruction instr, int indirectionIndex
) {
indirectInstr.getInstruction() = instr and
indirectInstr.getIndirectionIndex() = indirectionIndex
indirectInstr.hasInstructionAndIndirectionIndex(instr, indirectionIndex)
}
cached
@@ -1656,8 +1664,7 @@ module ExprFlowCached {
private predicate isIndirectBaseOfArrayAccess(IndirectOperand n, Expr e) {
exists(LoadInstruction load, PointerArithmeticInstruction pai |
pai = load.getSourceAddress() and
pai.getLeftOperand() = n.getOperand() and
n.getIndirectionIndex() = 1 and
n.hasOperandAndIndirectionIndex(pai.getLeftOperand(), 1) and
e = load.getConvertedResultExpression()
)
}
@@ -1825,6 +1832,20 @@ class Content extends TContent {
predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
path = "" and sl = 0 and sc = 0 and el = 0 and ec = 0
}
/** Gets the indirection index of this `Content`. */
abstract int getIndirectionIndex();
/**
* INTERNAL: Do not use.
*
* Holds if a write to this `Content` implies that `c` is
* also cleared.
*
* For example, a write to a field `f` implies that any content of
* the form `*f` is also cleared.
*/
abstract predicate impliesClearOf(Content c);
}
/** A reference through a non-union instance field. */
@@ -1842,10 +1863,21 @@ class FieldContent extends Content, TFieldContent {
Field getField() { result = f }
/** Gets the indirection index of this `FieldContent`. */
pragma[inline]
int getIndirectionIndex() {
override int getIndirectionIndex() {
pragma[only_bind_into](result) = pragma[only_bind_out](indirectionIndex)
}
override predicate impliesClearOf(Content c) {
exists(FieldContent fc |
fc = c and
fc.getField() = f and
// If `this` is `f` then `c` is cleared if it's of the
// form `*f`, `**f`, etc.
fc.getIndirectionIndex() >= indirectionIndex
)
}
}
/** A reference through an instance field of a union. */
@@ -1870,9 +1902,21 @@ class UnionContent extends Content, TUnionContent {
/** Gets the indirection index of this `UnionContent`. */
pragma[inline]
int getIndirectionIndex() {
override int getIndirectionIndex() {
pragma[only_bind_into](result) = pragma[only_bind_out](indirectionIndex)
}
override predicate impliesClearOf(Content c) {
exists(UnionContent uc |
uc = c and
uc.getUnion() = u and
// If `this` is `u` then `c` is cleared if it's of the
// form `*u`, `**u`, etc. (and we ignore `bytes` because
// we know the entire union is overwritten because it's a
// union).
uc.getIndirectionIndex() >= indirectionIndex
)
}
}
/**

View File

@@ -13,7 +13,7 @@ class FieldFlowPropertyProvider extends IRPropertyProvider {
override string getOperandProperty(Operand operand, string key) {
exists(PostFieldUpdateNode pfun, Content content |
key = "store " + content.toString() and
operand = pfun.getPreUpdateNode().(IndirectOperand).getOperand() and
pfun.getPreUpdateNode().(IndirectOperand).hasOperandAndIndirectionIndex(operand, _) and
result =
strictconcat(string element, Node node |
storeStep(node, content, pfun) and
@@ -25,7 +25,7 @@ class FieldFlowPropertyProvider extends IRPropertyProvider {
or
exists(Node node2, Content content |
key = "read " + content.toString() and
operand = node2.(IndirectOperand).getOperand() and
node2.(IndirectOperand).hasOperandAndIndirectionIndex(operand, _) and
result =
strictconcat(string element, Node node1 |
readStep(node1, content, node2) and

View File

@@ -18,9 +18,12 @@ private string stars(int k) {
}
string starsForNode(Node node) {
result = stars(node.(IndirectInstruction).getIndirectionIndex())
or
result = stars(node.(IndirectOperand).getIndirectionIndex())
exists(int indirectionIndex |
node.(IndirectInstruction).hasInstructionAndIndirectionIndex(_, indirectionIndex) or
node.(IndirectOperand).hasOperandAndIndirectionIndex(_, indirectionIndex)
|
result = stars(indirectionIndex)
)
or
not node instanceof IndirectInstruction and
not node instanceof IndirectOperand and

View File

@@ -359,7 +359,6 @@ module ProductFlow {
Config::isSinkPair(node1.getNode(), node1.getState(), node2.getNode(), node2.getState())
}
pragma[assume_small_delta]
pragma[nomagic]
private predicate fwdReachableInterprocEntry(Flow1::PathNode node1, Flow2::PathNode node2) {
isSourcePair(node1, node2)
@@ -396,7 +395,6 @@ module ProductFlow {
fwdIsSuccessorExit(pragma[only_bind_into](mid1), pragma[only_bind_into](mid2), succ1, succ2)
}
pragma[assume_small_delta]
private predicate fwdIsSuccessor(
Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode succ1, Flow2::PathNode succ2
) {
@@ -406,7 +404,6 @@ module ProductFlow {
)
}
pragma[assume_small_delta]
pragma[nomagic]
private predicate revReachableInterprocEntry(Flow1::PathNode node1, Flow2::PathNode node2) {
fwdReachableInterprocEntry(node1, node2) and

View File

@@ -364,7 +364,25 @@ abstract private class OperandBasedUse extends UseImpl {
OperandBasedUse() { any() }
final override predicate hasIndexInBlock(IRBlock block, int index) {
operand.getUse() = block.getInstruction(index)
// See the comment in `ssa0`'s `OperandBasedUse` for an explanation of this
// predicate's implementation.
exists(BaseSourceVariableInstruction base | base = this.getBase() |
if base.getAst() = any(Cpp::PostfixCrementOperation c).getOperand()
then
exists(Operand op, int indirectionIndex, int indirection |
indirectionIndex = this.getIndirectionIndex() and
indirection = this.getIndirection() and
op =
min(Operand cand, int i |
isUse(_, cand, base, indirection, indirectionIndex) and
block.getInstruction(i) = cand.getUse()
|
cand order by i
) and
block.getInstruction(index) = op.getUse()
)
else operand.getUse() = block.getInstruction(index)
)
}
final Operand getOperand() { result = operand }

View File

@@ -117,6 +117,16 @@ private int countIndirections(Type t) {
else (
result = any(Indirection ind | ind.getType() = t).getNumberOfIndirections()
or
// If there is an indirection for the type, but we cannot count the number of indirections
// it means we couldn't reach a non-indirection type by stripping off indirections. This
// can occur if an iterator specifies itself as the value type. In this case we default to
// 1 indirection fore the type.
exists(Indirection ind |
ind.getType() = t and
not exists(ind.getNumberOfIndirections()) and
result = 1
)
or
not exists(Indirection ind | ind.getType() = t) and
result = 0
)
@@ -263,7 +273,7 @@ private module IteratorIndirections {
// Taint through `operator+=` and `operator-=` on iterators.
call.getStaticCallTarget() instanceof Iterator::IteratorAssignArithmeticOperator and
node2.(IndirectArgumentOutNode).getPreUpdateNode() = node1 and
node1.(IndirectOperand).getOperand() = call.getArgumentOperand(0) and
node1.(IndirectOperand).hasOperandAndIndirectionIndex(call.getArgumentOperand(0), _) and
node1.getType().getUnspecifiedType() = this
)
}
@@ -578,7 +588,6 @@ private module Cached {
)
}
pragma[assume_small_delta]
private predicate convertsIntoArgumentRev(Instruction instr) {
convertsIntoArgumentFwd(instr) and
(
@@ -796,7 +805,7 @@ private module Cached {
address.getDef() = instr and
isDereference(load, address) and
isUseImpl(address, _, indirectionIndex - 1) and
result = instr
result = load
)
}

View File

@@ -160,7 +160,7 @@ predicate modeledTaintStep(DataFlow::Node nodeIn, DataFlow::Node nodeOut) {
FunctionInput modelIn, FunctionOutput modelOut
|
indirectArgument = callInput(call, modelIn) and
indirectArgument.getAddressOperand() = nodeIn.asOperand() and
indirectArgument.hasAddressOperandAndIndirectionIndex(nodeIn.asOperand(), _) and
call.getStaticCallTarget() = func and
(
func.(DataFlowFunction).hasDataFlow(modelIn, modelOut)

View File

@@ -122,7 +122,46 @@ abstract private class OperandBasedUse extends UseImpl {
override string toString() { result = operand.toString() }
final override predicate hasIndexInBlock(IRBlock block, int index) {
operand.getUse() = block.getInstruction(index)
// Ideally, this would just be implemented as:
// ```
// operand.getUse() = block.getInstruction(index)
// ```
// but because the IR generated for a snippet such as
// ```
// int x = *p++;
// ```
// looks like
// ```
// r1(glval<int>) = VariableAddress[x] :
// r2(glval<int *>) = VariableAddress[p] :
// r3(int *) = Load[p] : &:r2, m1
// r4(int) = Constant[1] :
// r5(int *) = PointerAdd[4] : r3, r4
// m3(int *) = Store[p] : &:r2, r5
// r6(int *) = CopyValue : r3
// r7(int) = Load[?] : &:r6, ~m2
// m2(int) = Store[x] : &:r1, r7
// ```
// we need to ensure that the `r3` operand of the `CopyValue` instruction isn't seen as a fresh use
// of `p` that happens after the increment. So if the base instruction of this use comes from a
// post-fix crement operation we set the index of the SSA use that wraps the `r3` operand at the
// `CopyValue` instruction to be the same index as the `r3` operand at the `PointerAdd` instruction.
// This ensures that the SSA library doesn't create flow from the `PointerAdd` to `r6`.
exists(BaseSourceVariableInstruction base | base = this.getBase() |
if base.getAst() = any(Cpp::PostfixCrementOperation c).getOperand()
then
exists(Operand op |
op =
min(Operand cand, int i |
isUse(_, cand, base, _, _) and
block.getInstruction(i) = cand.getUse()
|
cand order by i
) and
block.getInstruction(index) = op.getUse()
)
else operand.getUse() = block.getInstruction(index)
)
}
final override Cpp::Location getLocation() { result = operand.getLocation() }

View File

@@ -176,7 +176,6 @@ private predicate binaryValueNumber0(
)
}
pragma[assume_small_delta]
private predicate binaryValueNumber(
BinaryInstruction instr, IRFunction irFunc, Opcode opcode, TValueNumber leftOperand,
TValueNumber rightOperand
@@ -202,7 +201,6 @@ private predicate pointerArithmeticValueNumber0(
)
}
pragma[assume_small_delta]
private predicate pointerArithmeticValueNumber(
PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, int elementSize,
TValueNumber leftOperand, TValueNumber rightOperand
@@ -249,7 +247,6 @@ private predicate loadTotalOverlapValueNumber0(
)
}
pragma[assume_small_delta]
private predicate loadTotalOverlapValueNumber(
LoadTotalOverlapInstruction instr, IRFunction irFunc, IRType type, TValueNumber memOperand,
TValueNumber operand

View File

@@ -176,7 +176,6 @@ private predicate binaryValueNumber0(
)
}
pragma[assume_small_delta]
private predicate binaryValueNumber(
BinaryInstruction instr, IRFunction irFunc, Opcode opcode, TValueNumber leftOperand,
TValueNumber rightOperand
@@ -202,7 +201,6 @@ private predicate pointerArithmeticValueNumber0(
)
}
pragma[assume_small_delta]
private predicate pointerArithmeticValueNumber(
PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, int elementSize,
TValueNumber leftOperand, TValueNumber rightOperand
@@ -249,7 +247,6 @@ private predicate loadTotalOverlapValueNumber0(
)
}
pragma[assume_small_delta]
private predicate loadTotalOverlapValueNumber(
LoadTotalOverlapInstruction instr, IRFunction irFunc, IRType type, TValueNumber memOperand,
TValueNumber operand

View File

@@ -176,7 +176,6 @@ private predicate binaryValueNumber0(
)
}
pragma[assume_small_delta]
private predicate binaryValueNumber(
BinaryInstruction instr, IRFunction irFunc, Opcode opcode, TValueNumber leftOperand,
TValueNumber rightOperand
@@ -202,7 +201,6 @@ private predicate pointerArithmeticValueNumber0(
)
}
pragma[assume_small_delta]
private predicate pointerArithmeticValueNumber(
PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, int elementSize,
TValueNumber leftOperand, TValueNumber rightOperand
@@ -249,7 +247,6 @@ private predicate loadTotalOverlapValueNumber0(
)
}
pragma[assume_small_delta]
private predicate loadTotalOverlapValueNumber(
LoadTotalOverlapInstruction instr, IRFunction irFunc, IRType type, TValueNumber memOperand,
TValueNumber operand

View File

@@ -108,7 +108,7 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, Sid
// these may do only a partial copy of the input buffer to the output
// buffer
exists(this.getParamSize()) and
input.isParameter(this.getParamSrc()) and
input.isParameterDeref(this.getParamSrc()) and
(
output.isParameterDeref(this.getParamDest()) or
output.isReturnValueDeref()

View File

@@ -70,6 +70,27 @@ predicate semBackEdge(SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionP
// Conservatively assume that every edge is a back edge if we don't have dominance information.
(
phi.getBasicBlock().bbDominates(edge.getOrigBlock()) or
irreducibleSccEdge(edge.getOrigBlock(), phi.getBasicBlock()) or
not edge.getOrigBlock().hasDominanceInformation()
)
}
/**
* Holds if the edge from b1 to b2 is part of a multiple-entry cycle in an irreducible control flow
* graph.
*
* An ireducible control flow graph is one where the usual dominance-based back edge detection does
* not work, because there is a cycle with multiple entry points, meaning there are
* mutually-reachable basic blocks where neither dominates the other. For such a graph, we first
* remove all detectable back-edges using the normal condition that the predecessor block is
* dominated by the successor block, then mark all edges in a cycle in the resulting graph as back
* edges.
*/
private predicate irreducibleSccEdge(SemBasicBlock b1, SemBasicBlock b2) {
trimmedEdge(b1, b2) and trimmedEdge+(b2, b1)
}
private predicate trimmedEdge(SemBasicBlock pred, SemBasicBlock succ) {
pred.getASuccessor() = succ and
not succ.bbDominates(pred)
}

View File

@@ -877,7 +877,6 @@ module RangeStage<
)
}
pragma[assume_small_delta]
pragma[nomagic]
private predicate boundedPhiRankStep(
SemSsaPhiNode phi, SemBound b, D::Delta delta, boolean upper, boolean fromBackEdge,

View File

@@ -135,18 +135,24 @@ module ParameterSinks {
}
}
predicate isUse(DataFlow::Node n, Expr e) {
isUse0(n, e)
or
exists(CallInstruction call, int i, InitializeParameterInstruction init |
n.asOperand().getDef().getUnconvertedResultExpression() = e and
init = ParameterSinks::getAnAlwaysDereferencedParameter() and
call.getArgumentOperand(i) = n.asOperand() and
init.hasIndex(i) and
init.getEnclosingFunction() = call.getStaticCallTarget()
)
module IsUse {
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplCommon
predicate isUse(DataFlow::Node n, Expr e) {
isUse0(n, e)
or
exists(CallInstruction call, InitializeParameterInstruction init |
n.asOperand().getDef().getUnconvertedResultExpression() = e and
pragma[only_bind_into](init) = ParameterSinks::getAnAlwaysDereferencedParameter() and
viableParamArg(call, DataFlow::instructionNode(init), n) and
pragma[only_bind_out](init.getEnclosingFunction()) =
pragma[only_bind_out](call.getStaticCallTarget())
)
}
}
import IsUse
/**
* `dealloc1` is a deallocation expression, `e` is an expression that dereferences a
* pointer, and the `(dealloc1, e)` pair should be excluded by the `FlowFromFree` library.

View File

@@ -5,7 +5,7 @@
* @kind path-problem
* @problem.severity error
* @security-severity 9.3
* @precision low
* @precision medium
* @id cpp/overrun-write
* @tags reliability
* security
@@ -233,7 +233,8 @@ module StringSizeConfig implements ProductFlow::StateConfigSig {
// we use `state2` to remember that there was an offset (in this case an offset of `1`) added
// to the size of the allocation. This state is then checked in `isSinkPair`.
exists(state1) and
hasSize(bufSource.asConvertedExpr(), sizeSource, state2)
hasSize(bufSource.asConvertedExpr(), sizeSource, state2) and
validState(sizeSource, state2)
}
predicate isSinkPair(

View File

@@ -45,13 +45,20 @@ Element friendlyLoc(Expr e) {
not e instanceof Access and not e instanceof Call and result = e
}
int getComparisonSizeAdjustment(Expr e) {
if e.getType().(IntegralType).isSigned() then result = 1 else result = 0
}
from Loop l, RelationalOperation rel, VariableAccess small, Expr large
where
small = rel.getLesserOperand() and
large = rel.getGreaterOperand() and
rel = l.getCondition().getAChild*() and
forall(Expr conv | conv = large.getConversion*() |
upperBound(conv).log2() > getComparisonSize(small) * 8
// We adjust the comparison size in the case of a signed integer type.
// This is to exclude the sign bit from the comparison that determines if the small type's size is sufficient to hold
// the value of the larger type determined with range analysis.
upperBound(conv).log2() > (getComparisonSize(small) * 8 - getComparisonSizeAdjustment(small))
) and
// Ignore cases where the smaller type is int or larger
// These are still bugs, but you should need a very large string or array to

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The `cpp/comparison-with-wider-type` query now correctly handles relational operations on signed operators. As a result the query may find more results.

View File

@@ -14,7 +14,7 @@ import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysi
import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExprSpecific
import semmle.code.cpp.ir.IR
import semmle.code.cpp.ir.dataflow.DataFlow
import FieldAddressToDerefFlow::PathGraph
import ArrayAddressToDerefFlow::PathGraph
pragma[nomagic]
Instruction getABoundIn(SemBound b, IRFunction func) {
@@ -78,28 +78,45 @@ predicate isInvalidPointerDerefSink2(DataFlow::Node sink, Instruction i, string
)
}
pragma[nomagic]
predicate arrayTypeHasSizes(ArrayType arr, int baseTypeSize, int arraySize) {
arr.getBaseType().getSize() = baseTypeSize and
arr.getArraySize() = arraySize
predicate arrayTypeCand(ArrayType arrayType) {
any(Variable v).getUnspecifiedType() = arrayType and
exists(arrayType.getByteSize())
}
predicate pointerArithOverflow0(
PointerArithmeticInstruction pai, Field f, int size, int bound, int delta
) {
not f.getNamespace() instanceof StdNamespace and
arrayTypeHasSizes(f.getUnspecifiedType(), pai.getElementSize(), size) and
semBounded(getSemanticExpr(pai.getRight()), any(SemZeroBound b), bound, true, _) and
delta = bound - size and
delta >= 0 and
size != 0 and
size != 1
bindingset[baseTypeSize]
pragma[inline_late]
predicate arrayTypeHasSizes(ArrayType arr, int baseTypeSize, int size) {
arrayTypeCand(arr) and
arr.getByteSize() / baseTypeSize = size
}
bindingset[pai]
pragma[inline_late]
predicate constantUpperBounded(PointerArithmeticInstruction pai, int delta) {
semBounded(getSemanticExpr(pai.getRight()), any(SemZeroBound b), delta, true, _)
}
bindingset[pai, size]
predicate pointerArithOverflow0Impl(PointerArithmeticInstruction pai, int size, int delta) {
exists(int bound |
constantUpperBounded(pai, bound) and
delta = bound - size and
delta >= 0 and
size != 0 and
size != 1
)
}
pragma[nomagic]
predicate pointerArithOverflow0(PointerArithmeticInstruction pai, int delta) {
exists(int size |
arrayTypeHasSizes(_, pai.getElementSize(), size) and
pointerArithOverflow0Impl(pai, size, delta)
)
}
module PointerArithmeticToDerefConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
pointerArithOverflow0(source.asInstruction(), _, _, _, _)
}
predicate isSource(DataFlow::Node source) { pointerArithOverflow0(source.asInstruction(), _) }
predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
@@ -110,25 +127,38 @@ module PointerArithmeticToDerefConfig implements DataFlow::ConfigSig {
module PointerArithmeticToDerefFlow = DataFlow::Global<PointerArithmeticToDerefConfig>;
predicate pointerArithOverflow(
PointerArithmeticInstruction pai, Field f, int size, int bound, int delta
) {
pointerArithOverflow0(pai, f, size, bound, delta) and
predicate pointerArithOverflow(PointerArithmeticInstruction pai, int delta) {
pointerArithOverflow0(pai, delta) and
PointerArithmeticToDerefFlow::flow(DataFlow::instructionNode(pai), _)
}
module FieldAddressToDerefConfig implements DataFlow::StateConfigSig {
bindingset[v]
predicate finalPointerArithOverflow(Variable v, PointerArithmeticInstruction pai, int delta) {
exists(int size |
arrayTypeHasSizes(pragma[only_bind_out](v.getUnspecifiedType()), pai.getElementSize(), size) and
pointerArithOverflow0Impl(pai, size, delta)
)
}
predicate isSourceImpl(DataFlow::Node source, Variable v) {
(
source.asInstruction().(FieldAddressInstruction).getField() = v
or
source.asInstruction().(VariableAddressInstruction).getAstVariable() = v
) and
arrayTypeCand(v.getUnspecifiedType())
}
module ArrayAddressToDerefConfig implements DataFlow::StateConfigSig {
newtype FlowState =
additional TArray(Field f) { pointerArithOverflow(_, f, _, _, _) } or
additional TArray() or
additional TOverflowArithmetic(PointerArithmeticInstruction pai) {
pointerArithOverflow(pai, _, _, _, _)
pointerArithOverflow(pai, _)
}
predicate isSource(DataFlow::Node source, FlowState state) {
exists(Field f |
source.asInstruction().(FieldAddressInstruction).getField() = f and
state = TArray(f)
)
isSourceImpl(source, _) and
state = TArray()
}
predicate isSink(DataFlow::Node sink, FlowState state) {
@@ -147,27 +177,27 @@ module FieldAddressToDerefConfig implements DataFlow::StateConfigSig {
predicate isAdditionalFlowStep(
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
) {
exists(PointerArithmeticInstruction pai, Field f |
state1 = TArray(f) and
exists(PointerArithmeticInstruction pai |
state1 = TArray() and
state2 = TOverflowArithmetic(pai) and
pai.getLeft() = node1.asInstruction() and
node2.asInstruction() = pai and
pointerArithOverflow(pai, f, _, _, _)
pointerArithOverflow(pai, _)
)
}
}
module FieldAddressToDerefFlow = DataFlow::GlobalWithState<FieldAddressToDerefConfig>;
module ArrayAddressToDerefFlow = DataFlow::GlobalWithState<ArrayAddressToDerefConfig>;
from
Field f, FieldAddressToDerefFlow::PathNode source, PointerArithmeticInstruction pai,
FieldAddressToDerefFlow::PathNode sink, Instruction deref, string operation, int delta
Variable v, ArrayAddressToDerefFlow::PathNode source, PointerArithmeticInstruction pai,
ArrayAddressToDerefFlow::PathNode sink, Instruction deref, string operation, int delta
where
FieldAddressToDerefFlow::flowPath(source, sink) and
ArrayAddressToDerefFlow::flowPath(pragma[only_bind_into](source), pragma[only_bind_into](sink)) and
isInvalidPointerDerefSink2(sink.getNode(), deref, operation) and
source.getState() = FieldAddressToDerefConfig::TArray(f) and
sink.getState() = FieldAddressToDerefConfig::TOverflowArithmetic(pai) and
pointerArithOverflow(pai, f, _, _, delta)
pragma[only_bind_out](sink.getState()) = ArrayAddressToDerefConfig::TOverflowArithmetic(pai) and
isSourceImpl(source.getNode(), v) and
finalPointerArithOverflow(v, pai, delta)
select pai, source, sink,
"This pointer arithmetic may have an off-by-" + (delta + 1) +
" error allowing it to overrun $@ at this $@.", f, f.getName(), deref, operation
" error allowing it to overrun $@ at this $@.", v, v.getName(), deref, operation

View File

@@ -19,6 +19,8 @@ import cpp
import semmle.code.cpp.ir.dataflow.internal.ProductFlow
import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysis
import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExprSpecific
import semmle.code.cpp.ir.ValueNumbering
import semmle.code.cpp.controlflow.IRGuards
import semmle.code.cpp.ir.IR
import codeql.util.Unit
@@ -67,6 +69,86 @@ predicate hasSize(HeuristicAllocationExpr alloc, DataFlow::Node n, int state) {
)
}
/**
* A module that encapsulates a barrier guard to remove false positives from flow like:
* ```cpp
* char *p = new char[size];
* // ...
* unsigned n = size;
* // ...
* if(n < size) {
* use(*p[n]);
* }
* ```
* In this case, the sink pair identified by the product flow library (without any additional barriers)
* would be `(p, n)` (where `n` is the `n` in `p[n]`), because there exists a pointer-arithmetic
* instruction `pai` such that:
* 1. The left-hand of `pai` flows from the allocation, and
* 2. The right-hand of `pai` is non-strictly upper bounded by `n` (where `n` is the `n` in `p[n]`)
* but because there's a strict comparison that compares `n` against the size of the allocation this
* snippet is fine.
*/
module Barrier2 {
private class FlowState2 = AllocToInvalidPointerConfig::FlowState2;
private module BarrierConfig2 implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
// The sources is the same as in the sources for the second
// projection in the `AllocToInvalidPointerConfig` module.
hasSize(_, source, _)
}
additional predicate isSink(
DataFlow::Node left, DataFlow::Node right, IRGuardCondition g, FlowState2 state,
boolean testIsTrue
) {
// The sink is any "large" side of a relational comparison.
g.comparesLt(left.asOperand(), right.asOperand(), state, true, testIsTrue)
}
predicate isSink(DataFlow::Node sink) { isSink(_, sink, _, _, _) }
}
private import DataFlow::Global<BarrierConfig2>
private FlowState2 getAFlowStateForNode(DataFlow::Node node) {
exists(DataFlow::Node source |
flow(source, node) and
hasSize(_, source, result)
)
}
private predicate operandGuardChecks(
IRGuardCondition g, Operand left, Operand right, FlowState2 state, boolean edge
) {
exists(DataFlow::Node nLeft, DataFlow::Node nRight, FlowState2 state0 |
nRight.asOperand() = right and
nLeft.asOperand() = left and
BarrierConfig2::isSink(nLeft, nRight, g, state0, edge) and
state = getAFlowStateForNode(nRight) and
state0 <= state
)
}
Instruction getABarrierInstruction(FlowState2 state) {
exists(IRGuardCondition g, ValueNumber value, Operand use, boolean edge |
use = value.getAUse() and
operandGuardChecks(pragma[only_bind_into](g), pragma[only_bind_into](use), _,
pragma[only_bind_into](state), pragma[only_bind_into](edge)) and
result = value.getAnInstruction() and
g.controls(result.getBlock(), edge)
)
}
DataFlow::Node getABarrierNode(FlowState2 state) {
result.asOperand() = getABarrierInstruction(state).getAUse()
}
IRBlock getABarrierBlock(FlowState2 state) {
result.getAnInstruction() = getABarrierInstruction(state)
}
}
/**
* A product-flow configuration for flow from an (allocation, size) pair to a
* pointer-arithmetic operation that is non-strictly upper-bounded by `allocation + size`.
@@ -111,15 +193,14 @@ module AllocToInvalidPointerConfig implements ProductFlow::StateConfigSig {
exists(state1) and
// We check that the delta computed by the range analysis matches the
// state value that we set in `isSourcePair`.
exists(int delta |
isSinkImpl(_, sink1, sink2, delta) and
state2 = delta
)
isSinkImpl(_, sink1, sink2, state2)
}
predicate isBarrier1(DataFlow::Node node, FlowState1 state) { none() }
predicate isBarrier2(DataFlow::Node node, FlowState2 state) { none() }
predicate isBarrier2(DataFlow::Node node, FlowState2 state) {
node = Barrier2::getABarrierNode(state)
}
predicate isBarrierIn1(DataFlow::Node node) { isSourcePair(node, _, _, _) }
@@ -160,13 +241,40 @@ pragma[nomagic]
predicate pointerAddInstructionHasBounds(
PointerAddInstruction pai, DataFlow::Node sink1, DataFlow::Node sink2, int delta
) {
exists(Instruction right |
InterestingPointerAddInstruction::isInteresting(pragma[only_bind_into](pai)) and
exists(Instruction right, Instruction instr2 |
pai.getRight() = right and
pai.getLeft() = sink1.asInstruction() and
bounded1(right, sink2.asInstruction(), delta)
instr2 = sink2.asInstruction() and
bounded1(right, instr2, delta) and
not right = Barrier2::getABarrierInstruction(delta) and
not instr2 = Barrier2::getABarrierInstruction(delta)
)
}
module InterestingPointerAddInstruction {
private module PointerAddInstructionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
// The sources is the same as in the sources for the second
// projection in the `AllocToInvalidPointerConfig` module.
hasSize(source.asConvertedExpr(), _, _)
}
predicate isSink(DataFlow::Node sink) {
sink.asInstruction() = any(PointerAddInstruction pai).getLeft()
}
}
private import DataFlow::Global<PointerAddInstructionConfig>
predicate isInteresting(PointerAddInstruction pai) {
exists(DataFlow::Node n |
n.asInstruction() = pai.getLeft() and
flowTo(n)
)
}
}
/**
* Holds if `pai` is non-strictly upper bounded by `sink2 + delta` and `sink1` is the
* left operand of the pointer-arithmetic operation.
@@ -204,11 +312,13 @@ Instruction getASuccessor(Instruction instr) {
*/
pragma[inline]
predicate isInvalidPointerDerefSink(DataFlow::Node sink, Instruction i, string operation, int delta) {
exists(AddressOperand addr, Instruction s |
exists(AddressOperand addr, Instruction s, IRBlock b |
s = sink.asInstruction() and
bounded1(addr.getDef(), s, delta) and
boundedImpl(addr.getDef(), s, delta) and
delta >= 0 and
i.getAnOperand() = addr
i.getAnOperand() = addr and
b = i.getBlock() and
not b = InvalidPointerToDerefBarrier::getABarrierBlock(delta)
|
i instanceof StoreInstruction and
operation = "write"
@@ -218,6 +328,60 @@ predicate isInvalidPointerDerefSink(DataFlow::Node sink, Instruction i, string o
)
}
module InvalidPointerToDerefBarrier {
private module BarrierConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
// The sources is the same as in the sources for `InvalidPointerToDerefConfig`.
invalidPointerToDerefSource(_, source, _)
}
additional predicate isSink(
DataFlow::Node left, DataFlow::Node right, IRGuardCondition g, int state, boolean testIsTrue
) {
// The sink is any "large" side of a relational comparison.
g.comparesLt(left.asOperand(), right.asOperand(), state, true, testIsTrue)
}
predicate isSink(DataFlow::Node sink) { isSink(_, sink, _, _, _) }
}
private import DataFlow::Global<BarrierConfig>
private int getInvalidPointerToDerefSourceDelta(DataFlow::Node node) {
exists(DataFlow::Node source |
flow(source, node) and
invalidPointerToDerefSource(_, source, result)
)
}
private predicate operandGuardChecks(
IRGuardCondition g, Operand left, Operand right, int state, boolean edge
) {
exists(DataFlow::Node nLeft, DataFlow::Node nRight, int state0 |
nRight.asOperand() = right and
nLeft.asOperand() = left and
BarrierConfig::isSink(nLeft, nRight, g, state0, edge) and
state = getInvalidPointerToDerefSourceDelta(nRight) and
state0 <= state
)
}
Instruction getABarrierInstruction(int state) {
exists(IRGuardCondition g, ValueNumber value, Operand use, boolean edge |
use = value.getAUse() and
operandGuardChecks(pragma[only_bind_into](g), pragma[only_bind_into](use), _, state,
pragma[only_bind_into](edge)) and
result = value.getAnInstruction() and
g.controls(result.getBlock(), edge)
)
}
DataFlow::Node getABarrierNode() { result.asOperand() = getABarrierInstruction(_).getAUse() }
pragma[nomagic]
IRBlock getABarrierBlock(int state) { result.getAnInstruction() = getABarrierInstruction(state) }
}
/**
* A configuration to track flow from a pointer-arithmetic operation found
* by `AllocToInvalidPointerConfig` to a dereference of the pointer.
@@ -230,6 +394,8 @@ module InvalidPointerToDerefConfig implements DataFlow::ConfigSig {
predicate isBarrier(DataFlow::Node node) {
node = any(DataFlow::SsaPhiNode phi | not phi.isPhiRead()).getAnInput(true)
or
node = InvalidPointerToDerefBarrier::getABarrierNode()
}
}
@@ -246,12 +412,21 @@ module InvalidPointerToDerefFlow = DataFlow::Global<InvalidPointerToDerefConfig>
predicate invalidPointerToDerefSource(
PointerArithmeticInstruction pai, DataFlow::Node source, int delta
) {
exists(AllocToInvalidPointerFlow::PathNode1 p, DataFlow::Node sink1 |
pragma[only_bind_out](p.getNode()) = sink1 and
AllocToInvalidPointerFlow::flowPath(_, _, pragma[only_bind_into](p), _) and
isSinkImpl(pai, sink1, _, _) and
exists(
AllocToInvalidPointerFlow::PathNode1 p1, AllocToInvalidPointerFlow::PathNode2 p2,
DataFlow::Node sink1, DataFlow::Node sink2, int delta0
|
pragma[only_bind_out](p1.getNode()) = sink1 and
pragma[only_bind_out](p2.getNode()) = sink2 and
AllocToInvalidPointerFlow::flowPath(_, _, pragma[only_bind_into](p1), pragma[only_bind_into](p2)) and
// Note that `delta` is not necessarily equal to `delta0`:
// `delta0` is the constant offset added to the size of the allocation, and
// delta is the constant difference between the pointer-arithmetic instruction
// and the instruction computing the address for which we will search for a dereference.
isSinkImpl(pai, sink1, sink2, delta0) and
bounded2(source.asInstruction(), pai, delta) and
delta >= 0
delta >= 0 and
not source.getBasicBlock() = Barrier2::getABarrierBlock(delta0)
)
}
@@ -265,7 +440,7 @@ newtype TMergedPathNode =
// pointer, but we want to raise an alert at the dereference.
TPathNodeSink(Instruction i) {
exists(DataFlow::Node n |
InvalidPointerToDerefFlow::flowTo(n) and
InvalidPointerToDerefFlow::flowTo(pragma[only_bind_into](n)) and
isInvalidPointerDerefSink(n, i, _, _) and
i = getASuccessor(n.asInstruction())
)

View File

@@ -4,8 +4,9 @@ edges
| test.cpp:19:9:19:16 | mk_array indirection [p] | test.cpp:28:19:28:26 | call to mk_array [p] |
| test.cpp:19:9:19:16 | mk_array indirection [p] | test.cpp:50:18:50:25 | call to mk_array [p] |
| test.cpp:21:5:21:24 | ... = ... | test.cpp:21:9:21:9 | arr indirection [post update] [p] |
| test.cpp:21:9:21:9 | arr indirection [post update] [p] | test.cpp:19:9:19:16 | mk_array indirection [p] |
| test.cpp:21:9:21:9 | arr indirection [post update] [p] | test.cpp:22:5:22:7 | arr indirection [p] |
| test.cpp:21:13:21:18 | call to malloc | test.cpp:21:5:21:24 | ... = ... |
| test.cpp:22:5:22:7 | arr indirection [p] | test.cpp:19:9:19:16 | mk_array indirection [p] |
| test.cpp:28:19:28:26 | call to mk_array [p] | test.cpp:31:9:31:11 | arr indirection [p] |
| test.cpp:28:19:28:26 | call to mk_array [p] | test.cpp:35:9:35:11 | arr indirection [p] |
| test.cpp:31:9:31:11 | arr indirection [p] | test.cpp:31:13:31:13 | p indirection |
@@ -20,9 +21,10 @@ edges
| test.cpp:45:13:45:13 | p indirection | test.cpp:45:13:45:13 | p |
| test.cpp:50:18:50:25 | call to mk_array [p] | test.cpp:39:27:39:29 | arr [p] |
| test.cpp:55:5:55:24 | ... = ... | test.cpp:55:9:55:9 | arr indirection [post update] [p] |
| test.cpp:55:9:55:9 | arr indirection [post update] [p] | test.cpp:59:9:59:11 | arr indirection [p] |
| test.cpp:55:9:55:9 | arr indirection [post update] [p] | test.cpp:63:9:63:11 | arr indirection [p] |
| test.cpp:55:9:55:9 | arr indirection [post update] [p] | test.cpp:56:5:56:7 | arr indirection [p] |
| test.cpp:55:13:55:18 | call to malloc | test.cpp:55:5:55:24 | ... = ... |
| test.cpp:56:5:56:7 | arr indirection [p] | test.cpp:59:9:59:11 | arr indirection [p] |
| test.cpp:56:5:56:7 | arr indirection [p] | test.cpp:63:9:63:11 | arr indirection [p] |
| test.cpp:59:9:59:11 | arr indirection [p] | test.cpp:59:13:59:13 | p indirection |
| test.cpp:59:13:59:13 | p indirection | test.cpp:59:13:59:13 | p |
| test.cpp:63:9:63:11 | arr indirection [p] | test.cpp:63:13:63:13 | p indirection |
@@ -30,8 +32,9 @@ edges
| test.cpp:67:10:67:19 | mk_array_p indirection [p] | test.cpp:76:20:76:29 | call to mk_array_p indirection [p] |
| test.cpp:67:10:67:19 | mk_array_p indirection [p] | test.cpp:98:18:98:27 | call to mk_array_p indirection [p] |
| test.cpp:69:5:69:25 | ... = ... | test.cpp:69:10:69:10 | arr indirection [post update] [p] |
| test.cpp:69:10:69:10 | arr indirection [post update] [p] | test.cpp:67:10:67:19 | mk_array_p indirection [p] |
| test.cpp:69:10:69:10 | arr indirection [post update] [p] | test.cpp:70:5:70:7 | arr indirection [p] |
| test.cpp:69:14:69:19 | call to malloc | test.cpp:69:5:69:25 | ... = ... |
| test.cpp:70:5:70:7 | arr indirection [p] | test.cpp:67:10:67:19 | mk_array_p indirection [p] |
| test.cpp:76:20:76:29 | call to mk_array_p indirection [p] | test.cpp:79:9:79:11 | arr indirection [p] |
| test.cpp:76:20:76:29 | call to mk_array_p indirection [p] | test.cpp:83:9:83:11 | arr indirection [p] |
| test.cpp:79:9:79:11 | arr indirection [p] | test.cpp:79:14:79:14 | p indirection |
@@ -53,6 +56,7 @@ nodes
| test.cpp:21:5:21:24 | ... = ... | semmle.label | ... = ... |
| test.cpp:21:9:21:9 | arr indirection [post update] [p] | semmle.label | arr indirection [post update] [p] |
| test.cpp:21:13:21:18 | call to malloc | semmle.label | call to malloc |
| test.cpp:22:5:22:7 | arr indirection [p] | semmle.label | arr indirection [p] |
| test.cpp:28:19:28:26 | call to mk_array [p] | semmle.label | call to mk_array [p] |
| test.cpp:31:9:31:11 | arr indirection [p] | semmle.label | arr indirection [p] |
| test.cpp:31:13:31:13 | p | semmle.label | p |
@@ -71,6 +75,7 @@ nodes
| test.cpp:55:5:55:24 | ... = ... | semmle.label | ... = ... |
| test.cpp:55:9:55:9 | arr indirection [post update] [p] | semmle.label | arr indirection [post update] [p] |
| test.cpp:55:13:55:18 | call to malloc | semmle.label | call to malloc |
| test.cpp:56:5:56:7 | arr indirection [p] | semmle.label | arr indirection [p] |
| test.cpp:59:9:59:11 | arr indirection [p] | semmle.label | arr indirection [p] |
| test.cpp:59:13:59:13 | p | semmle.label | p |
| test.cpp:59:13:59:13 | p indirection | semmle.label | p indirection |
@@ -81,6 +86,7 @@ nodes
| test.cpp:69:5:69:25 | ... = ... | semmle.label | ... = ... |
| test.cpp:69:10:69:10 | arr indirection [post update] [p] | semmle.label | arr indirection [post update] [p] |
| test.cpp:69:14:69:19 | call to malloc | semmle.label | call to malloc |
| test.cpp:70:5:70:7 | arr indirection [p] | semmle.label | arr indirection [p] |
| test.cpp:76:20:76:29 | call to mk_array_p indirection [p] | semmle.label | call to mk_array_p indirection [p] |
| test.cpp:79:9:79:11 | arr indirection [p] | semmle.label | arr indirection [p] |
| test.cpp:79:14:79:14 | p | semmle.label | p |

View File

@@ -1,38 +1,136 @@
edges
| test.cpp:34:10:34:12 | buf | test.cpp:34:5:34:24 | access to array |
| test.cpp:35:10:35:12 | buf | test.cpp:35:5:35:22 | access to array |
| test.cpp:36:10:36:12 | buf | test.cpp:36:5:36:24 | access to array |
| test.cpp:39:14:39:16 | buf | test.cpp:39:9:39:19 | access to array |
| test.cpp:43:14:43:16 | buf | test.cpp:43:9:43:19 | access to array |
| test.cpp:48:10:48:12 | buf | test.cpp:48:5:48:24 | access to array |
| test.cpp:49:10:49:12 | buf | test.cpp:49:5:49:22 | access to array |
| test.cpp:50:10:50:12 | buf | test.cpp:50:5:50:24 | access to array |
| test.cpp:53:14:53:16 | buf | test.cpp:53:9:53:19 | access to array |
| test.cpp:57:14:57:16 | buf | test.cpp:57:9:57:19 | access to array |
| test.cpp:61:14:61:16 | buf | test.cpp:61:9:61:19 | access to array |
| test.cpp:70:33:70:33 | p | test.cpp:71:5:71:17 | access to array |
| test.cpp:70:33:70:33 | p | test.cpp:72:5:72:15 | access to array |
| test.cpp:76:26:76:46 | & ... | test.cpp:66:32:66:32 | p |
| test.cpp:76:32:76:34 | buf | test.cpp:76:26:76:46 | & ... |
| test.cpp:77:26:77:44 | & ... | test.cpp:66:32:66:32 | p |
| test.cpp:77:32:77:34 | buf | test.cpp:77:26:77:44 | & ... |
| test.cpp:79:27:79:34 | buf | test.cpp:70:33:70:33 | p |
| test.cpp:79:32:79:34 | buf | test.cpp:79:27:79:34 | buf |
| test.cpp:85:34:85:36 | buf | test.cpp:87:5:87:31 | access to array |
| test.cpp:85:34:85:36 | buf | test.cpp:88:5:88:27 | access to array |
| test.cpp:96:13:96:15 | arr | test.cpp:96:13:96:18 | access to array |
| test.cpp:111:17:111:19 | arr | test.cpp:111:17:111:22 | access to array |
| test.cpp:111:17:111:19 | arr | test.cpp:115:35:115:40 | access to array |
| test.cpp:111:17:111:19 | arr | test.cpp:119:17:119:22 | access to array |
| test.cpp:115:35:115:37 | arr | test.cpp:111:17:111:22 | access to array |
| test.cpp:115:35:115:37 | arr | test.cpp:115:35:115:40 | access to array |
| test.cpp:115:35:115:37 | arr | test.cpp:119:17:119:22 | access to array |
| test.cpp:119:17:119:19 | arr | test.cpp:111:17:111:22 | access to array |
| test.cpp:119:17:119:19 | arr | test.cpp:115:35:115:40 | access to array |
| test.cpp:119:17:119:19 | arr | test.cpp:119:17:119:22 | access to array |
| test.cpp:128:9:128:11 | arr | test.cpp:128:9:128:14 | access to array |
| test.cpp:134:25:134:27 | arr | test.cpp:136:9:136:16 | ... += ... |
| test.cpp:136:9:136:16 | ... += ... | test.cpp:138:13:138:15 | arr |
| test.cpp:143:18:143:21 | asdf | test.cpp:134:25:134:27 | arr |
| test.cpp:143:18:143:21 | asdf | test.cpp:143:18:143:21 | asdf |
| test.cpp:146:26:146:26 | p indirection | test.cpp:148:6:148:9 | * ... |
| test.cpp:156:12:156:14 | buf | test.cpp:156:12:156:18 | ... + ... |
| test.cpp:156:12:156:18 | ... + ... | test.cpp:158:17:158:18 | & ... indirection |
| test.cpp:158:17:158:18 | & ... indirection | test.cpp:146:26:146:26 | p indirection |
| test.cpp:218:23:218:28 | buffer | test.cpp:220:5:220:11 | access to array |
| test.cpp:218:23:218:28 | buffer | test.cpp:221:5:221:11 | access to array |
| test.cpp:229:25:229:29 | array | test.cpp:231:5:231:10 | access to array |
| test.cpp:229:25:229:29 | array | test.cpp:232:5:232:10 | access to array |
| test.cpp:245:30:245:30 | p | test.cpp:261:27:261:30 | access to array |
| test.cpp:245:30:245:30 | p | test.cpp:261:27:261:30 | access to array |
| test.cpp:274:14:274:20 | buffer3 | test.cpp:245:30:245:30 | p |
| test.cpp:274:14:274:20 | buffer3 | test.cpp:274:14:274:20 | buffer3 |
| test.cpp:277:35:277:35 | p | test.cpp:278:14:278:14 | p |
| test.cpp:278:14:278:14 | p | test.cpp:245:30:245:30 | p |
| test.cpp:283:19:283:25 | buffer1 | test.cpp:277:35:277:35 | p |
| test.cpp:283:19:283:25 | buffer1 | test.cpp:283:19:283:25 | buffer1 |
| test.cpp:286:19:286:25 | buffer2 | test.cpp:277:35:277:35 | p |
| test.cpp:286:19:286:25 | buffer2 | test.cpp:286:19:286:25 | buffer2 |
| test.cpp:289:19:289:25 | buffer3 | test.cpp:277:35:277:35 | p |
| test.cpp:289:19:289:25 | buffer3 | test.cpp:289:19:289:25 | buffer3 |
nodes
| test.cpp:34:5:34:24 | access to array | semmle.label | access to array |
| test.cpp:34:10:34:12 | buf | semmle.label | buf |
| test.cpp:35:5:35:22 | access to array | semmle.label | access to array |
| test.cpp:35:10:35:12 | buf | semmle.label | buf |
| test.cpp:36:5:36:24 | access to array | semmle.label | access to array |
| test.cpp:36:10:36:12 | buf | semmle.label | buf |
| test.cpp:39:9:39:19 | access to array | semmle.label | access to array |
| test.cpp:39:14:39:16 | buf | semmle.label | buf |
| test.cpp:43:9:43:19 | access to array | semmle.label | access to array |
| test.cpp:43:14:43:16 | buf | semmle.label | buf |
| test.cpp:48:5:48:24 | access to array | semmle.label | access to array |
| test.cpp:48:10:48:12 | buf | semmle.label | buf |
| test.cpp:49:5:49:22 | access to array | semmle.label | access to array |
| test.cpp:49:10:49:12 | buf | semmle.label | buf |
| test.cpp:50:5:50:24 | access to array | semmle.label | access to array |
| test.cpp:50:10:50:12 | buf | semmle.label | buf |
| test.cpp:53:9:53:19 | access to array | semmle.label | access to array |
| test.cpp:53:14:53:16 | buf | semmle.label | buf |
| test.cpp:57:9:57:19 | access to array | semmle.label | access to array |
| test.cpp:57:14:57:16 | buf | semmle.label | buf |
| test.cpp:61:9:61:19 | access to array | semmle.label | access to array |
| test.cpp:61:14:61:16 | buf | semmle.label | buf |
| test.cpp:66:32:66:32 | p | semmle.label | p |
| test.cpp:66:32:66:32 | p | semmle.label | p |
| test.cpp:70:33:70:33 | p | semmle.label | p |
| test.cpp:71:5:71:17 | access to array | semmle.label | access to array |
| test.cpp:72:5:72:15 | access to array | semmle.label | access to array |
| test.cpp:76:26:76:46 | & ... | semmle.label | & ... |
| test.cpp:76:32:76:34 | buf | semmle.label | buf |
| test.cpp:77:26:77:44 | & ... | semmle.label | & ... |
| test.cpp:77:32:77:34 | buf | semmle.label | buf |
| test.cpp:79:27:79:34 | buf | semmle.label | buf |
| test.cpp:79:32:79:34 | buf | semmle.label | buf |
| test.cpp:85:34:85:36 | buf | semmle.label | buf |
| test.cpp:87:5:87:31 | access to array | semmle.label | access to array |
| test.cpp:88:5:88:27 | access to array | semmle.label | access to array |
| test.cpp:96:13:96:15 | arr | semmle.label | arr |
| test.cpp:96:13:96:18 | access to array | semmle.label | access to array |
| test.cpp:111:17:111:19 | arr | semmle.label | arr |
| test.cpp:111:17:111:22 | access to array | semmle.label | access to array |
| test.cpp:115:35:115:37 | arr | semmle.label | arr |
| test.cpp:115:35:115:40 | access to array | semmle.label | access to array |
| test.cpp:119:17:119:19 | arr | semmle.label | arr |
| test.cpp:119:17:119:22 | access to array | semmle.label | access to array |
| test.cpp:128:9:128:11 | arr | semmle.label | arr |
| test.cpp:128:9:128:14 | access to array | semmle.label | access to array |
| test.cpp:134:25:134:27 | arr | semmle.label | arr |
| test.cpp:136:9:136:16 | ... += ... | semmle.label | ... += ... |
| test.cpp:138:13:138:15 | arr | semmle.label | arr |
| test.cpp:143:18:143:21 | asdf | semmle.label | asdf |
| test.cpp:143:18:143:21 | asdf | semmle.label | asdf |
| test.cpp:146:26:146:26 | p indirection | semmle.label | p indirection |
| test.cpp:148:6:148:9 | * ... | semmle.label | * ... |
| test.cpp:156:12:156:14 | buf | semmle.label | buf |
| test.cpp:156:12:156:18 | ... + ... | semmle.label | ... + ... |
| test.cpp:158:17:158:18 | & ... indirection | semmle.label | & ... indirection |
| test.cpp:218:23:218:28 | buffer | semmle.label | buffer |
| test.cpp:220:5:220:11 | access to array | semmle.label | access to array |
| test.cpp:221:5:221:11 | access to array | semmle.label | access to array |
| test.cpp:229:25:229:29 | array | semmle.label | array |
| test.cpp:231:5:231:10 | access to array | semmle.label | access to array |
| test.cpp:232:5:232:10 | access to array | semmle.label | access to array |
| test.cpp:245:30:245:30 | p | semmle.label | p |
| test.cpp:245:30:245:30 | p | semmle.label | p |
| test.cpp:261:27:261:30 | access to array | semmle.label | access to array |
| test.cpp:274:14:274:20 | buffer3 | semmle.label | buffer3 |
| test.cpp:274:14:274:20 | buffer3 | semmle.label | buffer3 |
| test.cpp:277:35:277:35 | p | semmle.label | p |
| test.cpp:278:14:278:14 | p | semmle.label | p |
| test.cpp:283:19:283:25 | buffer1 | semmle.label | buffer1 |
| test.cpp:283:19:283:25 | buffer1 | semmle.label | buffer1 |
| test.cpp:286:19:286:25 | buffer2 | semmle.label | buffer2 |
| test.cpp:286:19:286:25 | buffer2 | semmle.label | buffer2 |
| test.cpp:289:19:289:25 | buffer3 | semmle.label | buffer3 |
| test.cpp:289:19:289:25 | buffer3 | semmle.label | buffer3 |
subpaths
#select
| test.cpp:35:5:35:22 | PointerAdd: access to array | test.cpp:35:10:35:12 | buf | test.cpp:35:5:35:22 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:15:9:15:11 | buf | buf | test.cpp:35:5:35:26 | Store: ... = ... | write |
@@ -44,3 +142,10 @@ subpaths
| test.cpp:61:9:61:19 | PointerAdd: access to array | test.cpp:61:14:61:16 | buf | test.cpp:61:9:61:19 | access to array | This pointer arithmetic may have an off-by-2 error allowing it to overrun $@ at this $@. | test.cpp:19:9:19:11 | buf | buf | test.cpp:61:9:61:23 | Store: ... = ... | write |
| test.cpp:72:5:72:15 | PointerAdd: access to array | test.cpp:79:32:79:34 | buf | test.cpp:72:5:72:15 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:15:9:15:11 | buf | buf | test.cpp:72:5:72:19 | Store: ... = ... | write |
| test.cpp:77:27:77:44 | PointerAdd: access to array | test.cpp:77:32:77:34 | buf | test.cpp:66:32:66:32 | p | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:15:9:15:11 | buf | buf | test.cpp:67:5:67:10 | Store: ... = ... | write |
| test.cpp:88:5:88:27 | PointerAdd: access to array | test.cpp:85:34:85:36 | buf | test.cpp:88:5:88:27 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:15:9:15:11 | buf | buf | test.cpp:88:5:88:31 | Store: ... = ... | write |
| test.cpp:128:9:128:14 | PointerAdd: access to array | test.cpp:128:9:128:11 | arr | test.cpp:128:9:128:14 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:125:11:125:13 | arr | arr | test.cpp:128:9:128:18 | Store: ... = ... | write |
| test.cpp:136:9:136:16 | PointerAdd: ... += ... | test.cpp:143:18:143:21 | asdf | test.cpp:138:13:138:15 | arr | This pointer arithmetic may have an off-by-2 error allowing it to overrun $@ at this $@. | test.cpp:142:10:142:13 | asdf | asdf | test.cpp:138:12:138:15 | Load: * ... | read |
| test.cpp:156:12:156:18 | PointerAdd: ... + ... | test.cpp:156:12:156:14 | buf | test.cpp:148:6:148:9 | * ... | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:154:7:154:9 | buf | buf | test.cpp:147:3:147:13 | Store: ... = ... | write |
| test.cpp:221:5:221:11 | PointerAdd: access to array | test.cpp:218:23:218:28 | buffer | test.cpp:221:5:221:11 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:217:19:217:24 | buffer | buffer | test.cpp:221:5:221:15 | Store: ... = ... | write |
| test.cpp:232:5:232:10 | PointerAdd: access to array | test.cpp:229:25:229:29 | array | test.cpp:232:5:232:10 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:228:10:228:14 | array | array | test.cpp:232:5:232:19 | Store: ... = ... | write |
| test.cpp:261:27:261:30 | PointerAdd: access to array | test.cpp:286:19:286:25 | buffer2 | test.cpp:261:27:261:30 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:285:19:285:25 | buffer2 | buffer2 | test.cpp:261:27:261:30 | Load: access to array | read |

View File

@@ -85,7 +85,7 @@ void testCharIndex(BigArray *arr) {
char *charBuf = (char*) arr->buf;
charBuf[MAX_SIZE_BYTES - 1] = 0; // GOOD
charBuf[MAX_SIZE_BYTES] = 0; // BAD [FALSE NEGATIVE]
charBuf[MAX_SIZE_BYTES] = 0; // BAD
}
void testEqRefinement() {
@@ -120,3 +120,171 @@ void testEqRefinement2() {
}
}
}
void testStackAllocated() {
char *arr[MAX_SIZE];
for(int i = 0; i <= MAX_SIZE; i++) {
arr[i] = 0; // BAD
}
}
int strncmp(const char*, const char*, int);
char testStrncmp2(char *arr) {
if(strncmp(arr, "<test>", 6) == 0) {
arr += 6;
}
return *arr; // GOOD [FALSE POSITIVE]
}
void testStrncmp1() {
char asdf[5];
testStrncmp2(asdf);
}
void countdownBuf1(int **p) {
*--(*p) = 1; // GOOD [FALSE POSITIVE]
*--(*p) = 2; // GOOD
*--(*p) = 3; // GOOD
*--(*p) = 4; // GOOD
}
void countdownBuf2() {
int buf[4];
int *x = buf + 4;
countdownBuf1(&x);
}
int access(int *p) {
return p[0];
}
// unrolled loop style seen in crypto code.
int countdownLength1(int *p, int len) {
while(len > 0) {
access(p);
p[1] = 1;
p[2] = 2;
p[3] = 3;
p[4] = 4;
p[5] = 5;
p[6] = 6; // BAD [FALSE NEGATIVE]
p[7] = 7; // BAD [FALSE NEGATIVE]
p += 8;
len -= 8;
}
return p[5];
}
int callCountdownLength() {
int buf[6];
return countdownLength1(buf, 6);
}
int countdownLength2() {
int buf[6];
int len = 6;
int *p = buf;
if(len % 8) {
return -1;
}
while(len > 0) {
p[0] = 0;
p[1] = 1;
p[2] = 2;
p[3] = 3;
p[4] = 4;
p[5] = 5;
p[6] = 6; // GOOD
p[7] = 7; // GOOD
p += 8;
len -= 8;
}
return p[5];
}
void pointer_size_larger_than_array_element_size() {
unsigned char buffer[100]; // getByteSize() = 100
int *ptr = (int *)buffer; // pai.getElementSize() will be sizeof(int) = 4 -> size = 25
ptr[24] = 0; // GOOD: writes bytes 96, 97, 98, 99
ptr[25] = 0; // BAD: writes bytes 100, 101, 102, 103
}
struct vec2 { int x, y; };
struct vec3 { int x, y, z; };
void pointer_size_smaller_than_array_element_size_but_does_not_divide_it() {
vec3 array[3]; // getByteSize() = 9 * sizeof(int)
vec2 *ptr = (vec2 *)array; // pai.getElementSize() will be 2 * sizeof(int) -> size = 4
ptr[3] = vec2{}; // GOOD: writes ints 6, 7
ptr[4] = vec2{}; // BAD: writes ints 8, 9
}
void pointer_size_larger_than_array_element_size_and_does_not_divide_it() {
vec2 array[2]; // getByteSize() = 4 * sizeof(int) = 4 * 4 = 16
vec3 *ptr = (vec3 *)array; // pai.getElementSize() will be 3 * sizeof(int) -> size = 1
ptr[0] = vec3{}; // GOOD: writes ints 0, 1, 2
ptr[1] = vec3{}; // BAD: writes ints 3, 4, 5 [NOT DETECTED]
}
void use(...);
void call_use(unsigned char* p, int n) {
if(n == 0) {
return;
}
if(n == 1) {
unsigned char x = p[0];
use(x);
}
if(n == 2) {
unsigned char x = p[0];
unsigned char y = p[1];
use(x, y);
}
if(n == 3) {
unsigned char x = p[0];
unsigned char y = p[1];
unsigned char z = p[2]; // GOOD [FALSE POSITIVE]: `call_use(buffer2, 2)` won't reach this point.
use(x, y, z);
}
}
void test_call_use() {
unsigned char buffer1[1];
call_use(buffer1,1);
unsigned char buffer2[2];
call_use(buffer2,2);
unsigned char buffer3[3];
call_use(buffer3,3);
}
void call_call_use(unsigned char* p, int n) {
call_use(p, n);
}
void test_call_use2() {
unsigned char buffer1[1];
call_call_use(buffer1,1);
unsigned char buffer2[2];
call_call_use(buffer2,2);
unsigned char buffer3[3];
call_call_use(buffer3,3);
}

View File

@@ -380,9 +380,10 @@ edges
| test.cpp:80:9:80:16 | mk_array indirection [end] | test.cpp:89:19:89:26 | call to mk_array [end] |
| test.cpp:80:9:80:16 | mk_array indirection [end] | test.cpp:119:18:119:25 | call to mk_array [end] |
| test.cpp:82:5:82:28 | ... = ... | test.cpp:82:9:82:13 | arr indirection [post update] [begin] |
| test.cpp:82:9:82:13 | arr indirection [post update] [begin] | test.cpp:80:9:80:16 | mk_array indirection [begin] |
| test.cpp:82:9:82:13 | arr indirection [post update] [begin] | test.cpp:83:5:83:7 | arr indirection [begin] |
| test.cpp:82:9:82:13 | arr indirection [post update] [begin] | test.cpp:83:15:83:17 | arr indirection [begin] |
| test.cpp:82:17:82:22 | call to malloc | test.cpp:82:5:82:28 | ... = ... |
| test.cpp:83:5:83:7 | arr indirection [begin] | test.cpp:80:9:80:16 | mk_array indirection [begin] |
| test.cpp:83:5:83:30 | ... = ... | test.cpp:83:9:83:11 | arr indirection [post update] [end] |
| test.cpp:83:9:83:11 | arr indirection [post update] [end] | test.cpp:80:9:80:16 | mk_array indirection [end] |
| test.cpp:83:15:83:17 | arr indirection [begin] | test.cpp:83:19:83:23 | begin indirection |
@@ -455,9 +456,10 @@ edges
| test.cpp:124:15:124:20 | call to malloc | test.cpp:125:5:125:17 | ... = ... |
| test.cpp:124:15:124:20 | call to malloc | test.cpp:126:15:126:15 | p |
| test.cpp:125:5:125:17 | ... = ... | test.cpp:125:9:125:13 | arr indirection [post update] [begin] |
| test.cpp:125:9:125:13 | arr indirection [post update] [begin] | test.cpp:129:11:129:13 | arr indirection [begin] |
| test.cpp:125:9:125:13 | arr indirection [post update] [begin] | test.cpp:133:11:133:13 | arr indirection [begin] |
| test.cpp:125:9:125:13 | arr indirection [post update] [begin] | test.cpp:137:11:137:13 | arr indirection [begin] |
| test.cpp:125:9:125:13 | arr indirection [post update] [begin] | test.cpp:126:5:126:7 | arr indirection [begin] |
| test.cpp:126:5:126:7 | arr indirection [begin] | test.cpp:129:11:129:13 | arr indirection [begin] |
| test.cpp:126:5:126:7 | arr indirection [begin] | test.cpp:133:11:133:13 | arr indirection [begin] |
| test.cpp:126:5:126:7 | arr indirection [begin] | test.cpp:137:11:137:13 | arr indirection [begin] |
| test.cpp:129:11:129:13 | arr indirection [begin] | test.cpp:129:15:129:19 | begin indirection |
| test.cpp:129:15:129:19 | begin indirection | test.cpp:129:15:129:19 | begin |
| test.cpp:133:11:133:13 | arr indirection [begin] | test.cpp:133:15:133:19 | begin indirection |
@@ -469,9 +471,10 @@ edges
| test.cpp:141:10:141:19 | mk_array_p indirection [end] | test.cpp:150:20:150:29 | call to mk_array_p indirection [end] |
| test.cpp:141:10:141:19 | mk_array_p indirection [end] | test.cpp:180:19:180:28 | call to mk_array_p indirection [end] |
| test.cpp:143:5:143:29 | ... = ... | test.cpp:143:10:143:14 | arr indirection [post update] [begin] |
| test.cpp:143:10:143:14 | arr indirection [post update] [begin] | test.cpp:141:10:141:19 | mk_array_p indirection [begin] |
| test.cpp:143:10:143:14 | arr indirection [post update] [begin] | test.cpp:144:5:144:7 | arr indirection [begin] |
| test.cpp:143:10:143:14 | arr indirection [post update] [begin] | test.cpp:144:16:144:18 | arr indirection [begin] |
| test.cpp:143:18:143:23 | call to malloc | test.cpp:143:5:143:29 | ... = ... |
| test.cpp:144:5:144:7 | arr indirection [begin] | test.cpp:141:10:141:19 | mk_array_p indirection [begin] |
| test.cpp:144:5:144:32 | ... = ... | test.cpp:144:10:144:12 | arr indirection [post update] [end] |
| test.cpp:144:10:144:12 | arr indirection [post update] [end] | test.cpp:141:10:141:19 | mk_array_p indirection [end] |
| test.cpp:144:16:144:18 | arr indirection [begin] | test.cpp:144:21:144:25 | begin indirection |
@@ -664,11 +667,6 @@ edges
| test.cpp:338:8:338:15 | * ... | test.cpp:342:8:342:17 | * ... |
| test.cpp:341:8:341:17 | * ... | test.cpp:342:8:342:17 | * ... |
| test.cpp:347:14:347:27 | new[] | test.cpp:348:15:348:16 | xs |
| test.cpp:348:15:348:16 | xs | test.cpp:350:16:350:19 | ... ++ |
| test.cpp:348:15:348:16 | xs | test.cpp:350:16:350:19 | ... ++ |
| test.cpp:350:16:350:19 | ... ++ | test.cpp:350:15:350:19 | Load: * ... |
| test.cpp:350:16:350:19 | ... ++ | test.cpp:350:16:350:19 | ... ++ |
| test.cpp:350:16:350:19 | ... ++ | test.cpp:350:16:350:19 | ... ++ |
| test.cpp:355:14:355:27 | new[] | test.cpp:356:15:356:16 | xs |
| test.cpp:356:15:356:16 | xs | test.cpp:356:15:356:23 | ... + ... |
| test.cpp:356:15:356:16 | xs | test.cpp:356:15:356:23 | ... + ... |
@@ -722,14 +720,6 @@ edges
| test.cpp:359:16:359:27 | end_plus_one | test.cpp:359:14:359:32 | Load: * ... |
| test.cpp:359:16:359:31 | ... + ... | test.cpp:359:14:359:32 | Load: * ... |
| test.cpp:363:14:363:27 | new[] | test.cpp:365:15:365:15 | p |
| test.cpp:365:15:365:15 | p | test.cpp:368:5:368:10 | ... += ... |
| test.cpp:365:15:365:15 | p | test.cpp:368:5:368:10 | ... += ... |
| test.cpp:368:5:368:10 | ... += ... | test.cpp:371:7:371:7 | p |
| test.cpp:368:5:368:10 | ... += ... | test.cpp:371:7:371:7 | p |
| test.cpp:368:5:368:10 | ... += ... | test.cpp:372:16:372:16 | p |
| test.cpp:368:5:368:10 | ... += ... | test.cpp:372:16:372:16 | p |
| test.cpp:371:7:371:7 | p | test.cpp:372:15:372:16 | Load: * ... |
| test.cpp:372:16:372:16 | p | test.cpp:372:15:372:16 | Load: * ... |
| test.cpp:377:14:377:27 | new[] | test.cpp:378:15:378:16 | xs |
| test.cpp:378:15:378:16 | xs | test.cpp:378:15:378:23 | ... + ... |
| test.cpp:378:15:378:16 | xs | test.cpp:378:15:378:23 | ... + ... |
@@ -753,6 +743,304 @@ edges
| test.cpp:381:5:381:9 | ... ++ | test.cpp:384:14:384:16 | end |
| test.cpp:381:5:381:9 | ... ++ | test.cpp:384:14:384:16 | end |
| test.cpp:384:14:384:16 | end | test.cpp:384:13:384:16 | Load: * ... |
| test.cpp:388:14:388:27 | new[] | test.cpp:389:16:389:17 | xs |
| test.cpp:388:14:388:27 | new[] | test.cpp:392:3:392:4 | xs |
| test.cpp:399:14:399:27 | new[] | test.cpp:400:16:400:17 | xs |
| test.cpp:399:14:399:27 | new[] | test.cpp:402:5:402:6 | xs |
| test.cpp:410:14:410:27 | new[] | test.cpp:411:16:411:17 | xs |
| test.cpp:410:14:410:27 | new[] | test.cpp:413:5:413:6 | xs |
| test.cpp:411:15:411:23 | & ... | test.cpp:411:15:411:23 | & ... |
| test.cpp:411:15:411:23 | & ... | test.cpp:411:15:411:23 | & ... |
| test.cpp:411:15:411:23 | & ... | test.cpp:412:12:412:14 | end |
| test.cpp:411:15:411:23 | & ... | test.cpp:412:12:412:14 | end |
| test.cpp:411:15:411:23 | & ... | test.cpp:412:12:412:14 | end |
| test.cpp:411:15:411:23 | & ... | test.cpp:412:12:412:14 | end |
| test.cpp:411:15:411:23 | & ... | test.cpp:414:14:414:16 | end |
| test.cpp:411:15:411:23 | & ... | test.cpp:414:14:414:16 | end |
| test.cpp:411:15:411:23 | & ... | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:411:15:411:23 | & ... | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:411:15:411:23 | & ... | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:411:15:411:23 | & ... | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:411:16:411:17 | xs | test.cpp:411:15:411:23 | & ... |
| test.cpp:411:16:411:17 | xs | test.cpp:411:15:411:23 | & ... |
| test.cpp:411:16:411:17 | xs | test.cpp:411:15:411:23 | & ... |
| test.cpp:411:16:411:17 | xs | test.cpp:411:15:411:23 | & ... |
| test.cpp:411:16:411:17 | xs | test.cpp:411:16:411:23 | access to array |
| test.cpp:411:16:411:17 | xs | test.cpp:411:16:411:23 | access to array |
| test.cpp:411:16:411:17 | xs | test.cpp:412:12:412:14 | end |
| test.cpp:411:16:411:17 | xs | test.cpp:412:12:412:14 | end |
| test.cpp:411:16:411:17 | xs | test.cpp:413:5:413:8 | ... ++ |
| test.cpp:411:16:411:17 | xs | test.cpp:413:5:413:8 | ... ++ |
| test.cpp:411:16:411:17 | xs | test.cpp:413:5:413:8 | ... ++ |
| test.cpp:411:16:411:17 | xs | test.cpp:413:5:413:8 | ... ++ |
| test.cpp:411:16:411:17 | xs | test.cpp:414:9:414:10 | xs |
| test.cpp:411:16:411:17 | xs | test.cpp:414:14:414:16 | end |
| test.cpp:411:16:411:17 | xs | test.cpp:415:7:415:11 | access to array |
| test.cpp:411:16:411:23 | access to array | test.cpp:411:15:411:23 | & ... |
| test.cpp:411:16:411:23 | access to array | test.cpp:411:15:411:23 | & ... |
| test.cpp:411:16:411:23 | access to array | test.cpp:411:15:411:23 | & ... |
| test.cpp:411:16:411:23 | access to array | test.cpp:411:15:411:23 | & ... |
| test.cpp:411:16:411:23 | access to array | test.cpp:412:12:412:14 | end |
| test.cpp:411:16:411:23 | access to array | test.cpp:412:12:412:14 | end |
| test.cpp:411:16:411:23 | access to array | test.cpp:414:14:414:16 | end |
| test.cpp:411:16:411:23 | access to array | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:411:16:411:23 | access to array | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:412:12:412:14 | end | test.cpp:414:14:414:16 | end |
| test.cpp:412:12:412:14 | end | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:412:12:412:14 | end | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:413:5:413:8 | ... ++ | test.cpp:413:5:413:8 | ... ++ |
| test.cpp:413:5:413:8 | ... ++ | test.cpp:413:5:413:8 | ... ++ |
| test.cpp:413:5:413:8 | ... ++ | test.cpp:414:9:414:10 | xs |
| test.cpp:413:5:413:8 | ... ++ | test.cpp:414:9:414:10 | xs |
| test.cpp:413:5:413:8 | ... ++ | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:413:5:413:8 | ... ++ | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:413:5:413:8 | ... ++ | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:413:5:413:8 | ... ++ | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:414:9:414:10 | xs | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:414:14:414:16 | end | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:415:7:415:11 | access to array | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:421:14:421:27 | new[] | test.cpp:422:16:422:17 | xs |
| test.cpp:421:14:421:27 | new[] | test.cpp:424:5:424:6 | xs |
| test.cpp:422:15:422:23 | & ... | test.cpp:422:15:422:23 | & ... |
| test.cpp:422:15:422:23 | & ... | test.cpp:422:15:422:23 | & ... |
| test.cpp:422:15:422:23 | & ... | test.cpp:423:12:423:14 | end |
| test.cpp:422:15:422:23 | & ... | test.cpp:423:12:423:14 | end |
| test.cpp:422:15:422:23 | & ... | test.cpp:423:12:423:14 | end |
| test.cpp:422:15:422:23 | & ... | test.cpp:423:12:423:14 | end |
| test.cpp:422:15:422:23 | & ... | test.cpp:425:18:425:20 | end |
| test.cpp:422:15:422:23 | & ... | test.cpp:425:18:425:20 | end |
| test.cpp:422:15:422:23 | & ... | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:422:15:422:23 | & ... | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:422:15:422:23 | & ... | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:422:15:422:23 | & ... | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:422:16:422:17 | xs | test.cpp:422:15:422:23 | & ... |
| test.cpp:422:16:422:17 | xs | test.cpp:422:15:422:23 | & ... |
| test.cpp:422:16:422:17 | xs | test.cpp:422:15:422:23 | & ... |
| test.cpp:422:16:422:17 | xs | test.cpp:422:15:422:23 | & ... |
| test.cpp:422:16:422:17 | xs | test.cpp:422:16:422:23 | access to array |
| test.cpp:422:16:422:17 | xs | test.cpp:422:16:422:23 | access to array |
| test.cpp:422:16:422:17 | xs | test.cpp:423:12:423:14 | end |
| test.cpp:422:16:422:17 | xs | test.cpp:423:12:423:14 | end |
| test.cpp:422:16:422:17 | xs | test.cpp:424:5:424:8 | ... ++ |
| test.cpp:422:16:422:17 | xs | test.cpp:424:5:424:8 | ... ++ |
| test.cpp:422:16:422:17 | xs | test.cpp:424:5:424:8 | ... ++ |
| test.cpp:422:16:422:17 | xs | test.cpp:424:5:424:8 | ... ++ |
| test.cpp:422:16:422:17 | xs | test.cpp:425:9:425:10 | xs |
| test.cpp:422:16:422:17 | xs | test.cpp:425:9:425:10 | xs |
| test.cpp:422:16:422:17 | xs | test.cpp:425:18:425:20 | end |
| test.cpp:422:16:422:17 | xs | test.cpp:426:7:426:8 | xs |
| test.cpp:422:16:422:17 | xs | test.cpp:426:7:426:11 | access to array |
| test.cpp:422:16:422:23 | access to array | test.cpp:422:15:422:23 | & ... |
| test.cpp:422:16:422:23 | access to array | test.cpp:422:15:422:23 | & ... |
| test.cpp:422:16:422:23 | access to array | test.cpp:422:15:422:23 | & ... |
| test.cpp:422:16:422:23 | access to array | test.cpp:422:15:422:23 | & ... |
| test.cpp:422:16:422:23 | access to array | test.cpp:423:12:423:14 | end |
| test.cpp:422:16:422:23 | access to array | test.cpp:423:12:423:14 | end |
| test.cpp:422:16:422:23 | access to array | test.cpp:425:18:425:20 | end |
| test.cpp:422:16:422:23 | access to array | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:422:16:422:23 | access to array | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:423:12:423:14 | end | test.cpp:425:18:425:20 | end |
| test.cpp:423:12:423:14 | end | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:423:12:423:14 | end | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:424:5:424:8 | ... ++ | test.cpp:424:5:424:8 | ... ++ |
| test.cpp:424:5:424:8 | ... ++ | test.cpp:424:5:424:8 | ... ++ |
| test.cpp:424:5:424:8 | ... ++ | test.cpp:425:9:425:10 | xs |
| test.cpp:424:5:424:8 | ... ++ | test.cpp:425:9:425:10 | xs |
| test.cpp:424:5:424:8 | ... ++ | test.cpp:425:9:425:10 | xs |
| test.cpp:424:5:424:8 | ... ++ | test.cpp:425:9:425:10 | xs |
| test.cpp:424:5:424:8 | ... ++ | test.cpp:426:7:426:8 | xs |
| test.cpp:424:5:424:8 | ... ++ | test.cpp:426:7:426:8 | xs |
| test.cpp:424:5:424:8 | ... ++ | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:424:5:424:8 | ... ++ | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:424:5:424:8 | ... ++ | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:424:5:424:8 | ... ++ | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:425:9:425:10 | xs | test.cpp:426:7:426:8 | xs |
| test.cpp:425:9:425:10 | xs | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:425:9:425:10 | xs | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:425:18:425:20 | end | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:426:7:426:8 | xs | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:426:7:426:11 | access to array | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:432:14:432:27 | new[] | test.cpp:433:16:433:17 | xs |
| test.cpp:432:14:432:27 | new[] | test.cpp:436:5:436:6 | xs |
| test.cpp:433:15:433:23 | & ... | test.cpp:433:15:433:23 | & ... |
| test.cpp:433:15:433:23 | & ... | test.cpp:433:15:433:23 | & ... |
| test.cpp:433:15:433:23 | & ... | test.cpp:434:12:434:14 | end |
| test.cpp:433:15:433:23 | & ... | test.cpp:434:12:434:14 | end |
| test.cpp:433:15:433:23 | & ... | test.cpp:434:12:434:14 | end |
| test.cpp:433:15:433:23 | & ... | test.cpp:434:12:434:14 | end |
| test.cpp:433:15:433:23 | & ... | test.cpp:435:5:435:7 | end |
| test.cpp:433:15:433:23 | & ... | test.cpp:435:5:435:7 | end |
| test.cpp:433:15:433:23 | & ... | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:433:15:433:23 | & ... | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:433:15:433:23 | & ... | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:433:15:433:23 | & ... | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:433:16:433:17 | xs | test.cpp:433:15:433:23 | & ... |
| test.cpp:433:16:433:17 | xs | test.cpp:433:15:433:23 | & ... |
| test.cpp:433:16:433:17 | xs | test.cpp:433:15:433:23 | & ... |
| test.cpp:433:16:433:17 | xs | test.cpp:433:15:433:23 | & ... |
| test.cpp:433:16:433:17 | xs | test.cpp:433:16:433:23 | access to array |
| test.cpp:433:16:433:17 | xs | test.cpp:433:16:433:23 | access to array |
| test.cpp:433:16:433:17 | xs | test.cpp:434:12:434:14 | end |
| test.cpp:433:16:433:17 | xs | test.cpp:434:12:434:14 | end |
| test.cpp:433:16:433:17 | xs | test.cpp:435:5:435:7 | end |
| test.cpp:433:16:433:17 | xs | test.cpp:436:5:436:8 | ... ++ |
| test.cpp:433:16:433:17 | xs | test.cpp:436:5:436:8 | ... ++ |
| test.cpp:433:16:433:17 | xs | test.cpp:436:5:436:8 | ... ++ |
| test.cpp:433:16:433:17 | xs | test.cpp:436:5:436:8 | ... ++ |
| test.cpp:433:16:433:17 | xs | test.cpp:437:9:437:10 | xs |
| test.cpp:433:16:433:17 | xs | test.cpp:438:7:438:11 | access to array |
| test.cpp:433:16:433:23 | access to array | test.cpp:433:15:433:23 | & ... |
| test.cpp:433:16:433:23 | access to array | test.cpp:433:15:433:23 | & ... |
| test.cpp:433:16:433:23 | access to array | test.cpp:433:15:433:23 | & ... |
| test.cpp:433:16:433:23 | access to array | test.cpp:433:15:433:23 | & ... |
| test.cpp:433:16:433:23 | access to array | test.cpp:434:12:434:14 | end |
| test.cpp:433:16:433:23 | access to array | test.cpp:434:12:434:14 | end |
| test.cpp:433:16:433:23 | access to array | test.cpp:435:5:435:7 | end |
| test.cpp:433:16:433:23 | access to array | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:433:16:433:23 | access to array | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:434:12:434:14 | end | test.cpp:435:5:435:7 | end |
| test.cpp:434:12:434:14 | end | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:434:12:434:14 | end | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:435:5:435:7 | end | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:436:5:436:8 | ... ++ | test.cpp:436:5:436:8 | ... ++ |
| test.cpp:436:5:436:8 | ... ++ | test.cpp:436:5:436:8 | ... ++ |
| test.cpp:436:5:436:8 | ... ++ | test.cpp:437:9:437:10 | xs |
| test.cpp:436:5:436:8 | ... ++ | test.cpp:437:9:437:10 | xs |
| test.cpp:436:5:436:8 | ... ++ | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:436:5:436:8 | ... ++ | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:436:5:436:8 | ... ++ | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:436:5:436:8 | ... ++ | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:437:9:437:10 | xs | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:438:7:438:11 | access to array | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:444:14:444:27 | new[] | test.cpp:445:16:445:17 | xs |
| test.cpp:444:14:444:27 | new[] | test.cpp:448:5:448:6 | xs |
| test.cpp:445:15:445:23 | & ... | test.cpp:445:15:445:23 | & ... |
| test.cpp:445:15:445:23 | & ... | test.cpp:445:15:445:23 | & ... |
| test.cpp:445:15:445:23 | & ... | test.cpp:446:3:446:5 | end |
| test.cpp:445:15:445:23 | & ... | test.cpp:446:3:446:5 | end |
| test.cpp:445:15:445:23 | & ... | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:445:15:445:23 | & ... | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:445:15:445:23 | & ... | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:445:15:445:23 | & ... | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:445:16:445:17 | xs | test.cpp:445:15:445:23 | & ... |
| test.cpp:445:16:445:17 | xs | test.cpp:445:15:445:23 | & ... |
| test.cpp:445:16:445:17 | xs | test.cpp:445:15:445:23 | & ... |
| test.cpp:445:16:445:17 | xs | test.cpp:445:15:445:23 | & ... |
| test.cpp:445:16:445:17 | xs | test.cpp:445:16:445:23 | access to array |
| test.cpp:445:16:445:17 | xs | test.cpp:445:16:445:23 | access to array |
| test.cpp:445:16:445:17 | xs | test.cpp:446:3:446:5 | end |
| test.cpp:445:16:445:17 | xs | test.cpp:448:5:448:8 | ... ++ |
| test.cpp:445:16:445:17 | xs | test.cpp:448:5:448:8 | ... ++ |
| test.cpp:445:16:445:17 | xs | test.cpp:448:5:448:8 | ... ++ |
| test.cpp:445:16:445:17 | xs | test.cpp:448:5:448:8 | ... ++ |
| test.cpp:445:16:445:17 | xs | test.cpp:449:9:449:10 | xs |
| test.cpp:445:16:445:17 | xs | test.cpp:450:7:450:11 | access to array |
| test.cpp:445:16:445:23 | access to array | test.cpp:445:15:445:23 | & ... |
| test.cpp:445:16:445:23 | access to array | test.cpp:445:15:445:23 | & ... |
| test.cpp:445:16:445:23 | access to array | test.cpp:445:15:445:23 | & ... |
| test.cpp:445:16:445:23 | access to array | test.cpp:445:15:445:23 | & ... |
| test.cpp:445:16:445:23 | access to array | test.cpp:446:3:446:5 | end |
| test.cpp:445:16:445:23 | access to array | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:445:16:445:23 | access to array | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:446:3:446:5 | end | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:448:5:448:8 | ... ++ | test.cpp:448:5:448:8 | ... ++ |
| test.cpp:448:5:448:8 | ... ++ | test.cpp:448:5:448:8 | ... ++ |
| test.cpp:448:5:448:8 | ... ++ | test.cpp:449:9:449:10 | xs |
| test.cpp:448:5:448:8 | ... ++ | test.cpp:449:9:449:10 | xs |
| test.cpp:448:5:448:8 | ... ++ | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:448:5:448:8 | ... ++ | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:448:5:448:8 | ... ++ | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:448:5:448:8 | ... ++ | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:449:9:449:10 | xs | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:450:7:450:11 | access to array | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:456:14:456:31 | new[] | test.cpp:457:16:457:17 | xs |
| test.cpp:456:14:456:31 | new[] | test.cpp:460:5:460:6 | xs |
| test.cpp:468:14:468:27 | new[] | test.cpp:469:16:469:17 | xs |
| test.cpp:468:14:468:27 | new[] | test.cpp:472:5:472:6 | xs |
| test.cpp:480:14:480:27 | new[] | test.cpp:481:16:481:17 | xs |
| test.cpp:480:14:480:27 | new[] | test.cpp:484:5:484:6 | xs |
| test.cpp:481:15:481:23 | & ... | test.cpp:481:15:481:23 | & ... |
| test.cpp:481:15:481:23 | & ... | test.cpp:481:15:481:23 | & ... |
| test.cpp:481:15:481:23 | & ... | test.cpp:482:3:482:5 | end |
| test.cpp:481:15:481:23 | & ... | test.cpp:482:3:482:5 | end |
| test.cpp:481:15:481:23 | & ... | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:481:15:481:23 | & ... | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:481:15:481:23 | & ... | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:481:15:481:23 | & ... | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:481:16:481:17 | xs | test.cpp:481:15:481:23 | & ... |
| test.cpp:481:16:481:17 | xs | test.cpp:481:15:481:23 | & ... |
| test.cpp:481:16:481:17 | xs | test.cpp:481:15:481:23 | & ... |
| test.cpp:481:16:481:17 | xs | test.cpp:481:15:481:23 | & ... |
| test.cpp:481:16:481:17 | xs | test.cpp:481:16:481:23 | access to array |
| test.cpp:481:16:481:17 | xs | test.cpp:481:16:481:23 | access to array |
| test.cpp:481:16:481:17 | xs | test.cpp:482:3:482:5 | end |
| test.cpp:481:16:481:17 | xs | test.cpp:484:5:484:8 | ... ++ |
| test.cpp:481:16:481:17 | xs | test.cpp:484:5:484:8 | ... ++ |
| test.cpp:481:16:481:17 | xs | test.cpp:484:5:484:8 | ... ++ |
| test.cpp:481:16:481:17 | xs | test.cpp:484:5:484:8 | ... ++ |
| test.cpp:481:16:481:17 | xs | test.cpp:485:9:485:10 | xs |
| test.cpp:481:16:481:17 | xs | test.cpp:486:7:486:11 | access to array |
| test.cpp:481:16:481:23 | access to array | test.cpp:481:15:481:23 | & ... |
| test.cpp:481:16:481:23 | access to array | test.cpp:481:15:481:23 | & ... |
| test.cpp:481:16:481:23 | access to array | test.cpp:481:15:481:23 | & ... |
| test.cpp:481:16:481:23 | access to array | test.cpp:481:15:481:23 | & ... |
| test.cpp:481:16:481:23 | access to array | test.cpp:482:3:482:5 | end |
| test.cpp:481:16:481:23 | access to array | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:481:16:481:23 | access to array | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:482:3:482:5 | end | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:484:5:484:8 | ... ++ | test.cpp:484:5:484:8 | ... ++ |
| test.cpp:484:5:484:8 | ... ++ | test.cpp:484:5:484:8 | ... ++ |
| test.cpp:484:5:484:8 | ... ++ | test.cpp:485:9:485:10 | xs |
| test.cpp:484:5:484:8 | ... ++ | test.cpp:485:9:485:10 | xs |
| test.cpp:484:5:484:8 | ... ++ | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:484:5:484:8 | ... ++ | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:484:5:484:8 | ... ++ | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:484:5:484:8 | ... ++ | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:485:9:485:10 | xs | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:486:7:486:11 | access to array | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:499:3:499:25 | ... = ... | test.cpp:499:7:499:8 | val indirection [post update] [xs] |
| test.cpp:499:7:499:8 | val indirection [post update] [xs] | test.cpp:500:3:500:5 | val indirection [xs] |
| test.cpp:499:12:499:25 | new[] | test.cpp:499:3:499:25 | ... = ... |
| test.cpp:500:3:500:5 | val indirection [xs] | test.cpp:500:7:500:8 | xs indirection |
| test.cpp:500:7:500:8 | xs indirection | test.cpp:500:7:500:8 | xs |
| test.cpp:510:16:510:33 | new[] | test.cpp:512:7:512:8 | xs |
| test.cpp:520:14:520:27 | new[] | test.cpp:526:5:526:6 | xs |
| test.cpp:532:14:532:27 | new[] | test.cpp:537:5:537:6 | xs |
| test.cpp:543:14:543:27 | new[] | test.cpp:548:5:548:6 | xs |
| test.cpp:548:5:548:6 | xs | test.cpp:548:5:548:15 | access to array |
| test.cpp:548:5:548:15 | access to array | test.cpp:548:5:548:19 | Store: ... = ... |
| test.cpp:554:14:554:27 | new[] | test.cpp:559:5:559:6 | xs |
| test.cpp:559:5:559:6 | xs | test.cpp:559:5:559:15 | access to array |
| test.cpp:559:5:559:15 | access to array | test.cpp:559:5:559:19 | Store: ... = ... |
| test.cpp:565:14:565:27 | new[] | test.cpp:570:5:570:6 | xs |
| test.cpp:576:14:576:27 | new[] | test.cpp:581:5:581:6 | xs |
| test.cpp:587:14:587:31 | new[] | test.cpp:592:5:592:6 | xs |
| test.cpp:598:14:598:31 | new[] | test.cpp:603:5:603:6 | xs |
| test.cpp:609:14:609:31 | new[] | test.cpp:614:5:614:6 | xs |
| test.cpp:620:14:620:31 | new[] | test.cpp:625:5:625:6 | xs |
| test.cpp:631:14:631:31 | new[] | test.cpp:636:5:636:6 | xs |
| test.cpp:642:14:642:31 | new[] | test.cpp:647:5:647:6 | xs |
| test.cpp:647:5:647:6 | xs | test.cpp:647:5:647:15 | access to array |
| test.cpp:647:5:647:15 | access to array | test.cpp:647:5:647:19 | Store: ... = ... |
| test.cpp:652:14:652:27 | new[] | test.cpp:653:16:653:17 | xs |
| test.cpp:652:14:652:27 | new[] | test.cpp:656:3:656:4 | xs |
| test.cpp:653:16:653:17 | xs | test.cpp:656:3:656:6 | ... ++ |
| test.cpp:653:16:653:17 | xs | test.cpp:656:3:656:6 | ... ++ |
| test.cpp:653:16:653:17 | xs | test.cpp:656:3:656:6 | ... ++ |
| test.cpp:653:16:653:17 | xs | test.cpp:656:3:656:6 | ... ++ |
| test.cpp:653:16:653:17 | xs | test.cpp:657:7:657:8 | xs |
| test.cpp:656:3:656:6 | ... ++ | test.cpp:656:3:656:6 | ... ++ |
| test.cpp:656:3:656:6 | ... ++ | test.cpp:656:3:656:6 | ... ++ |
| test.cpp:656:3:656:6 | ... ++ | test.cpp:657:7:657:8 | xs |
| test.cpp:656:3:656:6 | ... ++ | test.cpp:657:7:657:8 | xs |
| test.cpp:656:3:656:6 | ... ++ | test.cpp:662:3:662:11 | Store: ... = ... |
| test.cpp:656:3:656:6 | ... ++ | test.cpp:662:3:662:11 | Store: ... = ... |
| test.cpp:656:3:656:6 | ... ++ | test.cpp:662:3:662:11 | Store: ... = ... |
| test.cpp:656:3:656:6 | ... ++ | test.cpp:662:3:662:11 | Store: ... = ... |
| test.cpp:657:7:657:8 | xs | test.cpp:662:3:662:11 | Store: ... = ... |
| test.cpp:667:14:667:31 | new[] | test.cpp:675:7:675:8 | xs |
| test.cpp:675:7:675:8 | xs | test.cpp:675:7:675:19 | access to array |
| test.cpp:675:7:675:19 | access to array | test.cpp:675:7:675:23 | Store: ... = ... |
nodes
| test.cpp:4:15:4:20 | call to malloc | semmle.label | call to malloc |
| test.cpp:5:15:5:15 | p | semmle.label | p |
@@ -845,6 +1133,7 @@ nodes
| test.cpp:82:5:82:28 | ... = ... | semmle.label | ... = ... |
| test.cpp:82:9:82:13 | arr indirection [post update] [begin] | semmle.label | arr indirection [post update] [begin] |
| test.cpp:82:17:82:22 | call to malloc | semmle.label | call to malloc |
| test.cpp:83:5:83:7 | arr indirection [begin] | semmle.label | arr indirection [begin] |
| test.cpp:83:5:83:30 | ... = ... | semmle.label | ... = ... |
| test.cpp:83:9:83:11 | arr indirection [post update] [end] | semmle.label | arr indirection [post update] [end] |
| test.cpp:83:15:83:17 | arr indirection [begin] | semmle.label | arr indirection [begin] |
@@ -904,6 +1193,7 @@ nodes
| test.cpp:124:15:124:20 | call to malloc | semmle.label | call to malloc |
| test.cpp:125:5:125:17 | ... = ... | semmle.label | ... = ... |
| test.cpp:125:9:125:13 | arr indirection [post update] [begin] | semmle.label | arr indirection [post update] [begin] |
| test.cpp:126:5:126:7 | arr indirection [begin] | semmle.label | arr indirection [begin] |
| test.cpp:126:15:126:15 | p | semmle.label | p |
| test.cpp:129:11:129:13 | arr indirection [begin] | semmle.label | arr indirection [begin] |
| test.cpp:129:15:129:19 | begin | semmle.label | begin |
@@ -919,6 +1209,7 @@ nodes
| test.cpp:143:5:143:29 | ... = ... | semmle.label | ... = ... |
| test.cpp:143:10:143:14 | arr indirection [post update] [begin] | semmle.label | arr indirection [post update] [begin] |
| test.cpp:143:18:143:23 | call to malloc | semmle.label | call to malloc |
| test.cpp:144:5:144:7 | arr indirection [begin] | semmle.label | arr indirection [begin] |
| test.cpp:144:5:144:32 | ... = ... | semmle.label | ... = ... |
| test.cpp:144:10:144:12 | arr indirection [post update] [end] | semmle.label | arr indirection [post update] [end] |
| test.cpp:144:16:144:18 | arr indirection [begin] | semmle.label | arr indirection [begin] |
@@ -1057,10 +1348,6 @@ nodes
| test.cpp:342:8:342:17 | * ... | semmle.label | * ... |
| test.cpp:347:14:347:27 | new[] | semmle.label | new[] |
| test.cpp:348:15:348:16 | xs | semmle.label | xs |
| test.cpp:350:15:350:19 | Load: * ... | semmle.label | Load: * ... |
| test.cpp:350:16:350:19 | ... ++ | semmle.label | ... ++ |
| test.cpp:350:16:350:19 | ... ++ | semmle.label | ... ++ |
| test.cpp:350:16:350:19 | ... ++ | semmle.label | ... ++ |
| test.cpp:355:14:355:27 | new[] | semmle.label | new[] |
| test.cpp:356:15:356:16 | xs | semmle.label | xs |
| test.cpp:356:15:356:23 | ... + ... | semmle.label | ... + ... |
@@ -1080,11 +1367,6 @@ nodes
| test.cpp:359:16:359:31 | ... + ... | semmle.label | ... + ... |
| test.cpp:363:14:363:27 | new[] | semmle.label | new[] |
| test.cpp:365:15:365:15 | p | semmle.label | p |
| test.cpp:368:5:368:10 | ... += ... | semmle.label | ... += ... |
| test.cpp:368:5:368:10 | ... += ... | semmle.label | ... += ... |
| test.cpp:371:7:371:7 | p | semmle.label | p |
| test.cpp:372:15:372:16 | Load: * ... | semmle.label | Load: * ... |
| test.cpp:372:16:372:16 | p | semmle.label | p |
| test.cpp:377:14:377:27 | new[] | semmle.label | new[] |
| test.cpp:378:15:378:16 | xs | semmle.label | xs |
| test.cpp:378:15:378:23 | ... + ... | semmle.label | ... + ... |
@@ -1096,6 +1378,162 @@ nodes
| test.cpp:381:5:381:9 | ... ++ | semmle.label | ... ++ |
| test.cpp:384:13:384:16 | Load: * ... | semmle.label | Load: * ... |
| test.cpp:384:14:384:16 | end | semmle.label | end |
| test.cpp:388:14:388:27 | new[] | semmle.label | new[] |
| test.cpp:389:16:389:17 | xs | semmle.label | xs |
| test.cpp:392:3:392:4 | xs | semmle.label | xs |
| test.cpp:399:14:399:27 | new[] | semmle.label | new[] |
| test.cpp:400:16:400:17 | xs | semmle.label | xs |
| test.cpp:402:5:402:6 | xs | semmle.label | xs |
| test.cpp:410:14:410:27 | new[] | semmle.label | new[] |
| test.cpp:411:15:411:23 | & ... | semmle.label | & ... |
| test.cpp:411:15:411:23 | & ... | semmle.label | & ... |
| test.cpp:411:15:411:23 | & ... | semmle.label | & ... |
| test.cpp:411:15:411:23 | & ... | semmle.label | & ... |
| test.cpp:411:16:411:17 | xs | semmle.label | xs |
| test.cpp:411:16:411:23 | access to array | semmle.label | access to array |
| test.cpp:411:16:411:23 | access to array | semmle.label | access to array |
| test.cpp:412:12:412:14 | end | semmle.label | end |
| test.cpp:412:12:412:14 | end | semmle.label | end |
| test.cpp:413:5:413:6 | xs | semmle.label | xs |
| test.cpp:413:5:413:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:413:5:413:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:413:5:413:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:413:5:413:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:414:9:414:10 | xs | semmle.label | xs |
| test.cpp:414:14:414:16 | end | semmle.label | end |
| test.cpp:415:7:415:11 | access to array | semmle.label | access to array |
| test.cpp:415:7:415:15 | Store: ... = ... | semmle.label | Store: ... = ... |
| test.cpp:421:14:421:27 | new[] | semmle.label | new[] |
| test.cpp:422:15:422:23 | & ... | semmle.label | & ... |
| test.cpp:422:15:422:23 | & ... | semmle.label | & ... |
| test.cpp:422:15:422:23 | & ... | semmle.label | & ... |
| test.cpp:422:15:422:23 | & ... | semmle.label | & ... |
| test.cpp:422:16:422:17 | xs | semmle.label | xs |
| test.cpp:422:16:422:23 | access to array | semmle.label | access to array |
| test.cpp:422:16:422:23 | access to array | semmle.label | access to array |
| test.cpp:423:12:423:14 | end | semmle.label | end |
| test.cpp:423:12:423:14 | end | semmle.label | end |
| test.cpp:424:5:424:6 | xs | semmle.label | xs |
| test.cpp:424:5:424:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:424:5:424:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:424:5:424:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:424:5:424:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:425:9:425:10 | xs | semmle.label | xs |
| test.cpp:425:9:425:10 | xs | semmle.label | xs |
| test.cpp:425:18:425:20 | end | semmle.label | end |
| test.cpp:426:7:426:8 | xs | semmle.label | xs |
| test.cpp:426:7:426:11 | access to array | semmle.label | access to array |
| test.cpp:426:7:426:15 | Store: ... = ... | semmle.label | Store: ... = ... |
| test.cpp:432:14:432:27 | new[] | semmle.label | new[] |
| test.cpp:433:15:433:23 | & ... | semmle.label | & ... |
| test.cpp:433:15:433:23 | & ... | semmle.label | & ... |
| test.cpp:433:15:433:23 | & ... | semmle.label | & ... |
| test.cpp:433:15:433:23 | & ... | semmle.label | & ... |
| test.cpp:433:16:433:17 | xs | semmle.label | xs |
| test.cpp:433:16:433:23 | access to array | semmle.label | access to array |
| test.cpp:433:16:433:23 | access to array | semmle.label | access to array |
| test.cpp:434:12:434:14 | end | semmle.label | end |
| test.cpp:434:12:434:14 | end | semmle.label | end |
| test.cpp:435:5:435:7 | end | semmle.label | end |
| test.cpp:436:5:436:6 | xs | semmle.label | xs |
| test.cpp:436:5:436:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:436:5:436:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:436:5:436:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:436:5:436:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:437:9:437:10 | xs | semmle.label | xs |
| test.cpp:438:7:438:11 | access to array | semmle.label | access to array |
| test.cpp:438:7:438:15 | Store: ... = ... | semmle.label | Store: ... = ... |
| test.cpp:444:14:444:27 | new[] | semmle.label | new[] |
| test.cpp:445:15:445:23 | & ... | semmle.label | & ... |
| test.cpp:445:15:445:23 | & ... | semmle.label | & ... |
| test.cpp:445:15:445:23 | & ... | semmle.label | & ... |
| test.cpp:445:15:445:23 | & ... | semmle.label | & ... |
| test.cpp:445:16:445:17 | xs | semmle.label | xs |
| test.cpp:445:16:445:23 | access to array | semmle.label | access to array |
| test.cpp:445:16:445:23 | access to array | semmle.label | access to array |
| test.cpp:446:3:446:5 | end | semmle.label | end |
| test.cpp:448:5:448:6 | xs | semmle.label | xs |
| test.cpp:448:5:448:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:448:5:448:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:448:5:448:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:448:5:448:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:449:9:449:10 | xs | semmle.label | xs |
| test.cpp:450:7:450:11 | access to array | semmle.label | access to array |
| test.cpp:450:7:450:15 | Store: ... = ... | semmle.label | Store: ... = ... |
| test.cpp:456:14:456:31 | new[] | semmle.label | new[] |
| test.cpp:457:16:457:17 | xs | semmle.label | xs |
| test.cpp:460:5:460:6 | xs | semmle.label | xs |
| test.cpp:468:14:468:27 | new[] | semmle.label | new[] |
| test.cpp:469:16:469:17 | xs | semmle.label | xs |
| test.cpp:472:5:472:6 | xs | semmle.label | xs |
| test.cpp:480:14:480:27 | new[] | semmle.label | new[] |
| test.cpp:481:15:481:23 | & ... | semmle.label | & ... |
| test.cpp:481:15:481:23 | & ... | semmle.label | & ... |
| test.cpp:481:15:481:23 | & ... | semmle.label | & ... |
| test.cpp:481:15:481:23 | & ... | semmle.label | & ... |
| test.cpp:481:16:481:17 | xs | semmle.label | xs |
| test.cpp:481:16:481:23 | access to array | semmle.label | access to array |
| test.cpp:481:16:481:23 | access to array | semmle.label | access to array |
| test.cpp:482:3:482:5 | end | semmle.label | end |
| test.cpp:484:5:484:6 | xs | semmle.label | xs |
| test.cpp:484:5:484:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:484:5:484:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:484:5:484:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:484:5:484:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:485:9:485:10 | xs | semmle.label | xs |
| test.cpp:486:7:486:11 | access to array | semmle.label | access to array |
| test.cpp:486:7:486:15 | Store: ... = ... | semmle.label | Store: ... = ... |
| test.cpp:499:3:499:25 | ... = ... | semmle.label | ... = ... |
| test.cpp:499:7:499:8 | val indirection [post update] [xs] | semmle.label | val indirection [post update] [xs] |
| test.cpp:499:12:499:25 | new[] | semmle.label | new[] |
| test.cpp:500:3:500:5 | val indirection [xs] | semmle.label | val indirection [xs] |
| test.cpp:500:7:500:8 | xs | semmle.label | xs |
| test.cpp:500:7:500:8 | xs indirection | semmle.label | xs indirection |
| test.cpp:510:16:510:33 | new[] | semmle.label | new[] |
| test.cpp:512:7:512:8 | xs | semmle.label | xs |
| test.cpp:520:14:520:27 | new[] | semmle.label | new[] |
| test.cpp:526:5:526:6 | xs | semmle.label | xs |
| test.cpp:532:14:532:27 | new[] | semmle.label | new[] |
| test.cpp:537:5:537:6 | xs | semmle.label | xs |
| test.cpp:543:14:543:27 | new[] | semmle.label | new[] |
| test.cpp:548:5:548:6 | xs | semmle.label | xs |
| test.cpp:548:5:548:15 | access to array | semmle.label | access to array |
| test.cpp:548:5:548:19 | Store: ... = ... | semmle.label | Store: ... = ... |
| test.cpp:554:14:554:27 | new[] | semmle.label | new[] |
| test.cpp:559:5:559:6 | xs | semmle.label | xs |
| test.cpp:559:5:559:15 | access to array | semmle.label | access to array |
| test.cpp:559:5:559:19 | Store: ... = ... | semmle.label | Store: ... = ... |
| test.cpp:565:14:565:27 | new[] | semmle.label | new[] |
| test.cpp:570:5:570:6 | xs | semmle.label | xs |
| test.cpp:576:14:576:27 | new[] | semmle.label | new[] |
| test.cpp:581:5:581:6 | xs | semmle.label | xs |
| test.cpp:587:14:587:31 | new[] | semmle.label | new[] |
| test.cpp:592:5:592:6 | xs | semmle.label | xs |
| test.cpp:598:14:598:31 | new[] | semmle.label | new[] |
| test.cpp:603:5:603:6 | xs | semmle.label | xs |
| test.cpp:609:14:609:31 | new[] | semmle.label | new[] |
| test.cpp:614:5:614:6 | xs | semmle.label | xs |
| test.cpp:620:14:620:31 | new[] | semmle.label | new[] |
| test.cpp:625:5:625:6 | xs | semmle.label | xs |
| test.cpp:631:14:631:31 | new[] | semmle.label | new[] |
| test.cpp:636:5:636:6 | xs | semmle.label | xs |
| test.cpp:642:14:642:31 | new[] | semmle.label | new[] |
| test.cpp:647:5:647:6 | xs | semmle.label | xs |
| test.cpp:647:5:647:15 | access to array | semmle.label | access to array |
| test.cpp:647:5:647:19 | Store: ... = ... | semmle.label | Store: ... = ... |
| test.cpp:652:14:652:27 | new[] | semmle.label | new[] |
| test.cpp:653:16:653:17 | xs | semmle.label | xs |
| test.cpp:656:3:656:4 | xs | semmle.label | xs |
| test.cpp:656:3:656:6 | ... ++ | semmle.label | ... ++ |
| test.cpp:656:3:656:6 | ... ++ | semmle.label | ... ++ |
| test.cpp:656:3:656:6 | ... ++ | semmle.label | ... ++ |
| test.cpp:656:3:656:6 | ... ++ | semmle.label | ... ++ |
| test.cpp:657:7:657:8 | xs | semmle.label | xs |
| test.cpp:662:3:662:11 | Store: ... = ... | semmle.label | Store: ... = ... |
| test.cpp:667:14:667:31 | new[] | semmle.label | new[] |
| test.cpp:675:7:675:8 | xs | semmle.label | xs |
| test.cpp:675:7:675:19 | access to array | semmle.label | access to array |
| test.cpp:675:7:675:23 | Store: ... = ... | semmle.label | Store: ... = ... |
subpaths
#select
| test.cpp:6:14:6:15 | Load: * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:6:14:6:15 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:4:15:4:20 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size |
@@ -1118,8 +1556,16 @@ subpaths
| test.cpp:264:13:264:14 | Load: * ... | test.cpp:260:13:260:24 | new[] | test.cpp:264:13:264:14 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:260:13:260:24 | new[] | new[] | test.cpp:261:19:261:21 | len | len |
| test.cpp:274:5:274:10 | Store: ... = ... | test.cpp:270:13:270:24 | new[] | test.cpp:274:5:274:10 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:270:13:270:24 | new[] | new[] | test.cpp:271:19:271:21 | len | len |
| test.cpp:308:5:308:29 | Store: ... = ... | test.cpp:304:15:304:26 | new[] | test.cpp:308:5:308:29 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:304:15:304:26 | new[] | new[] | test.cpp:308:8:308:10 | ... + ... | ... + ... |
| test.cpp:350:15:350:19 | Load: * ... | test.cpp:347:14:347:27 | new[] | test.cpp:350:15:350:19 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:347:14:347:27 | new[] | new[] | test.cpp:348:20:348:23 | size | size |
| test.cpp:358:14:358:26 | Load: * ... | test.cpp:355:14:355:27 | new[] | test.cpp:358:14:358:26 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:355:14:355:27 | new[] | new[] | test.cpp:356:20:356:23 | size | size |
| test.cpp:359:14:359:32 | Load: * ... | test.cpp:355:14:355:27 | new[] | test.cpp:359:14:359:32 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 2. | test.cpp:355:14:355:27 | new[] | new[] | test.cpp:356:20:356:23 | size | size |
| test.cpp:372:15:372:16 | Load: * ... | test.cpp:363:14:363:27 | new[] | test.cpp:372:15:372:16 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:363:14:363:27 | new[] | new[] | test.cpp:365:19:365:22 | size | size |
| test.cpp:384:13:384:16 | Load: * ... | test.cpp:377:14:377:27 | new[] | test.cpp:384:13:384:16 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:377:14:377:27 | new[] | new[] | test.cpp:378:20:378:23 | size | size |
| test.cpp:415:7:415:15 | Store: ... = ... | test.cpp:410:14:410:27 | new[] | test.cpp:415:7:415:15 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:410:14:410:27 | new[] | new[] | test.cpp:411:19:411:22 | size | size |
| test.cpp:426:7:426:15 | Store: ... = ... | test.cpp:421:14:421:27 | new[] | test.cpp:426:7:426:15 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:421:14:421:27 | new[] | new[] | test.cpp:422:19:422:22 | size | size |
| test.cpp:438:7:438:15 | Store: ... = ... | test.cpp:432:14:432:27 | new[] | test.cpp:438:7:438:15 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:432:14:432:27 | new[] | new[] | test.cpp:433:19:433:22 | size | size |
| test.cpp:450:7:450:15 | Store: ... = ... | test.cpp:444:14:444:27 | new[] | test.cpp:450:7:450:15 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:444:14:444:27 | new[] | new[] | test.cpp:445:19:445:22 | size | size |
| test.cpp:486:7:486:15 | Store: ... = ... | test.cpp:480:14:480:27 | new[] | test.cpp:486:7:486:15 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@ + 498. | test.cpp:480:14:480:27 | new[] | new[] | test.cpp:481:19:481:22 | size | size |
| test.cpp:548:5:548:19 | Store: ... = ... | test.cpp:543:14:543:27 | new[] | test.cpp:548:5:548:19 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:543:14:543:27 | new[] | new[] | test.cpp:548:8:548:14 | src_pos | src_pos |
| test.cpp:559:5:559:19 | Store: ... = ... | test.cpp:554:14:554:27 | new[] | test.cpp:559:5:559:19 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:554:14:554:27 | new[] | new[] | test.cpp:559:8:559:14 | src_pos | src_pos |
| test.cpp:647:5:647:19 | Store: ... = ... | test.cpp:642:14:642:31 | new[] | test.cpp:647:5:647:19 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:642:14:642:31 | new[] | new[] | test.cpp:647:8:647:14 | src_pos | src_pos |
| test.cpp:662:3:662:11 | Store: ... = ... | test.cpp:652:14:652:27 | new[] | test.cpp:662:3:662:11 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:652:14:652:27 | new[] | new[] | test.cpp:653:19:653:22 | size | size |
| test.cpp:675:7:675:23 | Store: ... = ... | test.cpp:667:14:667:31 | new[] | test.cpp:675:7:675:23 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:667:14:667:31 | new[] | new[] | test.cpp:675:10:675:18 | ... ++ | ... ++ |

View File

@@ -347,7 +347,7 @@ void test24(unsigned size) {
char *xs = new char[size];
char *end = xs + size;
if (xs < end) {
int val = *xs++; // GOOD [FALSE POSITIVE]
int val = *xs++; // GOOD
}
}
@@ -369,7 +369,7 @@ void test26(unsigned size) {
}
if (p < end) {
int val = *p; // GOOD [FALSE POSITIVE]
int val = *p; // GOOD
}
}
@@ -383,3 +383,295 @@ void test27(unsigned size, bool b) {
int val = *end; // BAD
}
void test28(unsigned size) {
char *xs = new char[size];
char *end = &xs[size];
if (xs >= end)
return;
xs++;
if (xs >= end)
return;
xs[0] = 0; // GOOD
}
void test28_simple(unsigned size) {
char *xs = new char[size];
char *end = &xs[size];
if (xs < end) {
xs++;
if (xs < end) {
xs[0] = 0; // GOOD
}
}
}
void test28_simple2(unsigned size) {
char *xs = new char[size];
char *end = &xs[size];
if (xs < end) {
xs++;
if (xs < end + 1) {
xs[0] = 0; // BAD
}
}
}
void test28_simple3(unsigned size) {
char *xs = new char[size];
char *end = &xs[size];
if (xs < end) {
xs++;
if (xs - 1 < end) {
xs[0] = 0; // BAD
}
}
}
void test28_simple4(unsigned size) {
char *xs = new char[size];
char *end = &xs[size];
if (xs < end) {
end++;
xs++;
if (xs < end) {
xs[0] = 0; // BAD
}
}
}
void test28_simple5(unsigned size) {
char *xs = new char[size];
char *end = &xs[size];
end++;
if (xs < end) {
xs++;
if (xs < end) {
xs[0] = 0; // BAD
}
}
}
void test28_simple6(unsigned size) {
char *xs = new char[size + 1];
char *end = &xs[size];
end++;
if (xs < end) {
xs++;
if (xs < end) {
xs[0] = 0; // GOOD
}
}
}
void test28_simple7(unsigned size) {
char *xs = new char[size];
char *end = &xs[size];
end++;
if (xs < end) {
xs++;
if (xs < end - 1) {
xs[0] = 0; // GOOD
}
}
}
void test28_simple8(unsigned size) {
char *xs = new char[size];
char *end = &xs[size];
end += 500;
if (xs < end) {
xs++;
if (xs < end - 1) {
xs[0] = 0; // BAD
}
}
}
struct test29_struct {
char* xs;
};
void test29(unsigned size) {
test29_struct val;
val.xs = new char[size];
size++;
val.xs = new char[size];
val.xs[size - 1] = 0; // GOOD
}
void test30(int *size)
{
int new_size = 0, tmp_size = 0;
test30(&tmp_size);
if (tmp_size + 1 > new_size) {
new_size = tmp_size + 1;
char *xs = new char[new_size];
for (int i = 0; i < new_size; i++) {
xs[i] = 0; // GOOD
}
}
*size = new_size;
}
void test31(unsigned size, unsigned src_pos)
{
char *xs = new char[size];
if (src_pos > size) {
src_pos = size;
}
unsigned dst_pos = src_pos;
if (dst_pos < size - 3) {
xs[dst_pos++] = 0; // GOOD
}
}
void test31_simple1(unsigned size, unsigned src_pos)
{
char *xs = new char[size];
if (src_pos > size) {
src_pos = size;
}
if (src_pos < size) {
xs[src_pos] = 0; // GOOD
}
}
void test31_simple2(unsigned size, unsigned src_pos)
{
char *xs = new char[size];
if (src_pos > size) {
src_pos = size;
}
if (src_pos < size + 1) {
xs[src_pos] = 0; // BAD
}
}
void test31_simple3(unsigned size, unsigned src_pos)
{
char *xs = new char[size];
if (src_pos > size) {
src_pos = size;
}
if (src_pos - 1 < size) {
xs[src_pos] = 0; // BAD
}
}
void test31_simple4(unsigned size, unsigned src_pos)
{
char *xs = new char[size];
if (src_pos > size) {
src_pos = size;
}
if (src_pos < size - 1) {
xs[src_pos] = 0; // GOOD
}
}
void test31_simple5(unsigned size, unsigned src_pos)
{
char *xs = new char[size];
if (src_pos > size) {
src_pos = size;
}
if (src_pos + 1 < size) {
xs[src_pos] = 0; // GOOD
}
}
void test31_simple1_plus1(unsigned size, unsigned src_pos)
{
char *xs = new char[size + 1];
if (src_pos > size) {
src_pos = size;
}
if (src_pos < size) {
xs[src_pos] = 0; // GOOD
}
}
void test31_simple2_plus1(unsigned size, unsigned src_pos)
{
char *xs = new char[size + 1];
if (src_pos > size) {
src_pos = size;
}
if (src_pos < size + 1) {
xs[src_pos] = 0; // GOOD
}
}
void test31_simple3_plus1(unsigned size, unsigned src_pos)
{
char *xs = new char[size + 1];
if (src_pos > size) {
src_pos = size;
}
if (src_pos - 1 < size) {
xs[src_pos] = 0; // GOOD
}
}
void test31_simple4_plus1(unsigned size, unsigned src_pos)
{
char *xs = new char[size + 1];
if (src_pos > size) {
src_pos = size;
}
if (src_pos < size - 1) {
xs[src_pos] = 0; // GOOD
}
}
void test31_simple5_plus1(unsigned size, unsigned src_pos)
{
char *xs = new char[size + 1];
if (src_pos > size) {
src_pos = size;
}
if (src_pos + 1 < size) {
xs[src_pos] = 0; // GOOD
}
}
void test31_simple1_sub1(unsigned size, unsigned src_pos)
{
char *xs = new char[size - 1];
if (src_pos > size) {
src_pos = size;
}
if (src_pos < size) {
xs[src_pos] = 0; // BAD
}
}
void test32(unsigned size) {
char *xs = new char[size];
char *end = &xs[size];
if (xs >= end)
return;
xs++;
if (xs >= end)
return;
xs++;
if (xs >= end)
return;
xs[0] = 0; // GOOD [FALSE POSITIVE]
}
void test33(unsigned size, unsigned src_pos)
{
char *xs = new char[size + 1];
if (src_pos > size) {
src_pos = size;
}
unsigned dst_pos = src_pos;
while (dst_pos < size - 1) {
dst_pos++;
if (true)
xs[dst_pos++] = 0; // GOOD [FALSE POSITIVE]
}
}

View File

@@ -67,6 +67,8 @@ postWithInFlow
| ref.cpp:109:9:109:11 | val [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:113:11:113:13 | val [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:115:11:115:13 | val [post update] | PostUpdateNode should not be the target of local flow. |
| self_parameter_flow.cpp:3:4:3:5 | ps [inner post update] | PostUpdateNode should not be the target of local flow. |
| self_parameter_flow.cpp:8:9:8:9 | s [inner post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:91:3:91:9 | source1 [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:115:3:115:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:115:4:115:6 | out [inner post update] | PostUpdateNode should not be the target of local flow. |
@@ -128,6 +130,10 @@ postWithInFlow
| test.cpp:690:3:690:3 | s [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:694:4:694:6 | buf [inner post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:704:23:704:25 | buf [inner post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:715:25:715:25 | c [inner post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:728:3:728:4 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:728:4:728:4 | p [inner post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:734:41:734:41 | x [inner post update] | PostUpdateNode should not be the target of local flow. |
viableImplInCallContextTooLarge
uniqueParameterNodeAtPosition
uniqueParameterNodePosition

View File

@@ -0,0 +1,21 @@
#include "../../../include/iterator.h"
int source();
template<typename T>
void sink(T);
template<> struct std::iterator_traits<unsigned long>
{ // get traits from integer type
typedef std::input_iterator_tag iterator_category;
typedef unsigned long value_type;
typedef unsigned long difference_type;
typedef unsigned long distance_type;
typedef unsigned long * pointer;
typedef unsigned long& reference;
};
int test() {
unsigned long x = source();
sink(x); // $ ast ir
}

View File

@@ -0,0 +1,14 @@
void incr(unsigned char **ps) // $ ast-def=ps ir-def=*ps ir-def=**ps
{
*ps += 1;
}
void callincr(unsigned char *s) // $ ast-def=s
{
incr(&s);
}
void test(unsigned char *s) // $ ast-def=s
{
callincr(s); // $ flow
}

View File

@@ -702,4 +702,90 @@ void call_increment_buf(int** buf) { // $ ast-def=buf
void test_conflation_regression(int* source) { // $ ast-def=source
int* buf = source;
call_increment_buf(&buf);
}
void write_to_star_star_p(unsigned char **p) // $ ast-def=p ir-def=**p ir-def=*p
{
**p = 0;
}
void write_to_star_buf(unsigned char *buf) // $ ast-def=buf
{
unsigned char *c = buf;
write_to_star_star_p(&c);
}
void test_write_to_star_buf(unsigned char *source) // $ ast-def=source
{
write_to_star_buf(source);
sink(*source); // clean
}
void does_not_write_source_to_dereference(int *p) // $ ast-def=p ir-def=*p
{
int x = source();
p = &x;
*p = 42;
}
void test_does_not_write_source_to_dereference()
{
int x;
does_not_write_source_to_dereference(&x);
sink(x); // $ ast,ir=733:7 SPURIOUS: ast,ir=726:11
}
void sometimes_calls_sink_eq(int x, int n) {
if(n == 0) {
sink(x); // $ ast,ir=751:27 ast,ir=755:32 SPURIOUS: ast=749:27 ast,ir=753:32 // IR spurious results because we only have call contexts of depth 1
}
}
void call_sometimes_calls_sink_eq(int x, int n) {
sometimes_calls_sink_eq(x, n);
}
void test_sometimes_calls_sink_eq_1() {
sometimes_calls_sink_eq(source(), 1);
sometimes_calls_sink_eq(0, 0);
sometimes_calls_sink_eq(source(), 0);
call_sometimes_calls_sink_eq(source(), 1);
call_sometimes_calls_sink_eq(0, 0);
call_sometimes_calls_sink_eq(source(), 0);
}
void sometimes_calls_sink_lt(int x, int n) {
if(n < 10) {
sink(x); // $ ast,ir=771:27 ast,ir=775:32 SPURIOUS: ast=769:27 ast,ir=773:32 // IR spurious results because we only have call contexts of depth 1
}
}
void call_sometimes_calls_sink_lt(int x, int n) {
sometimes_calls_sink_lt(x, n);
}
void test_sometimes_calls_sink_lt() {
sometimes_calls_sink_lt(source(), 10);
sometimes_calls_sink_lt(0, 0);
sometimes_calls_sink_lt(source(), 2);
call_sometimes_calls_sink_lt(source(), 10);
call_sometimes_calls_sink_lt(0, 0);
call_sometimes_calls_sink_lt(source(), 2);
}
void sometimes_calls_sink_switch(int x, int n) {
switch(n) {
case 0:
sink(x); // $ ast,ir=790:31 SPURIOUS: ast,ir=788:31 // IR spurious results because IRGuard doesn't understand switch statements.
break;
}
}
void test_sometimes_calls_sink_switch() {
sometimes_calls_sink_switch(source(), 1);
sometimes_calls_sink_switch(0, 0);
sometimes_calls_sink_switch(source(), 0);
}

View File

@@ -0,0 +1,2 @@
failures
testFailures

View File

@@ -0,0 +1,34 @@
import cpp
import semmle.code.cpp.dataflow.new.DataFlow
import TestUtilities.InlineExpectationsTest
module TestConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.getLocation().getFile().getBaseName() = "self_parameter_flow.cpp" and
source.asIndirectArgument() =
any(Call call | call.getTarget().hasName("callincr")).getAnArgument()
}
predicate isSink(DataFlow::Node sink) {
sink.asDefiningArgument() =
any(Call call | call.getTarget().hasName("callincr")).getAnArgument()
}
}
import DataFlow::Global<TestConfig>
module TestSelfParameterFlow implements TestSig {
string getARelevantTag() { result = "flow" }
predicate hasActualResult(Location location, string element, string tag, string value) {
exists(DataFlow::Node sink |
flowTo(sink) and
location = sink.getLocation() and
element = sink.toString() and
tag = "flow" and
value = ""
)
}
}
import MakeTest<TestSelfParameterFlow>

View File

@@ -42,3 +42,5 @@
| test.cpp:551:9:551:9 | y | test.cpp:552:28:552:28 | y |
| test.cpp:595:8:595:9 | xs | test.cpp:596:3:596:4 | xs |
| test.cpp:595:8:595:9 | xs | test.cpp:597:9:597:10 | xs |
| test.cpp:733:7:733:7 | x | test.cpp:734:41:734:41 | x |
| test.cpp:733:7:733:7 | x | test.cpp:735:8:735:8 | x |

View File

@@ -0,0 +1,182 @@
// We want a source of user input that can be both a pointer and a non-pointer. So we
// hack the testing a bit by providing an overload that takes a boolean to distinguish
// between the two while still satisfying the test requirement that the function must
// be named `user_input`.
int user_input();
int* user_input(bool);
void sink(...);
void argument_source(int*);
struct S {
int** x;
};
void test()
{
{
S s;
**s.x = user_input();
*s.x = 0;
sink(**s.x); // clean, as *s.x was overwritten and that contains the tainted **s.x
}
{
S s;
**s.x = user_input();
**s.x = 0;
sink(**s.x); // clean, as **s.x was overwritten and tainted
}
{
S s;
*s.x = user_input(true);
**s.x = 0;
sink(*s.x); // $ ir // not clean, as **s.x was overwritten and is neither equal nor contains the tainted *s.x
}
{
S s;
*s.x = user_input(true);
s.x = 0;
sink(*s.x); // clean, as s.x was overwritten and contains the tainted *s.x
}
{
S s;
**s.x = user_input();
s.x = 0;
sink(*s.x); // clean, as s.x was overwritten and contains the tainted **s.x
}
{
S s;
*s.x = user_input(true);
s.x++;
sink(s.x); // $ SPURIOUS: ir ast // Cannot tell the difference with the whole array being tainted
}
{
S s;
**s.x = user_input();
s.x++;
sink(s.x); // $ SPURIOUS: ir // Cannot tell the difference with the whole array being tainted
}
}
struct S2
{
int* val;
};
void test_uncertain_write_is_not_clear()
{
S2 s;
argument_source(s.val);
s.val[10] = 0;
sink(*s.val); // $ ir MISSING: ast // not clean, as all elements of s.val are tainted and only one is overwitten
}
void test_indirection_should_not_be_cleared_with_write_1() {
S2 s;
argument_source(s.val); // *s.val is tainted
s.val[0] = 0;
s.val = s.val + 1;
sink(*s.val); // $ ir MISSING: ast // not clean, as all elements of s.val are tainted, only one if overwritten, and the updated pointer still points to tainted elements
}
void test_indirection_should_not_be_cleared_with_write_2() {
S2 s;
argument_source(s.val); // *s.val is tainted
*s.val++ = 0;
sink(*s.val); // $ ir MISSING: ast // not clean, as all elements of s.val are tainted, only one if overwritten, and the updated pointer still points to tainted elements
}
void test_indirection_should_not_be_cleared_without_write_1() {
S2 s;
argument_source(s.val); // *s.val is tainted
s.val = s.val + 1;
sink(*s.val); // $ ir MISSING: ast // not clean, as all elements of s.val are tainted and the updated pointer still points to tainted elements
}
void test_indirection_should_not_be_cleared_without_write_2() {
S2 s;
argument_source(s.val); // *s.val is tainted
s.val++;
sink(*s.val); // $ ir MISSING: ast // not clean, as all elements of s.val are tainted and the updated pointer still points to tainted elements
}
void test_indirection_should_not_be_cleared_without_write_3() {
S2 s;
argument_source(s.val); // *s.val is tainted
++s.val;
sink(*s.val); // $ ir MISSING: ast // not clean as the pointer is only moved to the next tainted element
}
void test_indirection_should_not_be_cleared_without_write_4() {
S2 s;
argument_source(s.val); // *s.val is tainted
s.val += 1;
sink(*s.val); // $ ir MISSING: ast // not clean as the pointer is only moved to the next tainted element
}
void test_direct_should_be_cleared() {
S2 s;
s.val = user_input(true); // s.val is tainted
s.val += 1;
sink(s.val); // $ SPURIOUS: ast // clean, as s.val was overwritten and tainted
}
void test_direct_should_be_cleared_post() {
S2 s;
s.val = user_input(true); // s.val is tainted
s.val++;
sink(s.val); // $ SPURIOUS: ast // clean, as s.val was overwritten and tainted
}
void test_direct_should_be_cleared_pre() {
S2 s;
s.val = user_input(true); // s.val is tainted
++s.val;
sink(s.val); // $ SPURIOUS: ast // // clean, as s.x was overwritten and tainted
}
struct S3
{
int val;
};
void test_direct() {
{
S3 s;
s.val = user_input();
sink(s.val); // $ ir ast
}
{
S3 s;
s.val = user_input();
s.val = 0;
sink(s.val); // $ SPURIOUS: ast // clean
}
{
S3 s;
s.val = user_input();
s.val++;
sink(s.val); // $ SPURIOUS: ast // clean
}
{
S3 s;
s.val = user_input();
s.val += 1;
sink(s.val); // $ SPURIOUS: ast // clean
}
{
S3 s;
s.val = user_input();
s.val = s.val + 1;
sink(s.val); // $ SPURIOUS: ast // clean
}
}

View File

@@ -43,6 +43,9 @@ argHasPostUpdate
| arrays.cpp:10:8:10:15 | * ... | ArgumentNode is missing PostUpdateNode. |
| arrays.cpp:16:8:16:13 | access to array | ArgumentNode is missing PostUpdateNode. |
| arrays.cpp:17:8:17:13 | access to array | ArgumentNode is missing PostUpdateNode. |
| clearning.cpp:34:8:34:11 | * ... | ArgumentNode is missing PostUpdateNode. |
| clearning.cpp:41:8:41:11 | * ... | ArgumentNode is missing PostUpdateNode. |
| clearning.cpp:48:8:48:11 | * ... | ArgumentNode is missing PostUpdateNode. |
postWithInFlow
| A.cpp:25:13:25:13 | c [post update] | PostUpdateNode should not be the target of local flow. |
| A.cpp:27:28:27:28 | c [post update] | PostUpdateNode should not be the target of local flow. |
@@ -123,6 +126,32 @@ postWithInFlow
| by_reference.cpp:108:24:108:24 | a [inner post update] | PostUpdateNode should not be the target of local flow. |
| by_reference.cpp:123:28:123:36 | inner_ptr [inner post update] | PostUpdateNode should not be the target of local flow. |
| by_reference.cpp:127:30:127:38 | inner_ptr [inner post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:19:3:19:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:19:6:19:6 | x [inner post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:32:3:32:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:32:6:32:6 | x [inner post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:39:3:39:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:39:6:39:6 | x [inner post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:40:5:40:5 | x [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:47:5:47:5 | x [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:53:3:53:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:53:6:53:6 | x [inner post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:75:2:75:10 | access to array [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:75:4:75:6 | val [inner post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:82:2:82:9 | access to array [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:82:4:82:6 | val [inner post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:83:7:83:9 | val [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:97:4:97:6 | val [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:124:4:124:6 | val [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:131:4:131:6 | val [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:138:4:138:6 | val [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:151:5:151:7 | val [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:157:5:157:7 | val [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:158:5:158:7 | val [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:164:5:164:7 | val [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:171:5:171:7 | val [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:178:5:178:7 | val [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:179:5:179:7 | val [post update] | PostUpdateNode should not be the target of local flow. |
| complex.cpp:11:22:11:23 | a_ [post update] | PostUpdateNode should not be the target of local flow. |
| complex.cpp:12:22:12:23 | b_ [post update] | PostUpdateNode should not be the target of local flow. |
| conflated.cpp:10:3:10:7 | * ... [post update] | PostUpdateNode should not be the target of local flow. |

View File

@@ -19,6 +19,17 @@ uniquePostUpdate
| aliasing.cpp:77:11:77:11 | definition of w indirection | Node has multiple PostUpdateNodes. |
| aliasing.cpp:84:11:84:11 | definition of w indirection | Node has multiple PostUpdateNodes. |
| aliasing.cpp:91:11:91:11 | definition of w indirection | Node has multiple PostUpdateNodes. |
| clearning.cpp:54:3:54:3 | s indirection | Node has multiple PostUpdateNodes. |
| clearning.cpp:61:3:61:3 | s indirection | Node has multiple PostUpdateNodes. |
| clearning.cpp:90:3:90:3 | s indirection | Node has multiple PostUpdateNodes. |
| clearning.cpp:104:2:104:2 | s indirection | Node has multiple PostUpdateNodes. |
| clearning.cpp:111:4:111:4 | s indirection | Node has multiple PostUpdateNodes. |
| clearning.cpp:118:2:118:2 | s indirection | Node has multiple PostUpdateNodes. |
| clearning.cpp:125:2:125:2 | s indirection | Node has multiple PostUpdateNodes. |
| clearning.cpp:132:2:132:2 | s indirection | Node has multiple PostUpdateNodes. |
| clearning.cpp:139:4:139:4 | s indirection | Node has multiple PostUpdateNodes. |
| clearning.cpp:165:3:165:3 | s indirection | Node has multiple PostUpdateNodes. |
| clearning.cpp:172:3:172:3 | s indirection | Node has multiple PostUpdateNodes. |
| complex.cpp:22:3:22:5 | this indirection | Node has multiple PostUpdateNodes. |
| complex.cpp:25:7:25:7 | this indirection | Node has multiple PostUpdateNodes. |
| complex.cpp:42:10:42:14 | inner indirection | Node has multiple PostUpdateNodes. |

View File

@@ -572,6 +572,136 @@ edges
| by_reference.cpp:136:8:136:13 | pouter indirection [a] | by_reference.cpp:136:16:136:16 | a |
| by_reference.cpp:136:8:136:13 | pouter indirection [a] | by_reference.cpp:136:16:136:16 | a indirection |
| by_reference.cpp:136:16:136:16 | a indirection | by_reference.cpp:136:16:136:16 | a |
| clearning.cpp:32:3:32:25 | ... = ... | clearning.cpp:32:6:32:6 | s indirection [post update] [x indirection] |
| clearning.cpp:32:6:32:6 | s indirection [post update] [x indirection] | clearning.cpp:33:5:33:5 | s indirection [x indirection] |
| clearning.cpp:32:10:32:19 | call to user_input | clearning.cpp:32:3:32:25 | ... = ... |
| clearning.cpp:33:5:33:5 | s indirection [x indirection] | clearning.cpp:34:9:34:9 | s indirection [x indirection] |
| clearning.cpp:34:9:34:9 | s indirection [x indirection] | clearning.cpp:34:8:34:11 | * ... |
| clearning.cpp:34:9:34:9 | s indirection [x indirection] | clearning.cpp:34:11:34:11 | x indirection |
| clearning.cpp:34:9:34:9 | s indirection [x indirection] | clearning.cpp:34:11:34:11 | x indirection |
| clearning.cpp:34:11:34:11 | x indirection | clearning.cpp:34:8:34:11 | * ... |
| clearning.cpp:34:11:34:11 | x indirection | clearning.cpp:34:8:34:11 | * ... |
| clearning.cpp:53:3:53:25 | ... = ... | clearning.cpp:53:6:53:6 | s indirection [post update] [x indirection] |
| clearning.cpp:53:6:53:6 | s indirection [post update] [x indirection] | clearning.cpp:54:3:54:3 | s indirection [x indirection] |
| clearning.cpp:53:10:53:19 | call to user_input | clearning.cpp:53:3:53:25 | ... = ... |
| clearning.cpp:54:3:54:3 | s indirection [x indirection] | clearning.cpp:54:3:54:7 | ... ++ indirection |
| clearning.cpp:54:3:54:3 | s indirection [x indirection] | clearning.cpp:54:5:54:5 | x indirection |
| clearning.cpp:54:3:54:3 | s indirection [x indirection] | clearning.cpp:55:8:55:8 | s indirection [x indirection] |
| clearning.cpp:54:3:54:7 | ... ++ indirection | clearning.cpp:54:3:54:7 | ... ++ indirection |
| clearning.cpp:54:3:54:7 | ... ++ indirection | clearning.cpp:54:5:54:5 | s indirection [post update] [x indirection] |
| clearning.cpp:54:5:54:5 | s indirection [post update] [x indirection] | clearning.cpp:55:8:55:8 | s indirection [x indirection] |
| clearning.cpp:54:5:54:5 | x indirection | clearning.cpp:54:3:54:7 | ... ++ indirection |
| clearning.cpp:55:8:55:8 | s indirection [x indirection] | clearning.cpp:55:10:55:10 | x indirection |
| clearning.cpp:55:8:55:8 | s indirection [x indirection] | clearning.cpp:55:10:55:10 | x indirection |
| clearning.cpp:55:10:55:10 | x indirection | clearning.cpp:55:10:55:10 | x indirection |
| clearning.cpp:60:3:60:22 | ... = ... | clearning.cpp:60:7:60:7 | s indirection [post update] [x indirection] |
| clearning.cpp:60:7:60:7 | s indirection [post update] [x indirection] | clearning.cpp:61:3:61:3 | s indirection [x indirection] |
| clearning.cpp:60:11:60:20 | call to user_input | clearning.cpp:60:3:60:22 | ... = ... |
| clearning.cpp:61:3:61:3 | s indirection [x indirection] | clearning.cpp:61:3:61:7 | ... ++ indirection |
| clearning.cpp:61:3:61:3 | s indirection [x indirection] | clearning.cpp:61:5:61:5 | x indirection |
| clearning.cpp:61:3:61:3 | s indirection [x indirection] | clearning.cpp:62:8:62:8 | s indirection [x indirection] |
| clearning.cpp:61:3:61:7 | ... ++ indirection | clearning.cpp:61:3:61:7 | ... ++ indirection |
| clearning.cpp:61:3:61:7 | ... ++ indirection | clearning.cpp:61:5:61:5 | s indirection [post update] [x indirection] |
| clearning.cpp:61:5:61:5 | s indirection [post update] [x indirection] | clearning.cpp:62:8:62:8 | s indirection [x indirection] |
| clearning.cpp:61:5:61:5 | x indirection | clearning.cpp:61:3:61:7 | ... ++ indirection |
| clearning.cpp:62:8:62:8 | s indirection [x indirection] | clearning.cpp:62:10:62:10 | x indirection |
| clearning.cpp:62:8:62:8 | s indirection [x indirection] | clearning.cpp:62:10:62:10 | x indirection |
| clearning.cpp:62:10:62:10 | x indirection | clearning.cpp:62:10:62:10 | x indirection |
| clearning.cpp:74:20:74:22 | argument_source output argument | clearning.cpp:74:20:74:22 | s indirection [post update] [val indirection] |
| clearning.cpp:74:20:74:22 | s indirection [post update] [val indirection] | clearning.cpp:76:8:76:8 | s indirection [val indirection] |
| clearning.cpp:76:8:76:8 | s indirection [val indirection] | clearning.cpp:76:7:76:12 | * ... |
| clearning.cpp:76:8:76:8 | s indirection [val indirection] | clearning.cpp:76:10:76:12 | val indirection |
| clearning.cpp:76:8:76:8 | s indirection [val indirection] | clearning.cpp:76:10:76:12 | val indirection |
| clearning.cpp:76:10:76:12 | val indirection | clearning.cpp:76:7:76:12 | * ... |
| clearning.cpp:76:10:76:12 | val indirection | clearning.cpp:76:7:76:12 | * ... |
| clearning.cpp:81:20:81:22 | argument_source output argument | clearning.cpp:81:20:81:22 | s indirection [post update] [val indirection] |
| clearning.cpp:81:20:81:22 | s indirection [post update] [val indirection] | clearning.cpp:83:13:83:13 | s indirection [val indirection] |
| clearning.cpp:83:5:83:21 | ... = ... indirection | clearning.cpp:83:7:83:9 | s indirection [post update] [val indirection] |
| clearning.cpp:83:7:83:9 | s indirection [post update] [val indirection] | clearning.cpp:84:8:84:8 | s indirection [val indirection] |
| clearning.cpp:83:13:83:13 | s indirection [val indirection] | clearning.cpp:83:13:83:21 | ... + ... indirection |
| clearning.cpp:83:13:83:13 | s indirection [val indirection] | clearning.cpp:83:15:83:17 | val indirection |
| clearning.cpp:83:13:83:21 | ... + ... indirection | clearning.cpp:83:5:83:21 | ... = ... indirection |
| clearning.cpp:83:15:83:17 | val indirection | clearning.cpp:83:5:83:21 | ... = ... indirection |
| clearning.cpp:84:8:84:8 | s indirection [val indirection] | clearning.cpp:84:7:84:12 | * ... |
| clearning.cpp:84:8:84:8 | s indirection [val indirection] | clearning.cpp:84:10:84:12 | val indirection |
| clearning.cpp:84:8:84:8 | s indirection [val indirection] | clearning.cpp:84:10:84:12 | val indirection |
| clearning.cpp:84:10:84:12 | val indirection | clearning.cpp:84:7:84:12 | * ... |
| clearning.cpp:84:10:84:12 | val indirection | clearning.cpp:84:7:84:12 | * ... |
| clearning.cpp:89:20:89:22 | argument_source output argument | clearning.cpp:89:20:89:22 | s indirection [post update] [val indirection] |
| clearning.cpp:89:20:89:22 | s indirection [post update] [val indirection] | clearning.cpp:90:3:90:3 | s indirection [val indirection] |
| clearning.cpp:90:3:90:3 | s indirection [val indirection] | clearning.cpp:90:3:90:9 | ... ++ indirection |
| clearning.cpp:90:3:90:3 | s indirection [val indirection] | clearning.cpp:90:5:90:7 | val indirection |
| clearning.cpp:90:3:90:3 | s indirection [val indirection] | clearning.cpp:91:8:91:8 | s indirection [val indirection] |
| clearning.cpp:90:3:90:9 | ... ++ indirection | clearning.cpp:90:3:90:9 | ... ++ indirection |
| clearning.cpp:90:3:90:9 | ... ++ indirection | clearning.cpp:90:5:90:7 | s indirection [post update] [val indirection] |
| clearning.cpp:90:5:90:7 | s indirection [post update] [val indirection] | clearning.cpp:91:8:91:8 | s indirection [val indirection] |
| clearning.cpp:90:5:90:7 | val indirection | clearning.cpp:90:3:90:9 | ... ++ indirection |
| clearning.cpp:91:8:91:8 | s indirection [val indirection] | clearning.cpp:91:7:91:12 | * ... |
| clearning.cpp:91:8:91:8 | s indirection [val indirection] | clearning.cpp:91:10:91:12 | val indirection |
| clearning.cpp:91:8:91:8 | s indirection [val indirection] | clearning.cpp:91:10:91:12 | val indirection |
| clearning.cpp:91:10:91:12 | val indirection | clearning.cpp:91:7:91:12 | * ... |
| clearning.cpp:91:10:91:12 | val indirection | clearning.cpp:91:7:91:12 | * ... |
| clearning.cpp:96:20:96:22 | argument_source output argument | clearning.cpp:96:20:96:22 | s indirection [post update] [val indirection] |
| clearning.cpp:96:20:96:22 | s indirection [post update] [val indirection] | clearning.cpp:97:10:97:10 | s indirection [val indirection] |
| clearning.cpp:97:2:97:18 | ... = ... indirection | clearning.cpp:97:4:97:6 | s indirection [post update] [val indirection] |
| clearning.cpp:97:4:97:6 | s indirection [post update] [val indirection] | clearning.cpp:98:8:98:8 | s indirection [val indirection] |
| clearning.cpp:97:10:97:10 | s indirection [val indirection] | clearning.cpp:97:10:97:18 | ... + ... indirection |
| clearning.cpp:97:10:97:10 | s indirection [val indirection] | clearning.cpp:97:12:97:14 | val indirection |
| clearning.cpp:97:10:97:18 | ... + ... indirection | clearning.cpp:97:2:97:18 | ... = ... indirection |
| clearning.cpp:97:12:97:14 | val indirection | clearning.cpp:97:2:97:18 | ... = ... indirection |
| clearning.cpp:98:8:98:8 | s indirection [val indirection] | clearning.cpp:98:7:98:12 | * ... |
| clearning.cpp:98:8:98:8 | s indirection [val indirection] | clearning.cpp:98:10:98:12 | val indirection |
| clearning.cpp:98:8:98:8 | s indirection [val indirection] | clearning.cpp:98:10:98:12 | val indirection |
| clearning.cpp:98:10:98:12 | val indirection | clearning.cpp:98:7:98:12 | * ... |
| clearning.cpp:98:10:98:12 | val indirection | clearning.cpp:98:7:98:12 | * ... |
| clearning.cpp:103:20:103:22 | argument_source output argument | clearning.cpp:103:20:103:22 | s indirection [post update] [val indirection] |
| clearning.cpp:103:20:103:22 | s indirection [post update] [val indirection] | clearning.cpp:104:2:104:2 | s indirection [val indirection] |
| clearning.cpp:104:2:104:2 | s indirection [val indirection] | clearning.cpp:104:2:104:8 | ... ++ indirection |
| clearning.cpp:104:2:104:2 | s indirection [val indirection] | clearning.cpp:104:4:104:6 | val indirection |
| clearning.cpp:104:2:104:2 | s indirection [val indirection] | clearning.cpp:105:8:105:8 | s indirection [val indirection] |
| clearning.cpp:104:2:104:8 | ... ++ indirection | clearning.cpp:104:2:104:8 | ... ++ indirection |
| clearning.cpp:104:2:104:8 | ... ++ indirection | clearning.cpp:104:4:104:6 | s indirection [post update] [val indirection] |
| clearning.cpp:104:4:104:6 | s indirection [post update] [val indirection] | clearning.cpp:105:8:105:8 | s indirection [val indirection] |
| clearning.cpp:104:4:104:6 | val indirection | clearning.cpp:104:2:104:8 | ... ++ indirection |
| clearning.cpp:105:8:105:8 | s indirection [val indirection] | clearning.cpp:105:7:105:12 | * ... |
| clearning.cpp:105:8:105:8 | s indirection [val indirection] | clearning.cpp:105:10:105:12 | val indirection |
| clearning.cpp:105:8:105:8 | s indirection [val indirection] | clearning.cpp:105:10:105:12 | val indirection |
| clearning.cpp:105:10:105:12 | val indirection | clearning.cpp:105:7:105:12 | * ... |
| clearning.cpp:105:10:105:12 | val indirection | clearning.cpp:105:7:105:12 | * ... |
| clearning.cpp:110:20:110:22 | argument_source output argument | clearning.cpp:110:20:110:22 | s indirection [post update] [val indirection] |
| clearning.cpp:110:20:110:22 | s indirection [post update] [val indirection] | clearning.cpp:111:4:111:4 | s indirection [val indirection] |
| clearning.cpp:111:2:111:8 | ++ ... indirection | clearning.cpp:111:2:111:8 | ++ ... indirection |
| clearning.cpp:111:2:111:8 | ++ ... indirection | clearning.cpp:111:6:111:8 | s indirection [post update] [val indirection] |
| clearning.cpp:111:4:111:4 | s indirection [val indirection] | clearning.cpp:111:2:111:8 | ++ ... indirection |
| clearning.cpp:111:4:111:4 | s indirection [val indirection] | clearning.cpp:111:6:111:8 | val indirection |
| clearning.cpp:111:4:111:4 | s indirection [val indirection] | clearning.cpp:112:8:112:8 | s indirection [val indirection] |
| clearning.cpp:111:6:111:8 | s indirection [post update] [val indirection] | clearning.cpp:112:8:112:8 | s indirection [val indirection] |
| clearning.cpp:111:6:111:8 | val indirection | clearning.cpp:111:2:111:8 | ++ ... indirection |
| clearning.cpp:112:8:112:8 | s indirection [val indirection] | clearning.cpp:112:7:112:12 | * ... |
| clearning.cpp:112:8:112:8 | s indirection [val indirection] | clearning.cpp:112:10:112:12 | val indirection |
| clearning.cpp:112:8:112:8 | s indirection [val indirection] | clearning.cpp:112:10:112:12 | val indirection |
| clearning.cpp:112:10:112:12 | val indirection | clearning.cpp:112:7:112:12 | * ... |
| clearning.cpp:112:10:112:12 | val indirection | clearning.cpp:112:7:112:12 | * ... |
| clearning.cpp:117:20:117:22 | argument_source output argument | clearning.cpp:117:20:117:22 | s indirection [post update] [val indirection] |
| clearning.cpp:117:20:117:22 | s indirection [post update] [val indirection] | clearning.cpp:118:2:118:2 | s indirection [val indirection] |
| clearning.cpp:118:2:118:2 | s indirection [val indirection] | clearning.cpp:118:2:118:11 | ... += ... indirection |
| clearning.cpp:118:2:118:2 | s indirection [val indirection] | clearning.cpp:118:4:118:6 | val indirection |
| clearning.cpp:118:2:118:2 | s indirection [val indirection] | clearning.cpp:119:8:119:8 | s indirection [val indirection] |
| clearning.cpp:118:2:118:11 | ... += ... indirection | clearning.cpp:118:2:118:11 | ... += ... indirection |
| clearning.cpp:118:2:118:11 | ... += ... indirection | clearning.cpp:118:4:118:6 | s indirection [post update] [val indirection] |
| clearning.cpp:118:4:118:6 | s indirection [post update] [val indirection] | clearning.cpp:119:8:119:8 | s indirection [val indirection] |
| clearning.cpp:118:4:118:6 | val indirection | clearning.cpp:118:2:118:11 | ... += ... indirection |
| clearning.cpp:119:8:119:8 | s indirection [val indirection] | clearning.cpp:119:7:119:12 | * ... |
| clearning.cpp:119:8:119:8 | s indirection [val indirection] | clearning.cpp:119:10:119:12 | val indirection |
| clearning.cpp:119:8:119:8 | s indirection [val indirection] | clearning.cpp:119:10:119:12 | val indirection |
| clearning.cpp:119:10:119:12 | val indirection | clearning.cpp:119:7:119:12 | * ... |
| clearning.cpp:119:10:119:12 | val indirection | clearning.cpp:119:7:119:12 | * ... |
| clearning.cpp:151:3:151:22 | ... = ... | clearning.cpp:151:5:151:7 | s indirection [post update] [val] |
| clearning.cpp:151:5:151:7 | s indirection [post update] [val] | clearning.cpp:152:8:152:8 | s indirection [val] |
| clearning.cpp:151:11:151:20 | call to user_input | clearning.cpp:151:3:151:22 | ... = ... |
| clearning.cpp:152:8:152:8 | s indirection [val] | clearning.cpp:152:10:152:12 | val |
| clearning.cpp:152:8:152:8 | s indirection [val] | clearning.cpp:152:10:152:12 | val indirection |
| clearning.cpp:152:10:152:12 | val indirection | clearning.cpp:152:10:152:12 | val |
| complex.cpp:9:7:9:7 | this indirection [a_] | complex.cpp:9:20:9:21 | this indirection [a_] |
| complex.cpp:9:20:9:21 | a_ | complex.cpp:9:7:9:7 | a indirection |
| complex.cpp:9:20:9:21 | a_ indirection | complex.cpp:9:7:9:7 | a indirection |
@@ -861,19 +991,20 @@ edges
| struct_init.c:15:8:15:9 | ab indirection [a] | struct_init.c:15:12:15:12 | a |
| struct_init.c:15:8:15:9 | ab indirection [a] | struct_init.c:15:12:15:12 | a indirection |
| struct_init.c:15:12:15:12 | a indirection | struct_init.c:15:12:15:12 | a |
| struct_init.c:20:17:20:36 | definition of ab indirection [post update] [a] | struct_init.c:22:8:22:9 | ab indirection [a] |
| struct_init.c:20:17:20:36 | definition of ab indirection [post update] [a] | struct_init.c:24:10:24:12 | & ... indirection [a] |
| struct_init.c:20:17:20:36 | definition of ab indirection [post update] [a] | struct_init.c:28:5:28:7 | & ... indirection [a] |
| struct_init.c:20:13:20:14 | definition of ab indirection [a] | struct_init.c:22:8:22:9 | ab indirection [a] |
| struct_init.c:20:13:20:14 | definition of ab indirection [a] | struct_init.c:24:10:24:12 | & ... indirection [a] |
| struct_init.c:20:13:20:14 | definition of ab indirection [a] | struct_init.c:28:5:28:7 | & ... indirection [a] |
| struct_init.c:20:17:20:36 | definition of ab indirection [post update] [a] | struct_init.c:20:13:20:14 | definition of ab indirection [a] |
| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:20:17:20:36 | definition of ab indirection [post update] [a] |
| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:20:20:20:29 | call to user_input |
| struct_init.c:22:8:22:9 | ab indirection [a] | struct_init.c:22:11:22:11 | a |
| struct_init.c:22:8:22:9 | ab indirection [a] | struct_init.c:22:11:22:11 | a indirection |
| struct_init.c:22:11:22:11 | a indirection | struct_init.c:22:11:22:11 | a |
| struct_init.c:24:10:24:12 | & ... indirection [a] | struct_init.c:14:24:14:25 | ab indirection [a] |
| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] | struct_init.c:31:8:31:12 | outer indirection [nestedAB, a] |
| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] | struct_init.c:31:8:31:12 | outer indirection [nestedAB, a] |
| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] | struct_init.c:36:11:36:15 | outer indirection [nestedAB, a] |
| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] | struct_init.c:36:11:36:15 | outer indirection [nestedAB, a] |
| struct_init.c:26:16:26:20 | definition of outer indirection [nestedAB, a] | struct_init.c:31:8:31:12 | outer indirection [nestedAB, a] |
| struct_init.c:26:16:26:20 | definition of outer indirection [nestedAB, a] | struct_init.c:36:11:36:15 | outer indirection [nestedAB, a] |
| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] | struct_init.c:26:16:26:20 | definition of outer indirection [nestedAB, a] |
| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] | struct_init.c:26:16:26:20 | definition of outer indirection [nestedAB, a] |
| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [pointerAB indirection, a] | struct_init.c:33:8:33:12 | outer indirection [pointerAB indirection, a] |
| struct_init.c:27:5:27:23 | {...} indirection [post update] [a] | struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] |
| struct_init.c:27:5:27:23 | {...} indirection [post update] [a] | struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] |
@@ -892,7 +1023,8 @@ edges
| struct_init.c:33:25:33:25 | a indirection | struct_init.c:33:25:33:25 | a |
| struct_init.c:36:10:36:24 | & ... indirection [a] | struct_init.c:14:24:14:25 | ab indirection [a] |
| struct_init.c:36:11:36:15 | outer indirection [nestedAB, a] | struct_init.c:36:10:36:24 | & ... indirection [a] |
| struct_init.c:40:17:40:36 | definition of ab indirection [post update] [a] | struct_init.c:43:5:43:7 | & ... indirection [a] |
| struct_init.c:40:13:40:14 | definition of ab indirection [a] | struct_init.c:43:5:43:7 | & ... indirection [a] |
| struct_init.c:40:17:40:36 | definition of ab indirection [post update] [a] | struct_init.c:40:13:40:14 | definition of ab indirection [a] |
| struct_init.c:40:20:40:29 | call to user_input | struct_init.c:40:17:40:36 | definition of ab indirection [post update] [a] |
| struct_init.c:40:20:40:29 | call to user_input | struct_init.c:40:20:40:29 | call to user_input |
| struct_init.c:41:23:44:3 | definition of outer indirection [post update] [pointerAB indirection, a] | struct_init.c:46:10:46:14 | outer indirection [pointerAB indirection, a] |
@@ -1433,6 +1565,114 @@ nodes
| by_reference.cpp:136:8:136:13 | pouter indirection [a] | semmle.label | pouter indirection [a] |
| by_reference.cpp:136:16:136:16 | a | semmle.label | a |
| by_reference.cpp:136:16:136:16 | a indirection | semmle.label | a indirection |
| clearning.cpp:32:3:32:25 | ... = ... | semmle.label | ... = ... |
| clearning.cpp:32:6:32:6 | s indirection [post update] [x indirection] | semmle.label | s indirection [post update] [x indirection] |
| clearning.cpp:32:10:32:19 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:33:5:33:5 | s indirection [x indirection] | semmle.label | s indirection [x indirection] |
| clearning.cpp:34:8:34:11 | * ... | semmle.label | * ... |
| clearning.cpp:34:9:34:9 | s indirection [x indirection] | semmle.label | s indirection [x indirection] |
| clearning.cpp:34:11:34:11 | x indirection | semmle.label | x indirection |
| clearning.cpp:34:11:34:11 | x indirection | semmle.label | x indirection |
| clearning.cpp:53:3:53:25 | ... = ... | semmle.label | ... = ... |
| clearning.cpp:53:6:53:6 | s indirection [post update] [x indirection] | semmle.label | s indirection [post update] [x indirection] |
| clearning.cpp:53:10:53:19 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:54:3:54:3 | s indirection [x indirection] | semmle.label | s indirection [x indirection] |
| clearning.cpp:54:3:54:7 | ... ++ indirection | semmle.label | ... ++ indirection |
| clearning.cpp:54:3:54:7 | ... ++ indirection | semmle.label | ... ++ indirection |
| clearning.cpp:54:5:54:5 | s indirection [post update] [x indirection] | semmle.label | s indirection [post update] [x indirection] |
| clearning.cpp:54:5:54:5 | x indirection | semmle.label | x indirection |
| clearning.cpp:55:8:55:8 | s indirection [x indirection] | semmle.label | s indirection [x indirection] |
| clearning.cpp:55:10:55:10 | x indirection | semmle.label | x indirection |
| clearning.cpp:55:10:55:10 | x indirection | semmle.label | x indirection |
| clearning.cpp:60:3:60:22 | ... = ... | semmle.label | ... = ... |
| clearning.cpp:60:7:60:7 | s indirection [post update] [x indirection] | semmle.label | s indirection [post update] [x indirection] |
| clearning.cpp:60:11:60:20 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:61:3:61:3 | s indirection [x indirection] | semmle.label | s indirection [x indirection] |
| clearning.cpp:61:3:61:7 | ... ++ indirection | semmle.label | ... ++ indirection |
| clearning.cpp:61:3:61:7 | ... ++ indirection | semmle.label | ... ++ indirection |
| clearning.cpp:61:5:61:5 | s indirection [post update] [x indirection] | semmle.label | s indirection [post update] [x indirection] |
| clearning.cpp:61:5:61:5 | x indirection | semmle.label | x indirection |
| clearning.cpp:62:8:62:8 | s indirection [x indirection] | semmle.label | s indirection [x indirection] |
| clearning.cpp:62:10:62:10 | x indirection | semmle.label | x indirection |
| clearning.cpp:62:10:62:10 | x indirection | semmle.label | x indirection |
| clearning.cpp:74:20:74:22 | argument_source output argument | semmle.label | argument_source output argument |
| clearning.cpp:74:20:74:22 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:76:7:76:12 | * ... | semmle.label | * ... |
| clearning.cpp:76:8:76:8 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:76:10:76:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:76:10:76:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:81:20:81:22 | argument_source output argument | semmle.label | argument_source output argument |
| clearning.cpp:81:20:81:22 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:83:5:83:21 | ... = ... indirection | semmle.label | ... = ... indirection |
| clearning.cpp:83:7:83:9 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:83:13:83:13 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:83:13:83:21 | ... + ... indirection | semmle.label | ... + ... indirection |
| clearning.cpp:83:15:83:17 | val indirection | semmle.label | val indirection |
| clearning.cpp:84:7:84:12 | * ... | semmle.label | * ... |
| clearning.cpp:84:8:84:8 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:84:10:84:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:84:10:84:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:89:20:89:22 | argument_source output argument | semmle.label | argument_source output argument |
| clearning.cpp:89:20:89:22 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:90:3:90:3 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:90:3:90:9 | ... ++ indirection | semmle.label | ... ++ indirection |
| clearning.cpp:90:3:90:9 | ... ++ indirection | semmle.label | ... ++ indirection |
| clearning.cpp:90:5:90:7 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:90:5:90:7 | val indirection | semmle.label | val indirection |
| clearning.cpp:91:7:91:12 | * ... | semmle.label | * ... |
| clearning.cpp:91:8:91:8 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:91:10:91:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:91:10:91:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:96:20:96:22 | argument_source output argument | semmle.label | argument_source output argument |
| clearning.cpp:96:20:96:22 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:97:2:97:18 | ... = ... indirection | semmle.label | ... = ... indirection |
| clearning.cpp:97:4:97:6 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:97:10:97:10 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:97:10:97:18 | ... + ... indirection | semmle.label | ... + ... indirection |
| clearning.cpp:97:12:97:14 | val indirection | semmle.label | val indirection |
| clearning.cpp:98:7:98:12 | * ... | semmle.label | * ... |
| clearning.cpp:98:8:98:8 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:98:10:98:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:98:10:98:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:103:20:103:22 | argument_source output argument | semmle.label | argument_source output argument |
| clearning.cpp:103:20:103:22 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:104:2:104:2 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:104:2:104:8 | ... ++ indirection | semmle.label | ... ++ indirection |
| clearning.cpp:104:2:104:8 | ... ++ indirection | semmle.label | ... ++ indirection |
| clearning.cpp:104:4:104:6 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:104:4:104:6 | val indirection | semmle.label | val indirection |
| clearning.cpp:105:7:105:12 | * ... | semmle.label | * ... |
| clearning.cpp:105:8:105:8 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:105:10:105:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:105:10:105:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:110:20:110:22 | argument_source output argument | semmle.label | argument_source output argument |
| clearning.cpp:110:20:110:22 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:111:2:111:8 | ++ ... indirection | semmle.label | ++ ... indirection |
| clearning.cpp:111:2:111:8 | ++ ... indirection | semmle.label | ++ ... indirection |
| clearning.cpp:111:4:111:4 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:111:6:111:8 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:111:6:111:8 | val indirection | semmle.label | val indirection |
| clearning.cpp:112:7:112:12 | * ... | semmle.label | * ... |
| clearning.cpp:112:8:112:8 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:112:10:112:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:112:10:112:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:117:20:117:22 | argument_source output argument | semmle.label | argument_source output argument |
| clearning.cpp:117:20:117:22 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:118:2:118:2 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:118:2:118:11 | ... += ... indirection | semmle.label | ... += ... indirection |
| clearning.cpp:118:2:118:11 | ... += ... indirection | semmle.label | ... += ... indirection |
| clearning.cpp:118:4:118:6 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:118:4:118:6 | val indirection | semmle.label | val indirection |
| clearning.cpp:119:7:119:12 | * ... | semmle.label | * ... |
| clearning.cpp:119:8:119:8 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:119:10:119:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:119:10:119:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:151:3:151:22 | ... = ... | semmle.label | ... = ... |
| clearning.cpp:151:5:151:7 | s indirection [post update] [val] | semmle.label | s indirection [post update] [val] |
| clearning.cpp:151:11:151:20 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:152:8:152:8 | s indirection [val] | semmle.label | s indirection [val] |
| clearning.cpp:152:10:152:12 | val | semmle.label | val |
| clearning.cpp:152:10:152:12 | val indirection | semmle.label | val indirection |
| complex.cpp:9:7:9:7 | a indirection | semmle.label | a indirection |
| complex.cpp:9:7:9:7 | this indirection [a_] | semmle.label | this indirection [a_] |
| complex.cpp:9:20:9:21 | a_ | semmle.label | a_ |
@@ -1699,6 +1939,7 @@ nodes
| struct_init.c:15:8:15:9 | ab indirection [a] | semmle.label | ab indirection [a] |
| struct_init.c:15:12:15:12 | a | semmle.label | a |
| struct_init.c:15:12:15:12 | a indirection | semmle.label | a indirection |
| struct_init.c:20:13:20:14 | definition of ab indirection [a] | semmle.label | definition of ab indirection [a] |
| struct_init.c:20:17:20:36 | definition of ab indirection [post update] [a] | semmle.label | definition of ab indirection [post update] [a] |
| struct_init.c:20:20:20:29 | call to user_input | semmle.label | call to user_input |
| struct_init.c:20:20:20:29 | call to user_input | semmle.label | call to user_input |
@@ -1706,6 +1947,7 @@ nodes
| struct_init.c:22:11:22:11 | a | semmle.label | a |
| struct_init.c:22:11:22:11 | a indirection | semmle.label | a indirection |
| struct_init.c:24:10:24:12 | & ... indirection [a] | semmle.label | & ... indirection [a] |
| struct_init.c:26:16:26:20 | definition of outer indirection [nestedAB, a] | semmle.label | definition of outer indirection [nestedAB, a] |
| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] | semmle.label | definition of outer indirection [post update] [nestedAB, a] |
| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] | semmle.label | definition of outer indirection [post update] [nestedAB, a] |
| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [pointerAB indirection, a] | semmle.label | definition of outer indirection [post update] [pointerAB indirection, a] |
@@ -1724,6 +1966,7 @@ nodes
| struct_init.c:33:25:33:25 | a indirection | semmle.label | a indirection |
| struct_init.c:36:10:36:24 | & ... indirection [a] | semmle.label | & ... indirection [a] |
| struct_init.c:36:11:36:15 | outer indirection [nestedAB, a] | semmle.label | outer indirection [nestedAB, a] |
| struct_init.c:40:13:40:14 | definition of ab indirection [a] | semmle.label | definition of ab indirection [a] |
| struct_init.c:40:17:40:36 | definition of ab indirection [post update] [a] | semmle.label | definition of ab indirection [post update] [a] |
| struct_init.c:40:20:40:29 | call to user_input | semmle.label | call to user_input |
| struct_init.c:40:20:40:29 | call to user_input | semmle.label | call to user_input |
@@ -1883,6 +2126,17 @@ subpaths
| by_reference.cpp:134:29:134:29 | a | by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:134:29:134:29 | a | a flows from $@ | by_reference.cpp:88:13:88:22 | call to user_input | call to user_input |
| by_reference.cpp:135:27:135:27 | a | by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:135:27:135:27 | a | a flows from $@ | by_reference.cpp:88:13:88:22 | call to user_input | call to user_input |
| by_reference.cpp:136:16:136:16 | a | by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:136:16:136:16 | a | a flows from $@ | by_reference.cpp:96:8:96:17 | call to user_input | call to user_input |
| clearning.cpp:34:8:34:11 | * ... | clearning.cpp:32:10:32:19 | call to user_input | clearning.cpp:34:8:34:11 | * ... | * ... flows from $@ | clearning.cpp:32:10:32:19 | call to user_input | call to user_input |
| clearning.cpp:55:10:55:10 | x indirection | clearning.cpp:53:10:53:19 | call to user_input | clearning.cpp:55:10:55:10 | x indirection | x indirection flows from $@ | clearning.cpp:53:10:53:19 | call to user_input | call to user_input |
| clearning.cpp:62:10:62:10 | x indirection | clearning.cpp:60:11:60:20 | call to user_input | clearning.cpp:62:10:62:10 | x indirection | x indirection flows from $@ | clearning.cpp:60:11:60:20 | call to user_input | call to user_input |
| clearning.cpp:76:7:76:12 | * ... | clearning.cpp:74:20:74:22 | argument_source output argument | clearning.cpp:76:7:76:12 | * ... | * ... flows from $@ | clearning.cpp:74:20:74:22 | argument_source output argument | argument_source output argument |
| clearning.cpp:84:7:84:12 | * ... | clearning.cpp:81:20:81:22 | argument_source output argument | clearning.cpp:84:7:84:12 | * ... | * ... flows from $@ | clearning.cpp:81:20:81:22 | argument_source output argument | argument_source output argument |
| clearning.cpp:91:7:91:12 | * ... | clearning.cpp:89:20:89:22 | argument_source output argument | clearning.cpp:91:7:91:12 | * ... | * ... flows from $@ | clearning.cpp:89:20:89:22 | argument_source output argument | argument_source output argument |
| clearning.cpp:98:7:98:12 | * ... | clearning.cpp:96:20:96:22 | argument_source output argument | clearning.cpp:98:7:98:12 | * ... | * ... flows from $@ | clearning.cpp:96:20:96:22 | argument_source output argument | argument_source output argument |
| clearning.cpp:105:7:105:12 | * ... | clearning.cpp:103:20:103:22 | argument_source output argument | clearning.cpp:105:7:105:12 | * ... | * ... flows from $@ | clearning.cpp:103:20:103:22 | argument_source output argument | argument_source output argument |
| clearning.cpp:112:7:112:12 | * ... | clearning.cpp:110:20:110:22 | argument_source output argument | clearning.cpp:112:7:112:12 | * ... | * ... flows from $@ | clearning.cpp:110:20:110:22 | argument_source output argument | argument_source output argument |
| clearning.cpp:119:7:119:12 | * ... | clearning.cpp:117:20:117:22 | argument_source output argument | clearning.cpp:119:7:119:12 | * ... | * ... flows from $@ | clearning.cpp:117:20:117:22 | argument_source output argument | argument_source output argument |
| clearning.cpp:152:10:152:12 | val | clearning.cpp:151:11:151:20 | call to user_input | clearning.cpp:152:10:152:12 | val | val flows from $@ | clearning.cpp:151:11:151:20 | call to user_input | call to user_input |
| complex.cpp:42:18:42:18 | call to a | complex.cpp:53:19:53:28 | call to user_input | complex.cpp:42:18:42:18 | call to a | call to a flows from $@ | complex.cpp:53:19:53:28 | call to user_input | call to user_input |
| complex.cpp:42:18:42:18 | call to a | complex.cpp:55:19:55:28 | call to user_input | complex.cpp:42:18:42:18 | call to a | call to a flows from $@ | complex.cpp:55:19:55:28 | call to user_input | call to user_input |
| complex.cpp:43:18:43:18 | call to b | complex.cpp:54:19:54:28 | call to user_input | complex.cpp:43:18:43:18 | call to b | call to b flows from $@ | complex.cpp:54:19:54:28 | call to user_input | call to user_input |

View File

@@ -167,6 +167,66 @@
| by_reference.cpp:88:9:88:9 | a | AST only |
| by_reference.cpp:92:3:92:5 | * ... | AST only |
| by_reference.cpp:96:3:96:4 | pa | AST only |
| clearning.cpp:18:7:18:7 | s | IR only |
| clearning.cpp:19:3:19:6 | * ... | AST only |
| clearning.cpp:20:12:20:12 | s | IR only |
| clearning.cpp:25:7:25:7 | s | IR only |
| clearning.cpp:26:7:26:7 | s | IR only |
| clearning.cpp:27:12:27:12 | s | IR only |
| clearning.cpp:32:3:32:6 | * ... | AST only |
| clearning.cpp:33:7:33:7 | s | IR only |
| clearning.cpp:34:8:34:11 | * ... | IR only |
| clearning.cpp:34:11:34:11 | s | IR only |
| clearning.cpp:39:3:39:6 | * ... | AST only |
| clearning.cpp:40:5:40:5 | x | AST only |
| clearning.cpp:41:8:41:11 | * ... | IR only |
| clearning.cpp:41:11:41:11 | s | IR only |
| clearning.cpp:46:7:46:7 | s | IR only |
| clearning.cpp:47:5:47:5 | x | AST only |
| clearning.cpp:48:8:48:11 | * ... | IR only |
| clearning.cpp:48:11:48:11 | s | IR only |
| clearning.cpp:53:3:53:6 | * ... | AST only |
| clearning.cpp:54:5:54:5 | x | AST only |
| clearning.cpp:60:7:60:7 | s | IR only |
| clearning.cpp:61:5:61:5 | x | AST only |
| clearning.cpp:75:2:75:10 | access to array | AST only |
| clearning.cpp:76:10:76:12 | s | IR only |
| clearning.cpp:82:2:82:9 | access to array | AST only |
| clearning.cpp:83:7:83:9 | val | AST only |
| clearning.cpp:83:15:83:17 | s | IR only |
| clearning.cpp:84:10:84:12 | s | IR only |
| clearning.cpp:90:5:90:7 | val | AST only |
| clearning.cpp:91:10:91:12 | s | IR only |
| clearning.cpp:97:4:97:6 | val | AST only |
| clearning.cpp:97:12:97:14 | s | IR only |
| clearning.cpp:98:10:98:12 | s | IR only |
| clearning.cpp:104:4:104:6 | val | AST only |
| clearning.cpp:105:10:105:12 | s | IR only |
| clearning.cpp:111:6:111:8 | val | AST only |
| clearning.cpp:112:10:112:12 | s | IR only |
| clearning.cpp:118:4:118:6 | val | AST only |
| clearning.cpp:119:10:119:12 | s | IR only |
| clearning.cpp:124:4:124:6 | val | AST only |
| clearning.cpp:125:4:125:6 | val | AST only |
| clearning.cpp:131:4:131:6 | val | AST only |
| clearning.cpp:132:4:132:6 | val | AST only |
| clearning.cpp:138:4:138:6 | val | AST only |
| clearning.cpp:139:6:139:8 | val | AST only |
| clearning.cpp:151:5:151:7 | val | AST only |
| clearning.cpp:152:10:152:12 | s | IR only |
| clearning.cpp:157:5:157:7 | val | AST only |
| clearning.cpp:158:5:158:7 | val | AST only |
| clearning.cpp:159:10:159:12 | s | IR only |
| clearning.cpp:164:5:164:7 | val | AST only |
| clearning.cpp:165:5:165:7 | val | AST only |
| clearning.cpp:166:10:166:12 | s | IR only |
| clearning.cpp:171:5:171:7 | val | AST only |
| clearning.cpp:172:5:172:7 | val | AST only |
| clearning.cpp:173:10:173:12 | s | IR only |
| clearning.cpp:178:5:178:7 | val | AST only |
| clearning.cpp:179:5:179:7 | val | AST only |
| clearning.cpp:179:13:179:15 | s | IR only |
| clearning.cpp:180:10:180:12 | s | IR only |
| complex.cpp:9:20:9:21 | this | IR only |
| complex.cpp:10:20:10:21 | this | IR only |
| complex.cpp:11:22:11:23 | a_ | AST only |

View File

@@ -408,6 +408,90 @@
| by_reference.cpp:135:27:135:27 | a |
| by_reference.cpp:136:8:136:13 | pouter |
| by_reference.cpp:136:16:136:16 | a |
| clearning.cpp:18:5:18:5 | s |
| clearning.cpp:19:4:19:4 | s |
| clearning.cpp:20:10:20:10 | s |
| clearning.cpp:25:5:25:5 | s |
| clearning.cpp:26:5:26:5 | s |
| clearning.cpp:27:10:27:10 | s |
| clearning.cpp:32:4:32:4 | s |
| clearning.cpp:33:5:33:5 | s |
| clearning.cpp:34:8:34:11 | * ... |
| clearning.cpp:34:9:34:9 | s |
| clearning.cpp:39:4:39:4 | s |
| clearning.cpp:40:3:40:3 | s |
| clearning.cpp:41:8:41:11 | * ... |
| clearning.cpp:41:9:41:9 | s |
| clearning.cpp:46:5:46:5 | s |
| clearning.cpp:47:3:47:3 | s |
| clearning.cpp:48:8:48:11 | * ... |
| clearning.cpp:48:9:48:9 | s |
| clearning.cpp:53:4:53:4 | s |
| clearning.cpp:54:3:54:3 | s |
| clearning.cpp:55:8:55:8 | s |
| clearning.cpp:55:10:55:10 | x |
| clearning.cpp:60:5:60:5 | s |
| clearning.cpp:61:3:61:3 | s |
| clearning.cpp:62:8:62:8 | s |
| clearning.cpp:62:10:62:10 | x |
| clearning.cpp:74:18:74:18 | s |
| clearning.cpp:74:20:74:22 | val |
| clearning.cpp:75:2:75:2 | s |
| clearning.cpp:76:8:76:8 | s |
| clearning.cpp:81:18:81:18 | s |
| clearning.cpp:81:20:81:22 | val |
| clearning.cpp:82:2:82:2 | s |
| clearning.cpp:83:5:83:5 | s |
| clearning.cpp:83:13:83:13 | s |
| clearning.cpp:84:8:84:8 | s |
| clearning.cpp:89:18:89:18 | s |
| clearning.cpp:89:20:89:22 | val |
| clearning.cpp:90:3:90:3 | s |
| clearning.cpp:91:8:91:8 | s |
| clearning.cpp:96:18:96:18 | s |
| clearning.cpp:96:20:96:22 | val |
| clearning.cpp:97:2:97:2 | s |
| clearning.cpp:97:10:97:10 | s |
| clearning.cpp:98:8:98:8 | s |
| clearning.cpp:103:18:103:18 | s |
| clearning.cpp:103:20:103:22 | val |
| clearning.cpp:104:2:104:2 | s |
| clearning.cpp:105:8:105:8 | s |
| clearning.cpp:110:18:110:18 | s |
| clearning.cpp:110:20:110:22 | val |
| clearning.cpp:111:4:111:4 | s |
| clearning.cpp:112:8:112:8 | s |
| clearning.cpp:117:18:117:18 | s |
| clearning.cpp:117:20:117:22 | val |
| clearning.cpp:118:2:118:2 | s |
| clearning.cpp:119:8:119:8 | s |
| clearning.cpp:124:2:124:2 | s |
| clearning.cpp:125:2:125:2 | s |
| clearning.cpp:126:7:126:7 | s |
| clearning.cpp:126:9:126:11 | val |
| clearning.cpp:131:2:131:2 | s |
| clearning.cpp:132:2:132:2 | s |
| clearning.cpp:133:7:133:7 | s |
| clearning.cpp:133:9:133:11 | val |
| clearning.cpp:138:2:138:2 | s |
| clearning.cpp:139:4:139:4 | s |
| clearning.cpp:140:7:140:7 | s |
| clearning.cpp:140:9:140:11 | val |
| clearning.cpp:151:3:151:3 | s |
| clearning.cpp:152:8:152:8 | s |
| clearning.cpp:157:3:157:3 | s |
| clearning.cpp:158:3:158:3 | s |
| clearning.cpp:159:8:159:8 | s |
| clearning.cpp:164:3:164:3 | s |
| clearning.cpp:165:3:165:3 | s |
| clearning.cpp:166:8:166:8 | s |
| clearning.cpp:171:3:171:3 | s |
| clearning.cpp:172:3:172:3 | s |
| clearning.cpp:173:8:173:8 | s |
| clearning.cpp:178:3:178:3 | s |
| clearning.cpp:179:3:179:3 | s |
| clearning.cpp:179:11:179:11 | s |
| clearning.cpp:180:8:180:8 | s |
| complex.cpp:9:20:9:21 | this |
| complex.cpp:10:20:10:21 | this |
| complex.cpp:11:22:11:23 | this |

View File

@@ -348,6 +348,92 @@
| by_reference.cpp:135:27:135:27 | a |
| by_reference.cpp:136:8:136:13 | pouter |
| by_reference.cpp:136:16:136:16 | a |
| clearning.cpp:19:3:19:6 | * ... |
| clearning.cpp:19:4:19:4 | s |
| clearning.cpp:32:3:32:6 | * ... |
| clearning.cpp:32:4:32:4 | s |
| clearning.cpp:39:3:39:6 | * ... |
| clearning.cpp:39:4:39:4 | s |
| clearning.cpp:40:3:40:3 | s |
| clearning.cpp:40:5:40:5 | x |
| clearning.cpp:47:3:47:3 | s |
| clearning.cpp:47:5:47:5 | x |
| clearning.cpp:53:3:53:6 | * ... |
| clearning.cpp:53:4:53:4 | s |
| clearning.cpp:54:3:54:3 | s |
| clearning.cpp:54:5:54:5 | x |
| clearning.cpp:55:8:55:8 | s |
| clearning.cpp:55:10:55:10 | x |
| clearning.cpp:61:3:61:3 | s |
| clearning.cpp:61:5:61:5 | x |
| clearning.cpp:62:8:62:8 | s |
| clearning.cpp:62:10:62:10 | x |
| clearning.cpp:74:18:74:18 | s |
| clearning.cpp:74:20:74:22 | val |
| clearning.cpp:75:2:75:2 | s |
| clearning.cpp:75:2:75:10 | access to array |
| clearning.cpp:81:18:81:18 | s |
| clearning.cpp:81:20:81:22 | val |
| clearning.cpp:82:2:82:2 | s |
| clearning.cpp:82:2:82:9 | access to array |
| clearning.cpp:83:5:83:5 | s |
| clearning.cpp:83:7:83:9 | val |
| clearning.cpp:89:18:89:18 | s |
| clearning.cpp:89:20:89:22 | val |
| clearning.cpp:90:3:90:3 | s |
| clearning.cpp:90:5:90:7 | val |
| clearning.cpp:96:18:96:18 | s |
| clearning.cpp:96:20:96:22 | val |
| clearning.cpp:97:2:97:2 | s |
| clearning.cpp:97:4:97:6 | val |
| clearning.cpp:103:18:103:18 | s |
| clearning.cpp:103:20:103:22 | val |
| clearning.cpp:104:2:104:2 | s |
| clearning.cpp:104:4:104:6 | val |
| clearning.cpp:110:18:110:18 | s |
| clearning.cpp:110:20:110:22 | val |
| clearning.cpp:111:4:111:4 | s |
| clearning.cpp:111:6:111:8 | val |
| clearning.cpp:117:18:117:18 | s |
| clearning.cpp:117:20:117:22 | val |
| clearning.cpp:118:2:118:2 | s |
| clearning.cpp:118:4:118:6 | val |
| clearning.cpp:124:2:124:2 | s |
| clearning.cpp:124:4:124:6 | val |
| clearning.cpp:125:2:125:2 | s |
| clearning.cpp:125:4:125:6 | val |
| clearning.cpp:126:7:126:7 | s |
| clearning.cpp:126:9:126:11 | val |
| clearning.cpp:131:2:131:2 | s |
| clearning.cpp:131:4:131:6 | val |
| clearning.cpp:132:2:132:2 | s |
| clearning.cpp:132:4:132:6 | val |
| clearning.cpp:133:7:133:7 | s |
| clearning.cpp:133:9:133:11 | val |
| clearning.cpp:138:2:138:2 | s |
| clearning.cpp:138:4:138:6 | val |
| clearning.cpp:139:4:139:4 | s |
| clearning.cpp:139:6:139:8 | val |
| clearning.cpp:140:7:140:7 | s |
| clearning.cpp:140:9:140:11 | val |
| clearning.cpp:151:3:151:3 | s |
| clearning.cpp:151:5:151:7 | val |
| clearning.cpp:157:3:157:3 | s |
| clearning.cpp:157:5:157:7 | val |
| clearning.cpp:158:3:158:3 | s |
| clearning.cpp:158:5:158:7 | val |
| clearning.cpp:164:3:164:3 | s |
| clearning.cpp:164:5:164:7 | val |
| clearning.cpp:165:3:165:3 | s |
| clearning.cpp:165:5:165:7 | val |
| clearning.cpp:171:3:171:3 | s |
| clearning.cpp:171:5:171:7 | val |
| clearning.cpp:172:3:172:3 | s |
| clearning.cpp:172:5:172:7 | val |
| clearning.cpp:178:3:178:3 | s |
| clearning.cpp:178:5:178:7 | val |
| clearning.cpp:179:3:179:3 | s |
| clearning.cpp:179:5:179:7 | val |
| complex.cpp:11:22:11:23 | a_ |
| complex.cpp:11:22:11:23 | this |
| complex.cpp:12:22:12:23 | b_ |

View File

@@ -448,6 +448,42 @@ edges
| by_reference.cpp:135:8:135:13 | pouter [inner_ptr, a] | by_reference.cpp:135:16:135:24 | inner_ptr [a] |
| by_reference.cpp:135:16:135:24 | inner_ptr [a] | by_reference.cpp:135:27:135:27 | a |
| by_reference.cpp:136:8:136:13 | pouter [a] | by_reference.cpp:136:16:136:16 | a |
| clearning.cpp:53:4:53:4 | s [post update] [x] | clearning.cpp:55:8:55:8 | s [x] |
| clearning.cpp:53:6:53:6 | x [inner post update] | clearning.cpp:53:4:53:4 | s [post update] [x] |
| clearning.cpp:53:10:53:19 | call to user_input | clearning.cpp:53:6:53:6 | x [inner post update] |
| clearning.cpp:55:8:55:8 | s [x] | clearning.cpp:55:10:55:10 | x |
| clearning.cpp:124:2:124:2 | s [post update] [val] | clearning.cpp:126:7:126:7 | s [val] |
| clearning.cpp:124:2:124:25 | ... = ... | clearning.cpp:124:2:124:2 | s [post update] [val] |
| clearning.cpp:124:10:124:19 | call to user_input | clearning.cpp:124:2:124:25 | ... = ... |
| clearning.cpp:126:7:126:7 | s [val] | clearning.cpp:126:9:126:11 | val |
| clearning.cpp:131:2:131:2 | s [post update] [val] | clearning.cpp:133:7:133:7 | s [val] |
| clearning.cpp:131:2:131:25 | ... = ... | clearning.cpp:131:2:131:2 | s [post update] [val] |
| clearning.cpp:131:10:131:19 | call to user_input | clearning.cpp:131:2:131:25 | ... = ... |
| clearning.cpp:133:7:133:7 | s [val] | clearning.cpp:133:9:133:11 | val |
| clearning.cpp:138:2:138:2 | s [post update] [val] | clearning.cpp:140:7:140:7 | s [val] |
| clearning.cpp:138:2:138:25 | ... = ... | clearning.cpp:138:2:138:2 | s [post update] [val] |
| clearning.cpp:138:10:138:19 | call to user_input | clearning.cpp:138:2:138:25 | ... = ... |
| clearning.cpp:140:7:140:7 | s [val] | clearning.cpp:140:9:140:11 | val |
| clearning.cpp:151:3:151:3 | s [post update] [val] | clearning.cpp:152:8:152:8 | s [val] |
| clearning.cpp:151:3:151:22 | ... = ... | clearning.cpp:151:3:151:3 | s [post update] [val] |
| clearning.cpp:151:11:151:20 | call to user_input | clearning.cpp:151:3:151:22 | ... = ... |
| clearning.cpp:152:8:152:8 | s [val] | clearning.cpp:152:10:152:12 | val |
| clearning.cpp:157:3:157:3 | s [post update] [val] | clearning.cpp:159:8:159:8 | s [val] |
| clearning.cpp:157:3:157:22 | ... = ... | clearning.cpp:157:3:157:3 | s [post update] [val] |
| clearning.cpp:157:11:157:20 | call to user_input | clearning.cpp:157:3:157:22 | ... = ... |
| clearning.cpp:159:8:159:8 | s [val] | clearning.cpp:159:10:159:12 | val |
| clearning.cpp:164:3:164:3 | s [post update] [val] | clearning.cpp:166:8:166:8 | s [val] |
| clearning.cpp:164:3:164:22 | ... = ... | clearning.cpp:164:3:164:3 | s [post update] [val] |
| clearning.cpp:164:11:164:20 | call to user_input | clearning.cpp:164:3:164:22 | ... = ... |
| clearning.cpp:166:8:166:8 | s [val] | clearning.cpp:166:10:166:12 | val |
| clearning.cpp:171:3:171:3 | s [post update] [val] | clearning.cpp:173:8:173:8 | s [val] |
| clearning.cpp:171:3:171:22 | ... = ... | clearning.cpp:171:3:171:3 | s [post update] [val] |
| clearning.cpp:171:11:171:20 | call to user_input | clearning.cpp:171:3:171:22 | ... = ... |
| clearning.cpp:173:8:173:8 | s [val] | clearning.cpp:173:10:173:12 | val |
| clearning.cpp:178:3:178:3 | s [post update] [val] | clearning.cpp:180:8:180:8 | s [val] |
| clearning.cpp:178:3:178:22 | ... = ... | clearning.cpp:178:3:178:3 | s [post update] [val] |
| clearning.cpp:178:11:178:20 | call to user_input | clearning.cpp:178:3:178:22 | ... = ... |
| clearning.cpp:180:8:180:8 | s [val] | clearning.cpp:180:10:180:12 | val |
| complex.cpp:9:7:9:7 | this [a_] | complex.cpp:9:20:9:21 | this [a_] |
| complex.cpp:9:20:9:21 | this [a_] | complex.cpp:9:20:9:21 | a_ |
| complex.cpp:10:7:10:7 | this [b_] | complex.cpp:10:20:10:21 | this [b_] |
@@ -1155,6 +1191,51 @@ nodes
| by_reference.cpp:135:27:135:27 | a | semmle.label | a |
| by_reference.cpp:136:8:136:13 | pouter [a] | semmle.label | pouter [a] |
| by_reference.cpp:136:16:136:16 | a | semmle.label | a |
| clearning.cpp:53:4:53:4 | s [post update] [x] | semmle.label | s [post update] [x] |
| clearning.cpp:53:6:53:6 | x [inner post update] | semmle.label | x [inner post update] |
| clearning.cpp:53:10:53:19 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:55:8:55:8 | s [x] | semmle.label | s [x] |
| clearning.cpp:55:10:55:10 | x | semmle.label | x |
| clearning.cpp:124:2:124:2 | s [post update] [val] | semmle.label | s [post update] [val] |
| clearning.cpp:124:2:124:25 | ... = ... | semmle.label | ... = ... |
| clearning.cpp:124:10:124:19 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:126:7:126:7 | s [val] | semmle.label | s [val] |
| clearning.cpp:126:9:126:11 | val | semmle.label | val |
| clearning.cpp:131:2:131:2 | s [post update] [val] | semmle.label | s [post update] [val] |
| clearning.cpp:131:2:131:25 | ... = ... | semmle.label | ... = ... |
| clearning.cpp:131:10:131:19 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:133:7:133:7 | s [val] | semmle.label | s [val] |
| clearning.cpp:133:9:133:11 | val | semmle.label | val |
| clearning.cpp:138:2:138:2 | s [post update] [val] | semmle.label | s [post update] [val] |
| clearning.cpp:138:2:138:25 | ... = ... | semmle.label | ... = ... |
| clearning.cpp:138:10:138:19 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:140:7:140:7 | s [val] | semmle.label | s [val] |
| clearning.cpp:140:9:140:11 | val | semmle.label | val |
| clearning.cpp:151:3:151:3 | s [post update] [val] | semmle.label | s [post update] [val] |
| clearning.cpp:151:3:151:22 | ... = ... | semmle.label | ... = ... |
| clearning.cpp:151:11:151:20 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:152:8:152:8 | s [val] | semmle.label | s [val] |
| clearning.cpp:152:10:152:12 | val | semmle.label | val |
| clearning.cpp:157:3:157:3 | s [post update] [val] | semmle.label | s [post update] [val] |
| clearning.cpp:157:3:157:22 | ... = ... | semmle.label | ... = ... |
| clearning.cpp:157:11:157:20 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:159:8:159:8 | s [val] | semmle.label | s [val] |
| clearning.cpp:159:10:159:12 | val | semmle.label | val |
| clearning.cpp:164:3:164:3 | s [post update] [val] | semmle.label | s [post update] [val] |
| clearning.cpp:164:3:164:22 | ... = ... | semmle.label | ... = ... |
| clearning.cpp:164:11:164:20 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:166:8:166:8 | s [val] | semmle.label | s [val] |
| clearning.cpp:166:10:166:12 | val | semmle.label | val |
| clearning.cpp:171:3:171:3 | s [post update] [val] | semmle.label | s [post update] [val] |
| clearning.cpp:171:3:171:22 | ... = ... | semmle.label | ... = ... |
| clearning.cpp:171:11:171:20 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:173:8:173:8 | s [val] | semmle.label | s [val] |
| clearning.cpp:173:10:173:12 | val | semmle.label | val |
| clearning.cpp:178:3:178:3 | s [post update] [val] | semmle.label | s [post update] [val] |
| clearning.cpp:178:3:178:22 | ... = ... | semmle.label | ... = ... |
| clearning.cpp:178:11:178:20 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:180:8:180:8 | s [val] | semmle.label | s [val] |
| clearning.cpp:180:10:180:12 | val | semmle.label | val |
| complex.cpp:9:7:9:7 | this [a_] | semmle.label | this [a_] |
| complex.cpp:9:20:9:21 | a_ | semmle.label | a_ |
| complex.cpp:9:20:9:21 | this [a_] | semmle.label | this [a_] |
@@ -1551,6 +1632,15 @@ subpaths
| by_reference.cpp:134:29:134:29 | a | by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:134:29:134:29 | a | a flows from $@ | by_reference.cpp:88:13:88:22 | call to user_input | call to user_input |
| by_reference.cpp:135:27:135:27 | a | by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:135:27:135:27 | a | a flows from $@ | by_reference.cpp:88:13:88:22 | call to user_input | call to user_input |
| by_reference.cpp:136:16:136:16 | a | by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:136:16:136:16 | a | a flows from $@ | by_reference.cpp:96:8:96:17 | call to user_input | call to user_input |
| clearning.cpp:55:10:55:10 | x | clearning.cpp:53:10:53:19 | call to user_input | clearning.cpp:55:10:55:10 | x | x flows from $@ | clearning.cpp:53:10:53:19 | call to user_input | call to user_input |
| clearning.cpp:126:9:126:11 | val | clearning.cpp:124:10:124:19 | call to user_input | clearning.cpp:126:9:126:11 | val | val flows from $@ | clearning.cpp:124:10:124:19 | call to user_input | call to user_input |
| clearning.cpp:133:9:133:11 | val | clearning.cpp:131:10:131:19 | call to user_input | clearning.cpp:133:9:133:11 | val | val flows from $@ | clearning.cpp:131:10:131:19 | call to user_input | call to user_input |
| clearning.cpp:140:9:140:11 | val | clearning.cpp:138:10:138:19 | call to user_input | clearning.cpp:140:9:140:11 | val | val flows from $@ | clearning.cpp:138:10:138:19 | call to user_input | call to user_input |
| clearning.cpp:152:10:152:12 | val | clearning.cpp:151:11:151:20 | call to user_input | clearning.cpp:152:10:152:12 | val | val flows from $@ | clearning.cpp:151:11:151:20 | call to user_input | call to user_input |
| clearning.cpp:159:10:159:12 | val | clearning.cpp:157:11:157:20 | call to user_input | clearning.cpp:159:10:159:12 | val | val flows from $@ | clearning.cpp:157:11:157:20 | call to user_input | call to user_input |
| clearning.cpp:166:10:166:12 | val | clearning.cpp:164:11:164:20 | call to user_input | clearning.cpp:166:10:166:12 | val | val flows from $@ | clearning.cpp:164:11:164:20 | call to user_input | call to user_input |
| clearning.cpp:173:10:173:12 | val | clearning.cpp:171:11:171:20 | call to user_input | clearning.cpp:173:10:173:12 | val | val flows from $@ | clearning.cpp:171:11:171:20 | call to user_input | call to user_input |
| clearning.cpp:180:10:180:12 | val | clearning.cpp:178:11:178:20 | call to user_input | clearning.cpp:180:10:180:12 | val | val flows from $@ | clearning.cpp:178:11:178:20 | call to user_input | call to user_input |
| complex.cpp:42:18:42:18 | call to a | complex.cpp:53:19:53:28 | call to user_input | complex.cpp:42:18:42:18 | call to a | call to a flows from $@ | complex.cpp:53:19:53:28 | call to user_input | call to user_input |
| complex.cpp:42:18:42:18 | call to a | complex.cpp:55:19:55:28 | call to user_input | complex.cpp:42:18:42:18 | call to a | call to a flows from $@ | complex.cpp:55:19:55:28 | call to user_input | call to user_input |
| complex.cpp:43:18:43:18 | call to b | complex.cpp:54:19:54:28 | call to user_input | complex.cpp:43:18:43:18 | call to b | call to b flows from $@ | complex.cpp:54:19:54:28 | call to user_input | call to user_input |

View File

@@ -6584,6 +6584,27 @@
| taint.cpp:691:18:691:18 | s [post update] | taint.cpp:695:7:695:7 | s | |
| taint.cpp:691:20:691:20 | ref arg x | taint.cpp:694:9:694:9 | x | |
| taint.cpp:694:7:694:7 | s [post update] | taint.cpp:695:7:695:7 | s | |
| taint.cpp:700:13:700:18 | call to source | taint.cpp:702:11:702:11 | s | |
| taint.cpp:701:9:701:9 | p | taint.cpp:702:4:702:4 | p | |
| taint.cpp:702:4:702:4 | p | taint.cpp:702:4:702:6 | ... ++ | |
| taint.cpp:702:4:702:6 | ... ++ | taint.cpp:702:3:702:6 | * ... | TAINT |
| taint.cpp:702:4:702:6 | ... ++ | taint.cpp:703:8:703:8 | p | TAINT |
| taint.cpp:702:10:702:11 | * ... | taint.cpp:702:3:702:11 | ... = ... | |
| taint.cpp:702:11:702:11 | s | taint.cpp:702:10:702:11 | * ... | TAINT |
| taint.cpp:709:25:709:25 | d | taint.cpp:709:25:709:25 | d | |
| taint.cpp:709:25:709:25 | d | taint.cpp:711:10:711:10 | d | |
| taint.cpp:709:25:709:25 | d | taint.cpp:712:7:712:7 | d | |
| taint.cpp:709:34:709:34 | s | taint.cpp:709:34:709:34 | s | |
| taint.cpp:709:34:709:34 | s | taint.cpp:710:18:710:18 | s | |
| taint.cpp:709:34:709:34 | s | taint.cpp:711:13:711:13 | s | |
| taint.cpp:710:18:710:18 | ref arg s | taint.cpp:709:34:709:34 | s | |
| taint.cpp:710:18:710:18 | ref arg s | taint.cpp:711:13:711:13 | s | |
| taint.cpp:711:10:711:10 | d | taint.cpp:711:2:711:8 | call to strncpy | |
| taint.cpp:711:10:711:10 | ref arg d | taint.cpp:709:25:709:25 | d | |
| taint.cpp:711:10:711:10 | ref arg d | taint.cpp:712:7:712:7 | d | |
| taint.cpp:711:13:711:13 | s | taint.cpp:711:2:711:8 | call to strncpy | TAINT |
| taint.cpp:711:13:711:13 | s | taint.cpp:711:10:711:10 | ref arg d | TAINT |
| taint.cpp:712:7:712:7 | ref arg d | taint.cpp:709:25:709:25 | d | |
| vector.cpp:16:43:16:49 | source1 | vector.cpp:17:26:17:32 | source1 | |
| vector.cpp:16:43:16:49 | source1 | vector.cpp:31:38:31:44 | source1 | |
| vector.cpp:17:21:17:33 | call to vector | vector.cpp:19:14:19:14 | v | |

View File

@@ -693,4 +693,21 @@ void test_argument_source_field_to_obj() {
sink(s); // $ SPURIOUS: ast,ir
sink(s.x); // $ ast,ir
sink(s.y); // clean
}
namespace strings {
void test_write_to_read_then_incr_then_deref() {
char* s = source();
char* p;
*p++ = *s;
sink(p); // $ ast ir
}
}
char * strncpy (char *, const char *, unsigned long);
void test_strncpy(char* d, char* s) {
argument_source(s);
strncpy(d, s, 16);
sink(d); // $ ast ir
}

View File

@@ -14462,6 +14462,106 @@ ir.cpp:
# 1911| getExpr(): [VariableAccess] x
# 1911| Type = [IntType] int
# 1911| ValueCategory = prvalue(load)
# 1914| [TopLevelFunction] int static_function(int)
# 1914| <params>:
# 1914| getParameter(0): [Parameter] x
# 1914| Type = [IntType] int
# 1914| getEntryPoint(): [BlockStmt] { ... }
# 1915| getStmt(0): [ReturnStmt] return ...
# 1915| getExpr(): [VariableAccess] x
# 1915| Type = [IntType] int
# 1915| ValueCategory = prvalue(load)
# 1918| [TopLevelFunction] void test_static_functions_with_assignments()
# 1918| <params>:
# 1918| getEntryPoint(): [BlockStmt] { ... }
# 1919| getStmt(0): [DeclStmt] declaration
# 1919| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c
# 1919| Type = [Class] C
# 1919| getVariable().getInitializer(): [Initializer] initializer for c
# 1919| getExpr(): [ConstructorCall] call to C
# 1919| Type = [VoidType] void
# 1919| ValueCategory = prvalue
# 1920| getStmt(1): [DeclStmt] declaration
# 1920| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
# 1920| Type = [IntType] int
# 1921| getStmt(2): [ExprStmt] ExprStmt
# 1921| getExpr(): [AssignExpr] ... = ...
# 1921| Type = [IntType] int
# 1921| ValueCategory = lvalue
# 1921| getLValue(): [VariableAccess] x
# 1921| Type = [IntType] int
# 1921| ValueCategory = lvalue
# 1921| getRValue(): [FunctionCall] call to StaticMemberFunction
# 1921| Type = [IntType] int
# 1921| ValueCategory = prvalue
# 1921| getQualifier(): [VariableAccess] c
# 1921| Type = [Class] C
# 1921| ValueCategory = lvalue
# 1921| getArgument(0): [Literal] 10
# 1921| Type = [IntType] int
# 1921| Value = [Literal] 10
# 1921| ValueCategory = prvalue
# 1922| getStmt(3): [DeclStmt] declaration
# 1922| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y
# 1922| Type = [IntType] int
# 1923| getStmt(4): [ExprStmt] ExprStmt
# 1923| getExpr(): [AssignExpr] ... = ...
# 1923| Type = [IntType] int
# 1923| ValueCategory = lvalue
# 1923| getLValue(): [VariableAccess] y
# 1923| Type = [IntType] int
# 1923| ValueCategory = lvalue
# 1923| getRValue(): [FunctionCall] call to StaticMemberFunction
# 1923| Type = [IntType] int
# 1923| ValueCategory = prvalue
# 1923| getArgument(0): [Literal] 10
# 1923| Type = [IntType] int
# 1923| Value = [Literal] 10
# 1923| ValueCategory = prvalue
# 1924| getStmt(5): [DeclStmt] declaration
# 1924| getDeclarationEntry(0): [VariableDeclarationEntry] definition of z
# 1924| Type = [IntType] int
# 1925| getStmt(6): [ExprStmt] ExprStmt
# 1925| getExpr(): [AssignExpr] ... = ...
# 1925| Type = [IntType] int
# 1925| ValueCategory = lvalue
# 1925| getLValue(): [VariableAccess] z
# 1925| Type = [IntType] int
# 1925| ValueCategory = lvalue
# 1925| getRValue(): [FunctionCall] call to static_function
# 1925| Type = [IntType] int
# 1925| ValueCategory = prvalue
# 1925| getArgument(0): [Literal] 10
# 1925| Type = [IntType] int
# 1925| Value = [Literal] 10
# 1925| ValueCategory = prvalue
# 1926| getStmt(7): [ReturnStmt] return ...
# 1928| [TopLevelFunction] void test_double_assign()
# 1928| <params>:
# 1928| getEntryPoint(): [BlockStmt] { ... }
# 1929| getStmt(0): [DeclStmt] declaration
# 1929| getDeclarationEntry(0): [VariableDeclarationEntry] definition of i
# 1929| Type = [IntType] int
# 1929| getDeclarationEntry(1): [VariableDeclarationEntry] definition of j
# 1929| Type = [IntType] int
# 1930| getStmt(1): [ExprStmt] ExprStmt
# 1930| getExpr(): [AssignExpr] ... = ...
# 1930| Type = [IntType] int
# 1930| ValueCategory = lvalue
# 1930| getLValue(): [VariableAccess] i
# 1930| Type = [IntType] int
# 1930| ValueCategory = lvalue
# 1930| getRValue(): [AssignExpr] ... = ...
# 1930| Type = [IntType] int
# 1930| ValueCategory = prvalue
# 1930| getLValue(): [VariableAccess] j
# 1930| Type = [IntType] int
# 1930| ValueCategory = lvalue
# 1930| getRValue(): [Literal] 40
# 1930| Type = [IntType] int
# 1930| Value = [Literal] 40
# 1930| ValueCategory = prvalue
# 1931| getStmt(2): [ReturnStmt] return ...
perf-regression.cpp:
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
# 4| <params>:

View File

@@ -1911,4 +1911,23 @@ int noreturnTest2(int x) {
return x;
}
int static_function(int x) {
return x;
}
void test_static_functions_with_assignments() {
C c;
int x;
x = c.StaticMemberFunction(10);
int y;
y = C::StaticMemberFunction(10);
int z;
z = static_function(10);
}
void test_double_assign() {
int i, j;
i = j = 40;
}
// semmle-extractor-options: -std=c++17 --clang

View File

@@ -8821,6 +8821,62 @@
| ir.cpp:1911:12:1911:12 | Address | &:r1911_2 |
| ir.cpp:1911:12:1911:12 | Load | m1907_6 |
| ir.cpp:1911:12:1911:12 | StoreValue | r1911_3 |
| ir.cpp:1914:5:1914:19 | Address | &:r1914_7 |
| ir.cpp:1914:5:1914:19 | ChiPartial | partial:m1914_3 |
| ir.cpp:1914:5:1914:19 | ChiTotal | total:m1914_2 |
| ir.cpp:1914:5:1914:19 | Load | m1915_4 |
| ir.cpp:1914:5:1914:19 | SideEffect | m1914_3 |
| ir.cpp:1914:25:1914:25 | Address | &:r1914_5 |
| ir.cpp:1915:5:1915:13 | Address | &:r1915_1 |
| ir.cpp:1915:12:1915:12 | Address | &:r1915_2 |
| ir.cpp:1915:12:1915:12 | Load | m1914_6 |
| ir.cpp:1915:12:1915:12 | StoreValue | r1915_3 |
| ir.cpp:1918:6:1918:43 | ChiPartial | partial:m1918_3 |
| ir.cpp:1918:6:1918:43 | ChiTotal | total:m1918_2 |
| ir.cpp:1918:6:1918:43 | SideEffect | ~m1925_5 |
| ir.cpp:1919:7:1919:7 | Address | &:r1919_1 |
| ir.cpp:1919:7:1919:7 | Address | &:r1919_1 |
| ir.cpp:1919:7:1919:7 | Arg(this) | this:r1919_1 |
| ir.cpp:1919:7:1919:7 | CallTarget | func:r1919_3 |
| ir.cpp:1919:7:1919:7 | ChiPartial | partial:m1919_5 |
| ir.cpp:1919:7:1919:7 | ChiPartial | partial:m1919_7 |
| ir.cpp:1919:7:1919:7 | ChiTotal | total:m1918_4 |
| ir.cpp:1919:7:1919:7 | ChiTotal | total:m1919_2 |
| ir.cpp:1919:7:1919:7 | SideEffect | ~m1918_4 |
| ir.cpp:1920:9:1920:9 | Address | &:r1920_1 |
| ir.cpp:1921:5:1921:5 | Address | &:r1921_7 |
| ir.cpp:1921:11:1921:30 | CallTarget | func:r1921_2 |
| ir.cpp:1921:11:1921:30 | ChiPartial | partial:m1921_5 |
| ir.cpp:1921:11:1921:30 | ChiTotal | total:m1919_6 |
| ir.cpp:1921:11:1921:30 | SideEffect | ~m1919_6 |
| ir.cpp:1921:11:1921:30 | StoreValue | r1921_4 |
| ir.cpp:1921:32:1921:33 | Arg(0) | 0:r1921_3 |
| ir.cpp:1922:9:1922:9 | Address | &:r1922_1 |
| ir.cpp:1923:5:1923:5 | Address | &:r1923_6 |
| ir.cpp:1923:9:1923:31 | CallTarget | func:r1923_1 |
| ir.cpp:1923:9:1923:31 | ChiPartial | partial:m1923_4 |
| ir.cpp:1923:9:1923:31 | ChiTotal | total:m1921_6 |
| ir.cpp:1923:9:1923:31 | SideEffect | ~m1921_6 |
| ir.cpp:1923:9:1923:31 | StoreValue | r1923_3 |
| ir.cpp:1923:33:1923:34 | Arg(0) | 0:r1923_2 |
| ir.cpp:1924:9:1924:9 | Address | &:r1924_1 |
| ir.cpp:1925:5:1925:5 | Address | &:r1925_6 |
| ir.cpp:1925:9:1925:23 | CallTarget | func:r1925_1 |
| ir.cpp:1925:9:1925:23 | ChiPartial | partial:m1925_4 |
| ir.cpp:1925:9:1925:23 | ChiTotal | total:m1923_5 |
| ir.cpp:1925:9:1925:23 | SideEffect | ~m1923_5 |
| ir.cpp:1925:9:1925:23 | StoreValue | r1925_3 |
| ir.cpp:1925:25:1925:26 | Arg(0) | 0:r1925_2 |
| ir.cpp:1928:6:1928:23 | ChiPartial | partial:m1928_3 |
| ir.cpp:1928:6:1928:23 | ChiTotal | total:m1928_2 |
| ir.cpp:1928:6:1928:23 | SideEffect | m1928_3 |
| ir.cpp:1929:7:1929:7 | Address | &:r1929_1 |
| ir.cpp:1929:10:1929:10 | Address | &:r1929_3 |
| ir.cpp:1930:3:1930:3 | Address | &:r1930_5 |
| ir.cpp:1930:7:1930:7 | Address | &:r1930_2 |
| ir.cpp:1930:7:1930:12 | StoreValue | r1930_4 |
| ir.cpp:1930:11:1930:12 | StoreValue | r1930_1 |
| ir.cpp:1930:11:1930:12 | Unary | r1930_1 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_7 |

View File

@@ -10167,6 +10167,83 @@ ir.cpp:
# 1907| v1907_9(void) = AliasedUse : ~m?
# 1907| v1907_10(void) = ExitFunction :
# 1914| int static_function(int)
# 1914| Block 0
# 1914| v1914_1(void) = EnterFunction :
# 1914| mu1914_2(unknown) = AliasedDefinition :
# 1914| mu1914_3(unknown) = InitializeNonLocal :
# 1914| r1914_4(glval<int>) = VariableAddress[x] :
# 1914| mu1914_5(int) = InitializeParameter[x] : &:r1914_4
# 1915| r1915_1(glval<int>) = VariableAddress[#return] :
# 1915| r1915_2(glval<int>) = VariableAddress[x] :
# 1915| r1915_3(int) = Load[x] : &:r1915_2, ~m?
# 1915| mu1915_4(int) = Store[#return] : &:r1915_1, r1915_3
# 1914| r1914_6(glval<int>) = VariableAddress[#return] :
# 1914| v1914_7(void) = ReturnValue : &:r1914_6, ~m?
# 1914| v1914_8(void) = AliasedUse : ~m?
# 1914| v1914_9(void) = ExitFunction :
# 1918| void test_static_functions_with_assignments()
# 1918| Block 0
# 1918| v1918_1(void) = EnterFunction :
# 1918| mu1918_2(unknown) = AliasedDefinition :
# 1918| mu1918_3(unknown) = InitializeNonLocal :
# 1919| r1919_1(glval<C>) = VariableAddress[c] :
# 1919| mu1919_2(C) = Uninitialized[c] : &:r1919_1
# 1919| r1919_3(glval<unknown>) = FunctionAddress[C] :
# 1919| v1919_4(void) = Call[C] : func:r1919_3, this:r1919_1
# 1919| mu1919_5(unknown) = ^CallSideEffect : ~m?
# 1919| mu1919_6(C) = ^IndirectMayWriteSideEffect[-1] : &:r1919_1
# 1920| r1920_1(glval<int>) = VariableAddress[x] :
# 1920| mu1920_2(int) = Uninitialized[x] : &:r1920_1
# 1921| r1921_1(glval<C>) = VariableAddress[c] :
# 1921| r1921_2(glval<unknown>) = FunctionAddress[StaticMemberFunction] :
# 1921| r1921_3(int) = Constant[10] :
# 1921| r1921_4(int) = Call[StaticMemberFunction] : func:r1921_2, 0:r1921_3
# 1921| mu1921_5(unknown) = ^CallSideEffect : ~m?
# 1921| r1921_6(glval<int>) = VariableAddress[x] :
# 1921| mu1921_7(int) = Store[x] : &:r1921_6, r1921_4
# 1922| r1922_1(glval<int>) = VariableAddress[y] :
# 1922| mu1922_2(int) = Uninitialized[y] : &:r1922_1
# 1923| r1923_1(glval<unknown>) = FunctionAddress[StaticMemberFunction] :
# 1923| r1923_2(int) = Constant[10] :
# 1923| r1923_3(int) = Call[StaticMemberFunction] : func:r1923_1, 0:r1923_2
# 1923| mu1923_4(unknown) = ^CallSideEffect : ~m?
# 1923| r1923_5(glval<int>) = VariableAddress[y] :
# 1923| mu1923_6(int) = Store[y] : &:r1923_5, r1923_3
# 1924| r1924_1(glval<int>) = VariableAddress[z] :
# 1924| mu1924_2(int) = Uninitialized[z] : &:r1924_1
# 1925| r1925_1(glval<unknown>) = FunctionAddress[static_function] :
# 1925| r1925_2(int) = Constant[10] :
# 1925| r1925_3(int) = Call[static_function] : func:r1925_1, 0:r1925_2
# 1925| mu1925_4(unknown) = ^CallSideEffect : ~m?
# 1925| r1925_5(glval<int>) = VariableAddress[z] :
# 1925| mu1925_6(int) = Store[z] : &:r1925_5, r1925_3
# 1926| v1926_1(void) = NoOp :
# 1918| v1918_4(void) = ReturnVoid :
# 1918| v1918_5(void) = AliasedUse : ~m?
# 1918| v1918_6(void) = ExitFunction :
# 1928| void test_double_assign()
# 1928| Block 0
# 1928| v1928_1(void) = EnterFunction :
# 1928| mu1928_2(unknown) = AliasedDefinition :
# 1928| mu1928_3(unknown) = InitializeNonLocal :
# 1929| r1929_1(glval<int>) = VariableAddress[i] :
# 1929| mu1929_2(int) = Uninitialized[i] : &:r1929_1
# 1929| r1929_3(glval<int>) = VariableAddress[j] :
# 1929| mu1929_4(int) = Uninitialized[j] : &:r1929_3
# 1930| r1930_1(int) = Constant[40] :
# 1930| r1930_2(glval<int>) = VariableAddress[j] :
# 1930| mu1930_3(int) = Store[j] : &:r1930_2, r1930_1
# 1930| r1930_4(int) = CopyValue : r1930_1
# 1930| r1930_5(glval<int>) = VariableAddress[i] :
# 1930| mu1930_6(int) = Store[i] : &:r1930_5, r1930_4
# 1931| v1931_1(void) = NoOp :
# 1928| v1928_4(void) = ReturnVoid :
# 1928| v1928_5(void) = AliasedUse : ~m?
# 1928| v1928_6(void) = ExitFunction :
perf-regression.cpp:
# 6| void Big::Big()
# 6| Block 0

View File

@@ -70,3 +70,28 @@ int f4(int x) {
}
}
}
// No interesting ranges to check here - this irreducible CFG caused an infinite loop due to back edge detection
void gotoLoop(bool b1, bool b2)
{
int j;
if (b1)
return;
if (!b2)
{
for (j = 0; j < 10; ++j)
{
goto main_decode_loop;
}
}
else
{
for (j = 0; j < 10; ++j)
{
int x;
main_decode_loop:
}
}
}

View File

@@ -1,8 +1,9 @@
edges
| test.cpp:16:11:16:21 | mk_string_t indirection [string] | test.cpp:39:21:39:31 | call to mk_string_t indirection [string] |
| test.cpp:18:5:18:30 | ... = ... | test.cpp:18:10:18:15 | str indirection [post update] [string] |
| test.cpp:18:10:18:15 | str indirection [post update] [string] | test.cpp:16:11:16:21 | mk_string_t indirection [string] |
| test.cpp:18:10:18:15 | str indirection [post update] [string] | test.cpp:19:5:19:7 | str indirection [string] |
| test.cpp:18:19:18:24 | call to malloc | test.cpp:18:5:18:30 | ... = ... |
| test.cpp:19:5:19:7 | str indirection [string] | test.cpp:16:11:16:21 | mk_string_t indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:42:13:42:15 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:72:17:72:19 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:80:17:80:19 | str indirection [string] |
@@ -17,8 +18,9 @@ edges
| test.cpp:80:22:80:27 | string indirection | test.cpp:80:22:80:27 | string |
| test.cpp:88:11:88:30 | mk_string_t_plus_one indirection [string] | test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] |
| test.cpp:90:5:90:34 | ... = ... | test.cpp:90:10:90:15 | str indirection [post update] [string] |
| test.cpp:90:10:90:15 | str indirection [post update] [string] | test.cpp:88:11:88:30 | mk_string_t_plus_one indirection [string] |
| test.cpp:90:10:90:15 | str indirection [post update] [string] | test.cpp:91:5:91:7 | str indirection [string] |
| test.cpp:90:19:90:24 | call to malloc | test.cpp:90:5:90:34 | ... = ... |
| test.cpp:91:5:91:7 | str indirection [string] | test.cpp:88:11:88:30 | mk_string_t_plus_one indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:99:13:99:15 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:129:17:129:19 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:137:17:137:19 | str indirection [string] |
@@ -32,16 +34,17 @@ edges
| test.cpp:137:17:137:19 | str indirection [string] | test.cpp:137:22:137:27 | string indirection |
| test.cpp:137:22:137:27 | string indirection | test.cpp:137:22:137:27 | string |
| test.cpp:147:5:147:34 | ... = ... | test.cpp:147:10:147:15 | str indirection [post update] [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:152:13:152:15 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:154:13:154:15 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:156:13:156:15 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:175:17:175:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:187:17:187:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:195:17:195:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:199:17:199:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:203:17:203:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:207:17:207:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:148:5:148:7 | str indirection [string] |
| test.cpp:147:19:147:24 | call to malloc | test.cpp:147:5:147:34 | ... = ... |
| test.cpp:148:5:148:7 | str indirection [string] | test.cpp:152:13:152:15 | str indirection [string] |
| test.cpp:148:5:148:7 | str indirection [string] | test.cpp:154:13:154:15 | str indirection [string] |
| test.cpp:148:5:148:7 | str indirection [string] | test.cpp:156:13:156:15 | str indirection [string] |
| test.cpp:148:5:148:7 | str indirection [string] | test.cpp:175:17:175:19 | str indirection [string] |
| test.cpp:148:5:148:7 | str indirection [string] | test.cpp:187:17:187:19 | str indirection [string] |
| test.cpp:148:5:148:7 | str indirection [string] | test.cpp:195:17:195:19 | str indirection [string] |
| test.cpp:148:5:148:7 | str indirection [string] | test.cpp:199:17:199:19 | str indirection [string] |
| test.cpp:148:5:148:7 | str indirection [string] | test.cpp:203:17:203:19 | str indirection [string] |
| test.cpp:148:5:148:7 | str indirection [string] | test.cpp:207:17:207:19 | str indirection [string] |
| test.cpp:152:13:152:15 | str indirection [string] | test.cpp:152:18:152:23 | string |
| test.cpp:152:13:152:15 | str indirection [string] | test.cpp:152:18:152:23 | string indirection |
| test.cpp:152:18:152:23 | string indirection | test.cpp:152:18:152:23 | string |
@@ -91,6 +94,7 @@ nodes
| test.cpp:18:5:18:30 | ... = ... | semmle.label | ... = ... |
| test.cpp:18:10:18:15 | str indirection [post update] [string] | semmle.label | str indirection [post update] [string] |
| test.cpp:18:19:18:24 | call to malloc | semmle.label | call to malloc |
| test.cpp:19:5:19:7 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | semmle.label | call to mk_string_t indirection [string] |
| test.cpp:42:13:42:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:42:18:42:23 | string | semmle.label | string |
@@ -105,6 +109,7 @@ nodes
| test.cpp:90:5:90:34 | ... = ... | semmle.label | ... = ... |
| test.cpp:90:10:90:15 | str indirection [post update] [string] | semmle.label | str indirection [post update] [string] |
| test.cpp:90:19:90:24 | call to malloc | semmle.label | call to malloc |
| test.cpp:91:5:91:7 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | semmle.label | call to mk_string_t_plus_one indirection [string] |
| test.cpp:99:13:99:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:99:18:99:23 | string | semmle.label | string |
@@ -118,6 +123,7 @@ nodes
| test.cpp:147:5:147:34 | ... = ... | semmle.label | ... = ... |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | semmle.label | str indirection [post update] [string] |
| test.cpp:147:19:147:24 | call to malloc | semmle.label | call to malloc |
| test.cpp:148:5:148:7 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:152:13:152:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:152:18:152:23 | string | semmle.label | string |
| test.cpp:152:18:152:23 | string indirection | semmle.label | string indirection |

View File

@@ -8,13 +8,19 @@ edges
| overflowdestination.cpp:23:45:23:48 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection |
| overflowdestination.cpp:23:45:23:48 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection |
| overflowdestination.cpp:43:8:43:10 | fgets output argument | overflowdestination.cpp:46:15:46:17 | src indirection |
| overflowdestination.cpp:50:52:50:54 | src indirection | overflowdestination.cpp:53:9:53:12 | memcpy output argument |
| overflowdestination.cpp:50:52:50:54 | src indirection | overflowdestination.cpp:53:15:53:17 | src indirection |
| overflowdestination.cpp:50:52:50:54 | src indirection | overflowdestination.cpp:53:15:53:17 | src indirection |
| overflowdestination.cpp:50:52:50:54 | src indirection | overflowdestination.cpp:54:9:54:12 | memcpy output argument |
| overflowdestination.cpp:53:9:53:12 | memcpy output argument | overflowdestination.cpp:54:9:54:12 | memcpy output argument |
| overflowdestination.cpp:54:9:54:12 | memcpy output argument | overflowdestination.cpp:54:9:54:12 | memcpy output argument |
| overflowdestination.cpp:57:52:57:54 | src indirection | overflowdestination.cpp:64:16:64:19 | src2 indirection |
| overflowdestination.cpp:57:52:57:54 | src indirection | overflowdestination.cpp:64:16:64:19 | src2 indirection |
| overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:75:30:75:32 | src indirection |
| overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:76:30:76:32 | src indirection |
| overflowdestination.cpp:75:30:75:32 | overflowdest_test2 output argument | overflowdestination.cpp:76:30:76:32 | src indirection |
| overflowdestination.cpp:75:30:75:32 | src indirection | overflowdestination.cpp:50:52:50:54 | src indirection |
| overflowdestination.cpp:75:30:75:32 | src indirection | overflowdestination.cpp:75:30:75:32 | overflowdest_test2 output argument |
| overflowdestination.cpp:76:30:76:32 | src indirection | overflowdestination.cpp:57:52:57:54 | src indirection |
nodes
| main.cpp:6:27:6:30 | argv indirection | semmle.label | argv indirection |
@@ -28,15 +34,20 @@ nodes
| overflowdestination.cpp:43:8:43:10 | fgets output argument | semmle.label | fgets output argument |
| overflowdestination.cpp:46:15:46:17 | src indirection | semmle.label | src indirection |
| overflowdestination.cpp:50:52:50:54 | src indirection | semmle.label | src indirection |
| overflowdestination.cpp:53:9:53:12 | memcpy output argument | semmle.label | memcpy output argument |
| overflowdestination.cpp:53:15:53:17 | src indirection | semmle.label | src indirection |
| overflowdestination.cpp:53:15:53:17 | src indirection | semmle.label | src indirection |
| overflowdestination.cpp:54:9:54:12 | memcpy output argument | semmle.label | memcpy output argument |
| overflowdestination.cpp:57:52:57:54 | src indirection | semmle.label | src indirection |
| overflowdestination.cpp:64:16:64:19 | src2 indirection | semmle.label | src2 indirection |
| overflowdestination.cpp:64:16:64:19 | src2 indirection | semmle.label | src2 indirection |
| overflowdestination.cpp:73:8:73:10 | fgets output argument | semmle.label | fgets output argument |
| overflowdestination.cpp:75:30:75:32 | overflowdest_test2 output argument | semmle.label | overflowdest_test2 output argument |
| overflowdestination.cpp:75:30:75:32 | src indirection | semmle.label | src indirection |
| overflowdestination.cpp:76:30:76:32 | src indirection | semmle.label | src indirection |
subpaths
| overflowdestination.cpp:75:30:75:32 | src indirection | overflowdestination.cpp:50:52:50:54 | src indirection | overflowdestination.cpp:53:9:53:12 | memcpy output argument | overflowdestination.cpp:75:30:75:32 | overflowdest_test2 output argument |
| overflowdestination.cpp:75:30:75:32 | src indirection | overflowdestination.cpp:50:52:50:54 | src indirection | overflowdestination.cpp:54:9:54:12 | memcpy output argument | overflowdestination.cpp:75:30:75:32 | overflowdest_test2 output argument |
#select
| overflowdestination.cpp:30:2:30:8 | call to strncpy | main.cpp:6:27:6:30 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |
| overflowdestination.cpp:30:2:30:8 | call to strncpy | main.cpp:6:27:6:30 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |

View File

@@ -1,6 +1,7 @@
| test.c:4:14:4:18 | ... < ... | Comparison between $@ of type char and $@ of wider type int. | test.c:3:7:3:7 | c | c | test.c:2:17:2:17 | x | x |
| test.c:9:14:9:18 | ... > ... | Comparison between $@ of type char and $@ of wider type int. | test.c:8:7:8:7 | c | c | test.c:7:17:7:17 | x | x |
| test.c:14:14:14:18 | ... < ... | Comparison between $@ of type short and $@ of wider type int. | test.c:13:8:13:8 | s | s | test.c:12:17:12:17 | x | x |
| test.c:42:15:42:29 | ... < ... | Comparison between $@ of type short and $@ of wider type int. | test.c:41:9:41:10 | s1 | s1 | test.c:42:20:42:29 | 65535 | 65535 |
| test.c:65:14:65:18 | ... < ... | Comparison between $@ of type short and $@ of wider type int. | test.c:64:8:64:8 | s | s | test.c:63:17:63:17 | x | x |
| test.c:87:14:87:18 | ... < ... | Comparison between $@ of type unsigned char and $@ of wider type unsigned int. | test.c:83:16:83:16 | c | c | test.c:84:15:84:15 | x | x |
| test.c:91:14:91:23 | ... < ... | Comparison between $@ of type unsigned char and $@ of wider type int. | test.c:83:16:83:16 | c | c | test.c:91:18:91:23 | 65280 | 65280 |
@@ -13,3 +14,4 @@
| test.c:107:14:107:26 | ... < ... | Comparison between $@ of type unsigned char and $@ of wider type unsigned int. | test.c:83:16:83:16 | c | c | test.c:107:19:107:25 | ... >> ... | ... >> ... |
| test.c:128:15:128:21 | ... < ... | Comparison between $@ of type unsigned char and $@ of wider type unsigned int. | test.c:121:16:121:17 | uc | uc | test.c:123:19:123:20 | sz | sz |
| test.c:139:15:139:21 | ... < ... | Comparison between $@ of type unsigned char and $@ of wider type unsigned int. | test.c:121:16:121:17 | uc | uc | test.c:123:19:123:20 | sz | sz |
| test.c:156:9:156:14 | ... < ... | Comparison between $@ of type short and $@ of wider type int. | test.c:150:8:150:8 | s | s | test.c:151:6:151:7 | sx | sx |

View File

@@ -39,7 +39,7 @@ void test5 () {
void test6() {
short s1;
for (s1 = 0; s1 < 0x0000ffff; s1++) {}
for (s1 = 0; s1 < 0x0000ffff; s1++) {} // BAD
}
void test7(long long l) {
@@ -145,3 +145,22 @@ void test13() {
sz = (unsigned)sx & (unsigned)sy;
for (uc = 0; uc < sz; uc++) {} // GOOD
}
void test14() {
short s = 0;
int sx = 0x7FFF + 1;
// BAD: 's' is compared with a value of a wider type.
// 's' overflows before reaching 'sx',
// causing an infinite loop
while (s < sx) {
s += 1;
}
unsigned int ux = 0;
// GOOD: 'ux' has a type at least as wide as 'max_get'
while (ux < sx) {
ux += 1;
}
}

View File

@@ -6,3 +6,4 @@ dependencies:
codeql/cpp-queries: ${workspace}
extractor: cpp
tests: .
warnOnImplicitThis: true