Skip to content

Commit 184df7e

Browse files
committed
Data flow: Reduce doublyBoundedFastTC use in StoreReadMatching
1 parent 43cd2c0 commit 184df7e

File tree

1 file changed

+32
-124
lines changed

1 file changed

+32
-124
lines changed

shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll

+32-124
Original file line numberDiff line numberDiff line change
@@ -2338,6 +2338,8 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
23382338
signature module StoreReadMatchingInputSig {
23392339
class NodeEx {
23402340
string toString();
2341+
2342+
DataFlowType getDataFlowType();
23412343
}
23422344

23432345
predicate nodeRange(NodeEx node, boolean fromArg, DataFlowCallOption callCtx);
@@ -2370,13 +2372,6 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
23702372
* The implementation is based on `doublyBoundedFastTC`, and in order to avoid poor
23712373
* performance through recursion, we unroll the recursion manually 4 times, in order to
23722374
* be able to handle access paths of maximum length 5.
2373-
*
2374-
* Additionally, in order to speed up the join with `doublyBoundedFastTC`, we first
2375-
* compute three pruning steps:
2376-
*
2377-
* 1. Which _contents_ may have matching read-store pairs (called `contentIsReadAndStored` below).
2378-
* 2. Which store targets may have _a_ matching read (called `storeMayReachARead` below).
2379-
* 3. Which reads may have _a_ matching store (called `aStoreMayReachRead` below).
23802375
*/
23812376
module StoreReadMatching<StoreReadMatchingInputSig Input> {
23822377
private import codeql.util.Boolean
@@ -2396,36 +2391,24 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
23962391
);
23972392
}
23982393

2399-
private newtype TNodeOrContent =
2400-
TNodeOrContentNode(
2401-
NodeEx n, Boolean usesPrevDelta, boolean fromArg, DataFlowCallOption callCtx
2402-
) {
2394+
private newtype TNodeExt =
2395+
MkNodeExt(NodeEx n, Boolean usesPrevDelta, boolean fromArg, DataFlowCallOption callCtx) {
24032396
nodeRange(n, fromArg, callCtx)
2404-
} or
2405-
TNodeOrContentStoreContent(Content c) { storeContentStep(_, c, _) } or
2406-
TNodeOrContentReadContent(Content c) { readContentStep(_, c, _) }
2397+
}
24072398

2408-
private class NodeOrContent extends TNodeOrContent {
2399+
private class NodeExt extends MkNodeExt {
24092400
NodeEx asNodeEx(boolean usesPrevDelta, boolean fromArg, DataFlowCallOption callCtx) {
2410-
this = TNodeOrContentNode(result, usesPrevDelta, fromArg, callCtx)
2401+
this = MkNodeExt(result, usesPrevDelta, fromArg, callCtx)
24112402
}
24122403

2413-
Content asStoreContent() { this = TNodeOrContentStoreContent(result) }
2414-
2415-
Content asReadContent() { this = TNodeOrContentReadContent(result) }
2404+
DataFlowType getType() { result = this.asNodeEx(_, _, _).getDataFlowType() }
24162405

2417-
string toString() {
2418-
result = this.asStoreContent().toString()
2419-
or
2420-
result = this.asReadContent().toString()
2421-
or
2422-
result = this.asNodeEx(_, _, _).toString()
2423-
}
2406+
string toString() { result = this.asNodeEx(_, _, _).toString() }
24242407
}
24252408

24262409
pragma[nomagic]
24272410
private predicate stepNodeCommon(
2428-
NodeOrContent node1, NodeEx n2, boolean usesPrevDelta2, Boolean fromArg2,
2411+
NodeExt node1, NodeEx n2, boolean usesPrevDelta2, Boolean fromArg2,
24292412
DataFlowCallOption callCtx2
24302413
) {
24312414
exists(NodeEx n1, boolean fromArg1, DataFlowCallOption callCtx1 |
@@ -2467,7 +2450,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
24672450

24682451
pragma[nomagic]
24692452
private predicate stepNode(
2470-
NodeOrContent node1, NodeEx n2, boolean usesPrevDelta2, Boolean fromArg2,
2453+
NodeExt node1, NodeEx n2, boolean usesPrevDelta2, Boolean fromArg2,
24712454
DataFlowCallOption callCtx2
24722455
) {
24732456
enabled() and
@@ -2487,135 +2470,51 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
24872470
}
24882471

24892472
pragma[nomagic]
2490-
private predicate step(NodeOrContent node1, NodeOrContent node2) {
2473+
private predicate step(NodeExt node1, NodeExt node2) {
24912474
exists(NodeEx n2, boolean usesPrevDelta2, boolean fromArg2, DataFlowCallOption callCtx2 |
24922475
n2 = node2.asNodeEx(usesPrevDelta2, fromArg2, callCtx2) and
24932476
stepNode(node1, n2, usesPrevDelta2, fromArg2, callCtx2)
24942477
)
2495-
or
2496-
enabled() and
2497-
(
2498-
exists(NodeEx n2, Content c, boolean usesPrevDelta2 |
2499-
n2 = node2.asNodeEx(usesPrevDelta2, _, _) and
2500-
c = node1.asStoreContent() and
2501-
storeContentStep(_, c, n2) and
2502-
usesPrevDelta2 = false
2503-
)
2504-
or
2505-
exists(NodeEx n1, Content c, boolean usesPrevDelta1 |
2506-
n1 = node1.asNodeEx(usesPrevDelta1, _, _) and
2507-
c = node2.asReadContent() and
2508-
readContentStep(n1, c, _) and
2509-
usesPrevDelta(usesPrevDelta1)
2510-
)
2511-
)
25122478
}
25132479

2514-
private predicate isStoreContent(NodeOrContent c) {
2515-
enabled() and
2516-
exists(c.asStoreContent())
2517-
}
2518-
2519-
private predicate isReadContent(NodeOrContent c) {
2520-
enabled() and
2521-
exists(c.asReadContent())
2522-
}
2523-
2524-
private predicate contentReachesReadTc(NodeOrContent node1, NodeOrContent node2) =
2525-
doublyBoundedFastTC(step/2, isStoreContent/1, isReadContent/1)(node1, node2)
2526-
25272480
pragma[nomagic]
2528-
private predicate contentIsReadAndStoredJoin(NodeOrContent c1, NodeOrContent c2, Content c) {
2529-
enabled() and
2530-
c1.asStoreContent() = c and
2531-
c2.asReadContent() = c
2532-
}
2533-
2534-
additional predicate contentIsReadAndStored(Content c) {
2535-
exists(NodeOrContent n1, NodeOrContent n2 |
2536-
contentReachesReadTc(n1, n2) and
2537-
contentIsReadAndStoredJoin(n1, n2, c)
2538-
)
2539-
}
2540-
2541-
pragma[nomagic]
2542-
private predicate isStoreTarget0(NodeOrContent node, Content c) {
2481+
private predicate isStoreTarget0(NodeExt node, Content c) {
25432482
exists(boolean usesPrevDelta |
2544-
contentIsReadAndStored(c) and
25452483
storeContentStep(_, c, node.asNodeEx(usesPrevDelta, _, _)) and
25462484
usesPrevDelta = false
25472485
)
25482486
}
25492487

2550-
private predicate isStoreTarget(NodeOrContent node) { isStoreTarget0(node, _) }
2488+
private predicate isStoreTarget(NodeExt node) { isStoreTarget0(node, _) }
25512489

25522490
pragma[nomagic]
2553-
private predicate isReadSource0(NodeOrContent node, Content c) {
2491+
private predicate isReadSource0(NodeExt node, Content c) {
25542492
exists(boolean usesPrevDelta |
2555-
contentIsReadAndStored(c) and
25562493
readContentStep(node.asNodeEx(usesPrevDelta, _, _), c, _) and
25572494
usesPrevDelta(usesPrevDelta)
25582495
)
25592496
}
25602497

2561-
private predicate isReadSource(NodeOrContent node) { isReadSource0(node, _) }
2562-
2563-
private predicate storeMayReachAReadTc(NodeOrContent node1, NodeOrContent node2) =
2564-
doublyBoundedFastTC(step/2, isStoreTarget/1, isReadContent/1)(node1, node2)
2565-
2566-
pragma[nomagic]
2567-
private predicate storeMayReachAReadJoin(NodeOrContent n1, NodeOrContent n2, Content c) {
2568-
isStoreTarget0(n1, c) and
2569-
n2.asReadContent() = c
2570-
}
2571-
2572-
private predicate storeMayReachARead(NodeOrContent node1, Content c) {
2573-
exists(NodeOrContent node2 |
2574-
storeMayReachAReadTc(node1, node2) and
2575-
storeMayReachAReadJoin(node1, node2, c)
2576-
)
2577-
}
2578-
2579-
private predicate aStoreMayReachReadTc(NodeOrContent node1, NodeOrContent node2) =
2580-
doublyBoundedFastTC(step/2, isStoreContent/1, isReadSource/1)(node1, node2)
2581-
2582-
pragma[nomagic]
2583-
private predicate aStoreMayReachReadJoin(NodeOrContent n1, NodeOrContent n2, Content c) {
2584-
n1.asStoreContent() = c and
2585-
isReadSource0(n2, c)
2586-
}
2587-
2588-
additional predicate aStoreMayReachRead(NodeOrContent node2, Content c) {
2589-
exists(NodeOrContent node1 |
2590-
aStoreMayReachReadTc(node1, node2) and
2591-
aStoreMayReachReadJoin(node1, node2, c)
2592-
)
2593-
}
2594-
2595-
private predicate isStoreTargetPruned(NodeOrContent node) { storeMayReachARead(node, _) }
2596-
2597-
private predicate isReadSourcePruned(NodeOrContent node) { aStoreMayReachRead(node, _) }
2498+
private predicate isReadSource(NodeExt node) { isReadSource0(node, _) }
25982499

2599-
private predicate storeMayReachReadTc(NodeOrContent node1, NodeOrContent node2) =
2600-
doublyBoundedFastTC(step/2, isStoreTargetPruned/1, isReadSourcePruned/1)(node1, node2)
2500+
private predicate storeMayReachReadTc(NodeExt node1, NodeExt node2) =
2501+
doublyBoundedFastTC(step/2, isStoreTarget/1, isReadSource/1)(node1, node2)
26012502

26022503
pragma[nomagic]
26032504
private predicate storeMayReachReadDeltaJoinLeft(
2604-
NodeEx node1, Content c, NodeOrContent node2, boolean fromArg2, DataFlowCallOption callCtx2
2505+
NodeEx node1, Content c, NodeExt node2, boolean fromArg2, DataFlowCallOption callCtx2
26052506
) {
26062507
exists(boolean usesPrevDelta |
2607-
storeMayReachARead(pragma[only_bind_into](node2), pragma[only_bind_into](c)) and
26082508
storeContentStep(node1, c, node2.asNodeEx(usesPrevDelta, fromArg2, callCtx2)) and
26092509
usesPrevDelta = false
26102510
)
26112511
}
26122512

26132513
pragma[nomagic]
26142514
private predicate storeMayReachReadDeltaJoinRight(
2615-
NodeOrContent node1, Content c, NodeEx node2, boolean fromArg1, DataFlowCallOption callCtx1
2515+
NodeExt node1, Content c, NodeEx node2, boolean fromArg1, DataFlowCallOption callCtx1
26162516
) {
26172517
exists(boolean usesPrevDelta |
2618-
aStoreMayReachRead(pragma[only_bind_into](node1), pragma[only_bind_into](c)) and
26192518
readContentStep(node1.asNodeEx(usesPrevDelta, fromArg1, callCtx1), c, node2) and
26202519
usesPrevDelta(usesPrevDelta)
26212520
)
@@ -2626,10 +2525,20 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
26262525
NodeEx storeSource, Content c, NodeEx readTarget, boolean fromArg1, boolean fromArg2,
26272526
DataFlowCallOption callCtx1, DataFlowCallOption callCtx2
26282527
) {
2629-
exists(NodeOrContent storeTarget, NodeOrContent readSource |
2528+
exists(NodeExt storeTarget, NodeExt readSource |
26302529
storeMayReachReadTc(storeTarget, readSource) and
26312530
storeMayReachReadDeltaJoinLeft(storeSource, c, storeTarget, fromArg1, callCtx1) and
2632-
storeMayReachReadDeltaJoinRight(readSource, c, readTarget, fromArg2, callCtx2)
2531+
storeMayReachReadDeltaJoinRight(readSource, c, readTarget, fromArg2, callCtx2) and
2532+
(
2533+
compatibleTypesFilter(storeTarget.getType(), readSource.getType())
2534+
or
2535+
not exists(readSource.getType())
2536+
) and
2537+
(
2538+
compatibleTypesFilter(storeSource.getDataFlowType(), readTarget.getDataFlowType())
2539+
or
2540+
not exists(readTarget.getDataFlowType())
2541+
)
26332542
) and
26342543
not Prev::storeMayReachReadPrev(storeSource, c, readTarget, fromArg1, fromArg2, callCtx1,
26352544
callCtx2)
@@ -2679,7 +2588,6 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
26792588
or
26802589
// special case only needed for the first iteration: a store immediately followed by a read
26812590
exists(NodeEx storeTargetReadSource |
2682-
StoreReachesRead1::contentIsReadAndStored(c) and
26832591
storeContentStep(storeSource, c, storeTargetReadSource) and
26842592
readContentStep(storeTargetReadSource, c, readTarget)
26852593
) and

0 commit comments

Comments
 (0)