Skip to content

Commit 24d740b

Browse files
author
Benjamin Muskalla
committed
Merge branch 'main' into inlineFlowTest
2 parents bf5a46f + 47b5165 commit 24d740b

File tree

354 files changed

+12576
-2394
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

354 files changed

+12576
-2394
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
lgtm,codescanning
2+
* The `SimpleRangeAnalysis` library includes information from the
3+
immediate guard for determining the upper bound of a stack
4+
variable for improved accuracy.

cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll

Lines changed: 123 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -923,28 +923,29 @@ private module Stage2 {
923923

924924
ApOption apSome(Ap ap) { result = TBooleanSome(ap) }
925925

926-
class Cc = boolean;
927-
928-
class CcCall extends Cc {
929-
CcCall() { this = true }
926+
class Cc = CallContext;
930927

931-
/** Holds if this call context may be `call`. */
932-
predicate matchesCall(DataFlowCall call) { any() }
933-
}
928+
class CcCall = CallContextCall;
934929

935-
class CcNoCall extends Cc {
936-
CcNoCall() { this = false }
937-
}
930+
class CcNoCall = CallContextNoCall;
938931

939-
Cc ccNone() { result = false }
932+
Cc ccNone() { result instanceof CallContextAny }
940933

941934
private class LocalCc = Unit;
942935

943936
bindingset[call, c, outercc]
944-
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
937+
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
938+
checkCallContextCall(outercc, call, c) and
939+
if recordDataFlowCallSiteDispatch(call, c)
940+
then result = TSpecificCall(call)
941+
else result = TSomeCall()
942+
}
945943

946944
bindingset[call, c, innercc]
947-
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
945+
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
946+
checkCallContextReturn(innercc, c, call) and
947+
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
948+
}
948949

949950
bindingset[node, cc, config]
950951
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1172,7 +1173,8 @@ private module Stage2 {
11721173
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
11731174
pragma[only_bind_into](config)) and
11741175
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
1175-
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
1176+
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
1177+
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
11761178
pragma[only_bind_into](config))
11771179
)
11781180
}
@@ -1860,7 +1862,8 @@ private module Stage3 {
18601862
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
18611863
pragma[only_bind_into](config)) and
18621864
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
1863-
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
1865+
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
1866+
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
18641867
pragma[only_bind_into](config))
18651868
)
18661869
}
@@ -2117,7 +2120,7 @@ private module Stage3 {
21172120
private predicate flowCandSummaryCtx(NodeEx node, AccessPathFront argApf, Configuration config) {
21182121
exists(AccessPathFront apf |
21192122
Stage3::revFlow(node, true, _, apf, config) and
2120-
Stage3::fwdFlow(node, true, TAccessPathFrontSome(argApf), apf, config)
2123+
Stage3::fwdFlow(node, any(Stage3::CcCall ccc), TAccessPathFrontSome(argApf), apf, config)
21212124
)
21222125
}
21232126

@@ -2618,7 +2621,8 @@ private module Stage4 {
26182621
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
26192622
pragma[only_bind_into](config)) and
26202623
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
2621-
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
2624+
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
2625+
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
26222626
pragma[only_bind_into](config))
26232627
)
26242628
}
@@ -3258,24 +3262,16 @@ class PathNode extends TPathNode {
32583262
/** Gets the associated configuration. */
32593263
Configuration getConfiguration() { none() }
32603264

3261-
private predicate isHidden() {
3262-
hiddenNode(this.(PathNodeImpl).getNodeEx().asNode()) and
3263-
not this.isSource() and
3264-
not this instanceof PathNodeSink
3265-
or
3266-
this.(PathNodeImpl).getNodeEx() instanceof TNodeImplicitRead
3267-
}
3268-
32693265
private PathNode getASuccessorIfHidden() {
3270-
this.isHidden() and
3266+
this.(PathNodeImpl).isHidden() and
32713267
result = this.(PathNodeImpl).getASuccessorImpl()
32723268
}
32733269

32743270
/** Gets a successor of this node, if any. */
32753271
final PathNode getASuccessor() {
32763272
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
3277-
not this.isHidden() and
3278-
not result.isHidden()
3273+
not this.(PathNodeImpl).isHidden() and
3274+
not result.(PathNodeImpl).isHidden()
32793275
}
32803276

32813277
/** Holds if this node is a source. */
@@ -3287,6 +3283,14 @@ abstract private class PathNodeImpl extends PathNode {
32873283

32883284
abstract NodeEx getNodeEx();
32893285

3286+
predicate isHidden() {
3287+
hiddenNode(this.getNodeEx().asNode()) and
3288+
not this.isSource() and
3289+
not this instanceof PathNodeSink
3290+
or
3291+
this.getNodeEx() instanceof TNodeImplicitRead
3292+
}
3293+
32903294
private string ppAp() {
32913295
this instanceof PathNodeSink and result = ""
32923296
or
@@ -3313,10 +3317,15 @@ abstract private class PathNodeImpl extends PathNode {
33133317
}
33143318

33153319
/** Holds if `n` can reach a sink. */
3316-
private predicate reach(PathNode n) { n instanceof PathNodeSink or reach(n.getASuccessor()) }
3320+
private predicate directReach(PathNode n) {
3321+
n instanceof PathNodeSink or directReach(n.getASuccessor())
3322+
}
33173323

3318-
/** Holds if `n1.getSucc() = n2` and `n2` can reach a sink. */
3319-
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and reach(n2) }
3324+
/** Holds if `n` can reach a sink or is used in a subpath. */
3325+
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
3326+
3327+
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
3328+
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
33203329

33213330
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
33223331

@@ -3325,12 +3334,14 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
33253334
*/
33263335
module PathGraph {
33273336
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
3328-
query predicate edges(PathNode a, PathNode b) { pathSucc(a, b) }
3337+
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(b) }
33293338

33303339
/** Holds if `n` is a node in the graph of data flow path explanations. */
33313340
query predicate nodes(PathNode n, string key, string val) {
33323341
reach(n) and key = "semmle.label" and val = n.toString()
33333342
}
3343+
3344+
query predicate subpaths = Subpaths::subpaths/4;
33343345
}
33353346

33363347
/**
@@ -3622,6 +3633,86 @@ private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext c
36223633
)
36233634
}
36243635

3636+
private module Subpaths {
3637+
/**
3638+
* Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by
3639+
* `kind`, `sc`, `apout`, and `innercc`.
3640+
*/
3641+
pragma[nomagic]
3642+
private predicate subpaths01(
3643+
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
3644+
NodeEx out, AccessPath apout
3645+
) {
3646+
pathThroughCallable(arg, out, _, apout) and
3647+
pathIntoCallable(arg, par, _, innercc, sc, _) and
3648+
paramFlowsThrough(kind, innercc, sc, apout, _, unbindConf(arg.getConfiguration()))
3649+
}
3650+
3651+
/**
3652+
* Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by
3653+
* `kind`, `sc`, `apout`, and `innercc`.
3654+
*/
3655+
pragma[nomagic]
3656+
private predicate subpaths02(
3657+
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
3658+
NodeEx out, AccessPath apout
3659+
) {
3660+
subpaths01(arg, par, sc, innercc, kind, out, apout) and
3661+
out.asNode() = kind.getAnOutNode(_)
3662+
}
3663+
3664+
pragma[nomagic]
3665+
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
3666+
3667+
/**
3668+
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
3669+
*/
3670+
pragma[nomagic]
3671+
private predicate subpaths03(
3672+
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, AccessPath apout
3673+
) {
3674+
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
3675+
subpaths02(arg, par, sc, innercc, kind, out, apout) and
3676+
ret.getNodeEx() = retnode and
3677+
kind = retnode.getKind() and
3678+
innercc = ret.getCallContext() and
3679+
sc = ret.getSummaryCtx() and
3680+
ret.getConfiguration() = unbindConf(getPathNodeConf(arg)) and
3681+
apout = ret.getAp() and
3682+
not ret.isHidden()
3683+
)
3684+
}
3685+
3686+
/**
3687+
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
3688+
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
3689+
* `ret -> out` is summarized as the edge `arg -> out`.
3690+
*/
3691+
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeMid ret, PathNodeMid out) {
3692+
exists(ParamNodeEx p, NodeEx o, AccessPath apout |
3693+
arg.getASuccessor() = par and
3694+
arg.getASuccessor() = out and
3695+
subpaths03(arg, p, ret, o, apout) and
3696+
par.getNodeEx() = p and
3697+
out.getNodeEx() = o and
3698+
out.getAp() = apout
3699+
)
3700+
}
3701+
3702+
/**
3703+
* Holds if `n` can reach a return node in a summarized subpath.
3704+
*/
3705+
predicate retReach(PathNode n) {
3706+
subpaths(_, _, n, _)
3707+
or
3708+
exists(PathNode mid |
3709+
retReach(mid) and
3710+
n.getASuccessor() = mid and
3711+
not subpaths(_, mid, _, _)
3712+
)
3713+
}
3714+
}
3715+
36253716
/**
36263717
* Holds if data can flow (inter-procedurally) from `source` to `sink`.
36273718
*

0 commit comments

Comments
 (0)