Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6aae51f

Browse files
committed
Dataflow: Sync.
1 parent 8f055f5 commit 6aae51f

24 files changed

Lines changed: 5876 additions & 220 deletions

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

Lines changed: 289 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,7 @@ private predicate nodeCand1(Node node, Configuration config) { nodeCand1(node, _
535535

536536
private predicate throughFlowNodeCand1(Node node, Configuration config) {
537537
nodeCand1(node, true, config) and
538+
nodeCandFwd1(node, true, config) and
538539
not fullBarrier(node, config) and
539540
not inBarrier(node, config) and
540541
not outBarrier(node, config)
@@ -1523,11 +1524,50 @@ private predicate flowCandIsReturned(
15231524
)
15241525
}
15251526

1527+
/**
1528+
* Holds if `argApf` is recorded as the summary context for flow reaching `node`
1529+
* and remains relevant for the following pruning stage.
1530+
*/
1531+
private predicate flowCandSummaryCtx(Node node, AccessPathFront argApf, Configuration config) {
1532+
exists(AccessPathFront apf |
1533+
flowCand(node, true, _, apf, config) and
1534+
flowCandFwd(node, true, TAccessPathFrontSome(argApf), apf, config)
1535+
)
1536+
}
1537+
1538+
/**
1539+
* Holds if a length 2 access path approximation with the head `tc` is expected
1540+
* to be expensive.
1541+
*/
1542+
private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) {
1543+
exists(int tails, int nodes, int apLimit, int tupleLimit |
1544+
tails = strictcount(AccessPathFront apf | flowCandConsCand(tc, apf, config)) and
1545+
nodes =
1546+
strictcount(Node n |
1547+
flowCand(n, _, _, any(AccessPathFrontHead apf | apf.headUsesContent(tc)), config)
1548+
or
1549+
flowCandSummaryCtx(n, any(AccessPathFrontHead apf | apf.headUsesContent(tc)), _)
1550+
) and
1551+
accessPathApproxCostLimits(apLimit, tupleLimit) and
1552+
apLimit < tails and
1553+
tupleLimit < (tails - 1) * nodes
1554+
)
1555+
}
1556+
15261557
private newtype TAccessPathApprox =
15271558
TNil(DataFlowType t) or
1528-
TConsNil(TypedContent tc, DataFlowType t) { flowCandConsCand(tc, TFrontNil(t), _) } or
1559+
TConsNil(TypedContent tc, DataFlowType t) {
1560+
flowCandConsCand(tc, TFrontNil(t), _) and
1561+
not expensiveLen2unfolding(tc, _)
1562+
} or
15291563
TConsCons(TypedContent tc1, TypedContent tc2, int len) {
1530-
flowCandConsCand(tc1, TFrontHead(tc2), _) and len in [2 .. accessPathLimit()]
1564+
flowCandConsCand(tc1, TFrontHead(tc2), _) and
1565+
len in [2 .. accessPathLimit()] and
1566+
not expensiveLen2unfolding(tc1, _)
1567+
} or
1568+
TCons1(TypedContent tc, int len) {
1569+
len in [1 .. accessPathLimit()] and
1570+
expensiveLen2unfolding(tc, _)
15311571
}
15321572

15331573
/**
@@ -1622,6 +1662,49 @@ private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons {
16221662
or
16231663
len = 2 and
16241664
result = TConsNil(tc2, _)
1665+
or
1666+
result = TCons1(tc2, len - 1)
1667+
)
1668+
}
1669+
}
1670+
1671+
private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 {
1672+
private TypedContent tc;
1673+
private int len;
1674+
1675+
AccessPathApproxCons1() { this = TCons1(tc, len) }
1676+
1677+
override string toString() {
1678+
if len = 1
1679+
then result = "[" + tc.toString() + "]"
1680+
else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]"
1681+
}
1682+
1683+
override TypedContent getHead() { result = tc }
1684+
1685+
override int len() { result = len }
1686+
1687+
override DataFlowType getType() { result = tc.getContainerType() }
1688+
1689+
override AccessPathFront getFront() { result = TFrontHead(tc) }
1690+
1691+
override AccessPathApprox pop(TypedContent head) {
1692+
head = tc and
1693+
(
1694+
exists(TypedContent tc2 | flowCandConsCand(tc, TFrontHead(tc2), _) |
1695+
result = TConsCons(tc2, _, len - 1)
1696+
or
1697+
len = 2 and
1698+
result = TConsNil(tc2, _)
1699+
or
1700+
result = TCons1(tc2, len - 1)
1701+
)
1702+
or
1703+
exists(DataFlowType t |
1704+
len = 1 and
1705+
flowCandConsCand(tc, TFrontNil(t), _) and
1706+
result = TNil(t)
1707+
)
16251708
)
16261709
}
16271710
}
@@ -2045,23 +2128,33 @@ private predicate flow(Node n, Configuration config) { flow(n, _, _, _, config)
20452128

20462129
pragma[noinline]
20472130
private predicate parameterFlow(
2048-
ParameterNode p, AccessPathApprox apa, DataFlowCallable c, Configuration config
2131+
ParameterNode p, AccessPathApprox apa, AccessPathApprox apa0, DataFlowCallable c,
2132+
Configuration config
20492133
) {
2050-
flow(p, true, _, apa, config) and
2134+
flow(p, true, TAccessPathApproxSome(apa0), apa, config) and
20512135
c = p.getEnclosingCallable()
20522136
}
20532137

2054-
private predicate parameterMayFlowThrough(ParameterNode p, AccessPathApprox apa) {
2138+
private predicate parameterMayFlowThrough(ParameterNode p, DataFlowCallable c, AccessPathApprox apa) {
20552139
exists(ReturnNodeExt ret, Configuration config, AccessPathApprox apa0 |
2056-
parameterFlow(p, apa, ret.getEnclosingCallable(), config) and
2140+
parameterFlow(p, apa, apa0, c, config) and
2141+
c = ret.getEnclosingCallable() and
20572142
flow(ret, true, TAccessPathApproxSome(_), apa0, config) and
20582143
flowFwd(ret, any(CallContextCall ccc), TAccessPathApproxSome(apa), _, apa0, config)
20592144
)
20602145
}
20612146

2147+
private predicate nodeMayUseSummary(Node n, AccessPathApprox apa) {
2148+
exists(DataFlowCallable c, AccessPathApprox apa0 |
2149+
parameterMayFlowThrough(_, c, apa) and
2150+
flow(n, true, _, apa0, _) and
2151+
flowFwd(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), _, apa0, _)
2152+
)
2153+
}
2154+
20622155
private newtype TSummaryCtx =
20632156
TSummaryCtxNone() or
2064-
TSummaryCtxSome(ParameterNode p, AccessPath ap) { parameterMayFlowThrough(p, ap.getApprox()) }
2157+
TSummaryCtxSome(ParameterNode p, AccessPath ap) { parameterMayFlowThrough(p, _, ap.getApprox()) }
20652158

20662159
/**
20672160
* A context for generating flow summaries. This represents flow entry through
@@ -2096,9 +2189,118 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
20962189
}
20972190
}
20982191

2192+
/**
2193+
* Gets the number of length 2 access path approximations that correspond to `apa`.
2194+
*/
2195+
private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) {
2196+
exists(TypedContent tc, int len |
2197+
tc = apa.getHead() and
2198+
len = apa.len() and
2199+
result =
2200+
strictcount(AccessPathFront apf |
2201+
flowConsCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1),
2202+
config)
2203+
)
2204+
)
2205+
}
2206+
2207+
/**
2208+
* Holds if a length 2 access path approximation matching `apa` is expected
2209+
* to be expensive.
2210+
*/
2211+
private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) {
2212+
exists(int aps, int nodes, int apLimit, int tupleLimit |
2213+
aps = count1to2unfold(apa, config) and
2214+
nodes =
2215+
strictcount(Node n |
2216+
flow(n, _, _, apa, config)
2217+
or
2218+
nodeMayUseSummary(n, apa)
2219+
) and
2220+
accessPathCostLimits(apLimit, tupleLimit) and
2221+
apLimit < aps and
2222+
tupleLimit < (aps - 1) * nodes
2223+
)
2224+
}
2225+
2226+
private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
2227+
exists(TypedContent head |
2228+
apa.pop(head) = result and
2229+
flowConsCand(head, result, config)
2230+
)
2231+
}
2232+
2233+
/**
2234+
* Holds with `unfold = false` if a precise head-tail representation of `apa` is
2235+
* expected to be expensive. Holds with `unfold = true` otherwise.
2236+
*/
2237+
private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
2238+
exists(int aps, int nodes, int apLimit, int tupleLimit |
2239+
aps = countPotentialAps(apa, config) and
2240+
nodes =
2241+
strictcount(Node n |
2242+
flow(n, _, _, apa, _)
2243+
or
2244+
nodeMayUseSummary(n, apa)
2245+
) and
2246+
accessPathCostLimits(apLimit, tupleLimit) and
2247+
if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
2248+
)
2249+
}
2250+
2251+
/**
2252+
* Gets the number of `AccessPath`s that correspond to `apa`.
2253+
*/
2254+
private int countAps(AccessPathApprox apa, Configuration config) {
2255+
evalUnfold(apa, false, config) and
2256+
result = 1 and
2257+
(not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config))
2258+
or
2259+
evalUnfold(apa, false, config) and
2260+
result = count1to2unfold(apa, config) and
2261+
not expensiveLen1to2unfolding(apa, config)
2262+
or
2263+
evalUnfold(apa, true, config) and
2264+
result = countPotentialAps(apa, config)
2265+
}
2266+
2267+
/**
2268+
* Gets the number of `AccessPath`s that would correspond to `apa` assuming
2269+
* that it is expanded to a precise head-tail representation.
2270+
*/
2271+
language[monotonicAggregates]
2272+
private int countPotentialAps(AccessPathApprox apa, Configuration config) {
2273+
apa instanceof AccessPathApproxNil and result = 1
2274+
or
2275+
result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config))
2276+
}
2277+
20992278
private newtype TAccessPath =
21002279
TAccessPathNil(DataFlowType t) or
2101-
TAccessPathCons(TypedContent head, AccessPath tail) { flowConsCand(head, tail.getApprox(), _) }
2280+
TAccessPathCons(TypedContent head, AccessPath tail) {
2281+
exists(AccessPathApproxCons apa |
2282+
not evalUnfold(apa, false, _) and
2283+
head = apa.getHead() and
2284+
tail.getApprox() = getATail(apa, _)
2285+
)
2286+
} or
2287+
TAccessPathCons2(TypedContent head1, TypedContent head2, int len) {
2288+
exists(AccessPathApproxCons apa |
2289+
evalUnfold(apa, false, _) and
2290+
not expensiveLen1to2unfolding(apa, _) and
2291+
apa.len() = len and
2292+
head1 = apa.getHead() and
2293+
head2 = getATail(apa, _).getHead()
2294+
)
2295+
} or
2296+
TAccessPathCons1(TypedContent head, int len) {
2297+
exists(AccessPathApproxCons apa |
2298+
evalUnfold(apa, false, _) and
2299+
expensiveLen1to2unfolding(apa, _) and
2300+
apa.len() = len and
2301+
head = apa.getHead()
2302+
)
2303+
}
21022304

21032305
private newtype TPathNode =
21042306
TPathNodeMid(Node node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) {
@@ -2202,20 +2404,96 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
22022404
result = TConsNil(head, tail.(AccessPathNil).getType())
22032405
or
22042406
result = TConsCons(head, tail.getHead(), this.length())
2407+
or
2408+
result = TCons1(head, this.length())
22052409
}
22062410

22072411
override int length() { result = 1 + tail.length() }
22082412

2209-
private string toStringImpl() {
2413+
private string toStringImpl(boolean needsSuffix) {
22102414
exists(DataFlowType t |
22112415
tail = TAccessPathNil(t) and
2416+
needsSuffix = false and
22122417
result = head.toString() + "]" + concat(" : " + ppReprType(t))
22132418
)
22142419
or
2215-
result = head + ", " + tail.(AccessPathCons).toStringImpl()
2420+
result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix)
2421+
or
2422+
exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) |
2423+
result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true
2424+
or
2425+
result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false
2426+
)
2427+
or
2428+
exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) |
2429+
result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true
2430+
or
2431+
result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false
2432+
)
22162433
}
22172434

2218-
override string toString() { result = "[" + this.toStringImpl() }
2435+
override string toString() {
2436+
result = "[" + this.toStringImpl(true) + length().toString() + ")]"
2437+
or
2438+
result = "[" + this.toStringImpl(false)
2439+
}
2440+
}
2441+
2442+
private class AccessPathCons2 extends AccessPath, TAccessPathCons2 {
2443+
private TypedContent head1;
2444+
private TypedContent head2;
2445+
private int len;
2446+
2447+
AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) }
2448+
2449+
override TypedContent getHead() { result = head1 }
2450+
2451+
override AccessPath getTail() {
2452+
flowConsCand(head1, result.getApprox(), _) and
2453+
result.getHead() = head2 and
2454+
result.length() = len - 1
2455+
}
2456+
2457+
override AccessPathFrontHead getFront() { result = TFrontHead(head1) }
2458+
2459+
override AccessPathApproxCons getApprox() {
2460+
result = TConsCons(head1, head2, len) or
2461+
result = TCons1(head1, len)
2462+
}
2463+
2464+
override int length() { result = len }
2465+
2466+
override string toString() {
2467+
if len = 2
2468+
then result = "[" + head1.toString() + ", " + head2.toString() + "]"
2469+
else
2470+
result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]"
2471+
}
2472+
}
2473+
2474+
private class AccessPathCons1 extends AccessPath, TAccessPathCons1 {
2475+
private TypedContent head;
2476+
private int len;
2477+
2478+
AccessPathCons1() { this = TAccessPathCons1(head, len) }
2479+
2480+
override TypedContent getHead() { result = head }
2481+
2482+
override AccessPath getTail() {
2483+
flowConsCand(head, result.getApprox(), _) and result.length() = len - 1
2484+
}
2485+
2486+
override AccessPathFrontHead getFront() { result = TFrontHead(head) }
2487+
2488+
override AccessPathApproxCons getApprox() { result = TCons1(head, len) }
2489+
2490+
override int length() { result = len }
2491+
2492+
override string toString() {
2493+
if len = 1
2494+
then result = "[" + head.toString() + "]"
2495+
else result = "[" + head.toString() + ", ... (" + len.toString() + ")]"
2496+
}
22192497
}
22202498

22212499
/**

0 commit comments

Comments
 (0)