Skip to content

Commit c3bc9f8

Browse files
committed
C#/C++/Java: Unbreak partial data flow support
Partial data flow had a semantic merge conflict with this branch. The problem is that partial data flow doesn't (and shouldn't) cause the initial pruning steps to run, but the length-2 access paths depend on the `consCand` information that comes from that initial pruning. The solution is to restore the old `AccessPath` class, now called `PartialAccessPath` for use only by partial data flow. With this change, partial data flow will in some cases allow more field flow than non-partial data flow.
1 parent dec0c3a commit c3bc9f8

File tree

20 files changed

+1682
-589
lines changed

20 files changed

+1682
-589
lines changed

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

Lines changed: 88 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2048,11 +2048,64 @@ private module FlowExploration {
20482048
result = distSrcExt(TCallable(c, config)) - 1
20492049
}
20502050

2051+
private newtype TPartialAccessPath =
2052+
TPartialNil(DataFlowType t) or
2053+
TPartialCons(Content f, int len) { len in [1 .. 5] }
2054+
2055+
/**
2056+
* Conceptually a list of `Content`s followed by a `Type`, but only the first
2057+
* element of the list and its length are tracked. If data flows from a source to
2058+
* a given node with a given `AccessPath`, this indicates the sequence of
2059+
* dereference operations needed to get from the value in the node to the
2060+
* tracked object. The final type indicates the type of the tracked object.
2061+
*/
2062+
private class PartialAccessPath extends TPartialAccessPath {
2063+
abstract string toString();
2064+
2065+
Content getHead() { this = TPartialCons(result, _) }
2066+
2067+
int len() {
2068+
this = TPartialNil(_) and result = 0
2069+
or
2070+
this = TPartialCons(_, result)
2071+
}
2072+
2073+
DataFlowType getType() {
2074+
this = TPartialNil(result)
2075+
or
2076+
exists(Content head | this = TPartialCons(head, _) | result = head.getContainerType())
2077+
}
2078+
2079+
abstract AccessPathFront getFront();
2080+
}
2081+
2082+
private class PartialAccessPathNil extends PartialAccessPath, TPartialNil {
2083+
override string toString() {
2084+
exists(DataFlowType t | this = TPartialNil(t) | result = ppReprType(t))
2085+
}
2086+
2087+
override AccessPathFront getFront() {
2088+
exists(DataFlowType t | this = TPartialNil(t) | result = TFrontNil(t))
2089+
}
2090+
}
2091+
2092+
private class PartialAccessPathCons extends PartialAccessPath, TPartialCons {
2093+
override string toString() {
2094+
exists(Content f, int len | this = TPartialCons(f, len) |
2095+
result = f.toString() + ", ... (" + len.toString() + ")"
2096+
)
2097+
}
2098+
2099+
override AccessPathFront getFront() {
2100+
exists(Content f | this = TPartialCons(f, _) | result = TFrontHead(f))
2101+
}
2102+
}
2103+
20512104
private newtype TPartialPathNode =
2052-
TPartialPathNodeMk(Node node, CallContext cc, AccessPath ap, Configuration config) {
2105+
TPartialPathNodeMk(Node node, CallContext cc, PartialAccessPath ap, Configuration config) {
20532106
config.isSource(node) and
20542107
cc instanceof CallContextAny and
2055-
ap = TNil(getErasedRepr(node.getType())) and
2108+
ap = TPartialNil(getErasedRepr(node.getType())) and
20562109
not fullBarrier(node, config) and
20572110
exists(config.explorationLimit())
20582111
or
@@ -2062,7 +2115,7 @@ private module FlowExploration {
20622115

20632116
pragma[nomagic]
20642117
private predicate partialPathNodeMk0(
2065-
Node node, CallContext cc, AccessPath ap, Configuration config
2118+
Node node, CallContext cc, PartialAccessPath ap, Configuration config
20662119
) {
20672120
exists(PartialPathNode mid |
20682121
partialPathStep(mid, node, cc, ap, config) and
@@ -2138,7 +2191,7 @@ private module FlowExploration {
21382191

21392192
CallContext cc;
21402193

2141-
AccessPath ap;
2194+
PartialAccessPath ap;
21422195

21432196
Configuration config;
21442197

@@ -2148,7 +2201,7 @@ private module FlowExploration {
21482201

21492202
CallContext getCallContext() { result = cc }
21502203

2151-
AccessPath getAp() { result = ap }
2204+
PartialAccessPath getAp() { result = ap }
21522205

21532206
override Configuration getConfiguration() { result = config }
21542207

@@ -2161,7 +2214,7 @@ private module FlowExploration {
21612214
}
21622215

21632216
private predicate partialPathStep(
2164-
PartialPathNodePriv mid, Node node, CallContext cc, AccessPath ap, Configuration config
2217+
PartialPathNodePriv mid, Node node, CallContext cc, PartialAccessPath ap, Configuration config
21652218
) {
21662219
localFlowStep(mid.getNode(), node, config) and
21672220
cc = mid.getCallContext() and
@@ -2170,8 +2223,8 @@ private module FlowExploration {
21702223
or
21712224
additionalLocalFlowStep(mid.getNode(), node, config) and
21722225
cc = mid.getCallContext() and
2173-
mid.getAp() instanceof AccessPathNil and
2174-
ap = TNil(getErasedRepr(node.getType())) and
2226+
mid.getAp() instanceof PartialAccessPathNil and
2227+
ap = TPartialNil(getErasedRepr(node.getType())) and
21752228
config = mid.getConfiguration()
21762229
or
21772230
jumpStep(mid.getNode(), node, config) and
@@ -2181,15 +2234,15 @@ private module FlowExploration {
21812234
or
21822235
additionalJumpStep(mid.getNode(), node, config) and
21832236
cc instanceof CallContextAny and
2184-
mid.getAp() instanceof AccessPathNil and
2185-
ap = TNil(getErasedRepr(node.getType())) and
2237+
mid.getAp() instanceof PartialAccessPathNil and
2238+
ap = TPartialNil(getErasedRepr(node.getType())) and
21862239
config = mid.getConfiguration()
21872240
or
21882241
partialPathStoreStep(mid, _, _, node, ap) and
21892242
cc = mid.getCallContext() and
21902243
config = mid.getConfiguration()
21912244
or
2192-
exists(AccessPath ap0, Content f |
2245+
exists(PartialAccessPath ap0, Content f |
21932246
partialPathReadStep(mid, ap0, f, node, cc, config) and
21942247
apConsFwd(ap, f, ap0, config)
21952248
)
@@ -2210,7 +2263,7 @@ private module FlowExploration {
22102263

22112264
pragma[inline]
22122265
private predicate partialPathStoreStep(
2213-
PartialPathNodePriv mid, AccessPath ap1, Content f, Node node, AccessPath ap2
2266+
PartialPathNodePriv mid, PartialAccessPath ap1, Content f, Node node, PartialAccessPath ap2
22142267
) {
22152268
ap1 = mid.getAp() and
22162269
store(mid.getNode(), f, node) and
@@ -2220,7 +2273,9 @@ private module FlowExploration {
22202273
}
22212274

22222275
pragma[nomagic]
2223-
private predicate apConsFwd(AccessPath ap1, Content f, AccessPath ap2, Configuration config) {
2276+
private predicate apConsFwd(
2277+
PartialAccessPath ap1, Content f, PartialAccessPath ap2, Configuration config
2278+
) {
22242279
exists(PartialPathNodePriv mid |
22252280
partialPathStoreStep(mid, ap1, f, _, ap2) and
22262281
config = mid.getConfiguration()
@@ -2229,7 +2284,7 @@ private module FlowExploration {
22292284

22302285
pragma[nomagic]
22312286
private predicate partialPathReadStep(
2232-
PartialPathNodePriv mid, AccessPath ap, Content f, Node node, CallContext cc,
2287+
PartialPathNodePriv mid, PartialAccessPath ap, Content f, Node node, CallContext cc,
22332288
Configuration config
22342289
) {
22352290
ap = mid.getAp() and
@@ -2240,7 +2295,7 @@ private module FlowExploration {
22402295
}
22412296

22422297
private predicate partialPathOutOfCallable0(
2243-
PartialPathNodePriv mid, ReturnPosition pos, CallContext innercc, AccessPath ap,
2298+
PartialPathNodePriv mid, ReturnPosition pos, CallContext innercc, PartialAccessPath ap,
22442299
Configuration config
22452300
) {
22462301
pos = getReturnPosition(mid.getNode()) and
@@ -2252,8 +2307,8 @@ private module FlowExploration {
22522307

22532308
pragma[noinline]
22542309
private predicate partialPathOutOfCallable1(
2255-
PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, AccessPath ap,
2256-
Configuration config
2310+
PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc,
2311+
PartialAccessPath ap, Configuration config
22572312
) {
22582313
exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc |
22592314
partialPathOutOfCallable0(mid, pos, innercc, ap, config) and
@@ -2266,7 +2321,7 @@ private module FlowExploration {
22662321
}
22672322

22682323
private predicate partialPathOutOfCallable(
2269-
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPath ap, Configuration config
2324+
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config
22702325
) {
22712326
exists(ReturnKind kind, DataFlowCall call |
22722327
partialPathOutOfCallable1(mid, call, kind, cc, ap, config)
@@ -2276,7 +2331,7 @@ private module FlowExploration {
22762331
}
22772332

22782333
private predicate partialPathOutOfArgument(
2279-
PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, AccessPath ap,
2334+
PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap,
22802335
Configuration config
22812336
) {
22822337
exists(
@@ -2302,7 +2357,7 @@ private module FlowExploration {
23022357
pragma[noinline]
23032358
private predicate partialPathIntoArg(
23042359
PartialPathNodePriv mid, int i, CallContext cc, DataFlowCall call, boolean emptyAp,
2305-
AccessPath ap, Configuration config
2360+
PartialAccessPath ap, Configuration config
23062361
) {
23072362
exists(ArgumentNode arg |
23082363
arg = mid.getNode() and
@@ -2311,24 +2366,24 @@ private module FlowExploration {
23112366
ap = mid.getAp() and
23122367
config = mid.getConfiguration()
23132368
|
2314-
ap instanceof AccessPathNil and emptyAp = true
2369+
ap instanceof PartialAccessPathNil and emptyAp = true
23152370
or
2316-
ap instanceof AccessPathCons and emptyAp = false
2371+
ap instanceof PartialAccessPathCons and emptyAp = false
23172372
)
23182373
}
23192374

23202375
pragma[nomagic]
23212376
private predicate partialPathIntoCallable0(
23222377
PartialPathNodePriv mid, DataFlowCallable callable, int i, CallContext outercc,
2323-
DataFlowCall call, boolean emptyAp, AccessPath ap, Configuration config
2378+
DataFlowCall call, boolean emptyAp, PartialAccessPath ap, Configuration config
23242379
) {
23252380
partialPathIntoArg(mid, i, outercc, call, emptyAp, ap, config) and
23262381
callable = resolveCall(call, outercc)
23272382
}
23282383

23292384
private predicate partialPathIntoCallable(
23302385
PartialPathNodePriv mid, ParameterNode p, CallContext outercc, CallContextCall innercc,
2331-
DataFlowCall call, AccessPath ap, Configuration config
2386+
DataFlowCall call, PartialAccessPath ap, Configuration config
23322387
) {
23332388
exists(int i, DataFlowCallable callable, boolean emptyAp |
23342389
partialPathIntoCallable0(mid, callable, i, outercc, call, emptyAp, ap, config) and
@@ -2342,7 +2397,8 @@ private module FlowExploration {
23422397

23432398
pragma[nomagic]
23442399
private predicate paramFlowsThroughInPartialPath(
2345-
ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config
2400+
ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil,
2401+
Configuration config
23462402
) {
23472403
exists(PartialPathNodePriv mid, ReturnNode ret |
23482404
mid.getNode() = ret and
@@ -2362,17 +2418,18 @@ private module FlowExploration {
23622418
pragma[noinline]
23632419
private predicate partialPathThroughCallable0(
23642420
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc,
2365-
AccessPathNil apnil, Configuration config
2421+
PartialAccessPathNil apnil, Configuration config
23662422
) {
2367-
exists(ParameterNode p, CallContext innercc, AccessPathNil midapnil |
2423+
exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil |
23682424
partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and
23692425
paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and
23702426
not parameterValueFlowsThrough(p, kind, innercc)
23712427
)
23722428
}
23732429

23742430
private predicate partialPathThroughCallable(
2375-
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPathNil apnil, Configuration config
2431+
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil,
2432+
Configuration config
23762433
) {
23772434
exists(DataFlowCall call, ReturnKind kind |
23782435
partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and
@@ -2382,8 +2439,8 @@ private module FlowExploration {
23822439

23832440
pragma[noinline]
23842441
private predicate valuePartialPathThroughCallable0(
2385-
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, AccessPath ap,
2386-
Configuration config
2442+
DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc,
2443+
PartialAccessPath ap, Configuration config
23872444
) {
23882445
exists(ParameterNode p, CallContext innercc |
23892446
partialPathIntoCallable(mid, p, cc, innercc, call, ap, config) and
@@ -2392,7 +2449,7 @@ private module FlowExploration {
23922449
}
23932450

23942451
private predicate valuePartialPathThroughCallable(
2395-
PartialPathNodePriv mid, OutNode out, CallContext cc, AccessPath ap, Configuration config
2452+
PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config
23962453
) {
23972454
exists(DataFlowCall call, ReturnKind kind |
23982455
valuePartialPathThroughCallable0(call, mid, kind, cc, ap, config) and

0 commit comments

Comments
 (0)