@@ -149,7 +149,7 @@ abstract class Configuration extends string {
149
149
predicate isBarrier ( DataFlow:: Node node ) {
150
150
exists ( BarrierGuardNode guard |
151
151
isBarrierGuardInternal ( guard ) and
152
- guard . internalBlocks ( node , "" )
152
+ barrierGuardBlocksNode ( guard , node , "" )
153
153
)
154
154
}
155
155
@@ -183,7 +183,7 @@ abstract class Configuration extends string {
183
183
predicate isLabeledBarrier ( DataFlow:: Node node , FlowLabel lbl ) {
184
184
exists ( BarrierGuardNode guard |
185
185
isBarrierGuardInternal ( guard ) and
186
- guard . internalBlocks ( node , lbl )
186
+ barrierGuardBlocksNode ( guard , node , lbl )
187
187
)
188
188
or
189
189
none ( ) // relax type inference to account for overriding
@@ -199,6 +199,10 @@ abstract class Configuration extends string {
199
199
*/
200
200
predicate isBarrierGuard ( BarrierGuardNode guard ) { none ( ) }
201
201
202
+ /**
203
+ * Holds if `guard` is a barrier guard for this configuration, added through
204
+ * `isBarrierGuard` or `AdditionalBarrierGuardNode`.
205
+ */
202
206
private predicate isBarrierGuardInternal ( BarrierGuardNode guard ) {
203
207
isBarrierGuard ( guard )
204
208
or
@@ -319,44 +323,6 @@ module FlowLabel {
319
323
* implementations of `blocks` will _both_ apply to any configuration that includes either of them.
320
324
*/
321
325
abstract class BarrierGuardNode extends DataFlow:: Node {
322
- /**
323
- * Holds if data flow node `nd` acts as a barrier for data flow, possibly due to aliasing
324
- * through an access path.
325
- *
326
- * `label` is bound to the blocked label, or the empty string if all labels should be blocked.
327
- *
328
- * INTERNAL: this predicate should only be used from within `blocks(boolean, Expr)`.
329
- */
330
- predicate internalBlocks ( DataFlow:: Node nd , string label ) {
331
- // 1) `nd` is a use of a refinement node that blocks its input variable
332
- exists ( SsaRefinementNode ref , boolean outcome |
333
- nd = DataFlow:: ssaDefinitionNode ( ref ) and
334
- outcome = ref .getGuard ( ) .( ConditionGuardNode ) .getOutcome ( ) and
335
- ssaRefinementBlocks ( outcome , ref , label )
336
- )
337
- or
338
- // 2) `nd` is an instance of an access path `p`, and dominated by a barrier for `p`
339
- exists ( AccessPath p , BasicBlock bb , ConditionGuardNode cond , boolean outcome |
340
- nd = DataFlow:: valueNode ( p .getAnInstanceIn ( bb ) ) and
341
- getEnclosingExpr ( ) = cond .getTest ( ) and
342
- outcome = cond .getOutcome ( ) and
343
- barrierGuardBlocksAccessPath ( this , outcome , p , label ) and
344
- cond .dominates ( bb )
345
- )
346
- }
347
-
348
- /**
349
- * Holds if there exists an input variable of `ref` that blocks the label `label`.
350
- *
351
- * This predicate is outlined to give the optimizer a hint about the join ordering.
352
- */
353
- private predicate ssaRefinementBlocks ( boolean outcome , SsaRefinementNode ref , string label ) {
354
- getEnclosingExpr ( ) = ref .getGuard ( ) .getTest ( ) and
355
- forex ( SsaVariable input | input = ref .getAnInput ( ) |
356
- barrierGuardBlocksExpr ( this , outcome , input .getAUse ( ) , label )
357
- )
358
- }
359
-
360
326
/**
361
327
* Holds if this node blocks expression `e` provided it evaluates to `outcome`.
362
328
*
@@ -387,6 +353,17 @@ private predicate barrierGuardBlocksExpr(
387
353
guard .( AdditionalBarrierGuardCall ) .internalBlocksLabel ( outcome , test , label )
388
354
}
389
355
356
+ /**
357
+ * Holds if `guard` blocks the flow of a value reachable through exploratory flow.
358
+ */
359
+ pragma [ noinline]
360
+ private predicate barrierGuardIsRelevant ( BarrierGuardNode guard ) {
361
+ exists ( Expr e |
362
+ barrierGuardBlocksExpr ( guard , _, e , _) and
363
+ isRelevantForward ( e .flow ( ) , _)
364
+ )
365
+ }
366
+
390
367
/**
391
368
* Holds if data flow node `nd` acts as a barrier for data flow due to aliasing through
392
369
* an access path.
@@ -397,9 +374,50 @@ pragma[noinline]
397
374
private predicate barrierGuardBlocksAccessPath (
398
375
BarrierGuardNode guard , boolean outcome , AccessPath ap , string label
399
376
) {
377
+ barrierGuardIsRelevant ( guard ) and
400
378
barrierGuardBlocksExpr ( guard , outcome , ap .getAnInstance ( ) , label )
401
379
}
402
380
381
+ /**
382
+ * Holds if there exists an input variable of `ref` that blocks the label `label`.
383
+ *
384
+ * This predicate is outlined to give the optimizer a hint about the join ordering.
385
+ */
386
+ private predicate barrierGuardBlocksSsaRefinement (
387
+ BarrierGuardNode guard , boolean outcome , SsaRefinementNode ref , string label
388
+ ) {
389
+ barrierGuardIsRelevant ( guard ) and
390
+ guard .getEnclosingExpr ( ) = ref .getGuard ( ) .getTest ( ) and
391
+ forex ( SsaVariable input | input = ref .getAnInput ( ) |
392
+ barrierGuardBlocksExpr ( guard , outcome , input .getAUse ( ) , label )
393
+ )
394
+ }
395
+
396
+ /**
397
+ * Holds if data flow node `nd` acts as a barrier for data flow, possibly due to aliasing
398
+ * through an access path.
399
+ *
400
+ * `label` is bound to the blocked label, or the empty string if all labels should be blocked.
401
+ */
402
+ private predicate barrierGuardBlocksNode ( BarrierGuardNode guard , DataFlow:: Node nd , string label ) {
403
+ // 1) `nd` is a use of a refinement node that blocks its input variable
404
+ exists ( SsaRefinementNode ref , boolean outcome |
405
+ nd = DataFlow:: ssaDefinitionNode ( ref ) and
406
+ outcome = ref .getGuard ( ) .( ConditionGuardNode ) .getOutcome ( ) and
407
+ barrierGuardBlocksSsaRefinement ( guard , outcome , ref , label )
408
+ )
409
+ or
410
+ // 2) `nd` is an instance of an access path `p`, and dominated by a barrier for `p`
411
+ barrierGuardIsRelevant ( guard ) and
412
+ exists ( AccessPath p , BasicBlock bb , ConditionGuardNode cond , boolean outcome |
413
+ nd = DataFlow:: valueNode ( p .getAnInstanceIn ( bb ) ) and
414
+ guard .getEnclosingExpr ( ) = cond .getTest ( ) and
415
+ outcome = cond .getOutcome ( ) and
416
+ barrierGuardBlocksAccessPath ( guard , outcome , p , label ) and
417
+ cond .dominates ( bb )
418
+ )
419
+ }
420
+
403
421
/**
404
422
* Holds if `guard` should block flow along the edge `pred -> succ`.
405
423
*
@@ -408,6 +426,7 @@ private predicate barrierGuardBlocksAccessPath(
408
426
private predicate barrierGuardBlocksEdge (
409
427
BarrierGuardNode guard , DataFlow:: Node pred , DataFlow:: Node succ , string label
410
428
) {
429
+ barrierGuardIsRelevant ( guard ) and
411
430
exists (
412
431
SsaVariable input , SsaPhiNode phi , BasicBlock bb , ConditionGuardNode cond , boolean outcome
413
432
|
@@ -569,11 +588,12 @@ private class FlowStepThroughImport extends AdditionalFlowStep, DataFlow::ValueN
569
588
570
589
/**
571
590
* Holds if there is a flow step from `pred` to `succ` described by `summary`
572
- * under configuration `cfg`.
591
+ * under configuration `cfg`, disregarding barriers .
573
592
*
574
593
* Summary steps through function calls are not taken into account.
575
594
*/
576
- private predicate basicFlowStep (
595
+ pragma [ inline]
596
+ private predicate basicFlowStepNoBarrier (
577
597
DataFlow:: Node pred , DataFlow:: Node succ , PathSummary summary , DataFlow:: Configuration cfg
578
598
) {
579
599
isLive ( ) and
@@ -582,8 +602,7 @@ private predicate basicFlowStep(
582
602
// Local flow
583
603
exists ( FlowLabel predlbl , FlowLabel succlbl |
584
604
localFlowStep ( pred , succ , cfg , predlbl , succlbl ) and
585
- not isLabeledBarrierEdge ( cfg , pred , succ , predlbl ) and
586
- not isBarrierEdge ( cfg , pred , succ ) and
605
+ not cfg .isBarrierEdge ( pred , succ ) and
587
606
summary = MkPathSummary ( false , false , predlbl , succlbl )
588
607
)
589
608
or
@@ -605,6 +624,20 @@ private predicate basicFlowStep(
605
624
)
606
625
}
607
626
627
+ /**
628
+ * Holds if there is a flow step from `pred` to `succ` described by `summary`
629
+ * under configuration `cfg`.
630
+ *
631
+ * Summary steps through function calls are not taken into account.
632
+ */
633
+ private predicate basicFlowStep (
634
+ DataFlow:: Node pred , DataFlow:: Node succ , PathSummary summary , DataFlow:: Configuration cfg
635
+ ) {
636
+ basicFlowStepNoBarrier ( pred , succ , summary , cfg ) and
637
+ not isLabeledBarrierEdge ( cfg , pred , succ , summary .getStartLabel ( ) ) and
638
+ not isBarrierEdge ( cfg , pred , succ )
639
+ }
640
+
608
641
/**
609
642
* Holds if there is a flow step from `pred` to `succ` under configuration `cfg`,
610
643
* including both basic flow steps and steps into/out of properties.
@@ -615,7 +648,7 @@ private predicate basicFlowStep(
615
648
private predicate exploratoryFlowStep (
616
649
DataFlow:: Node pred , DataFlow:: Node succ , DataFlow:: Configuration cfg
617
650
) {
618
- basicFlowStep ( pred , succ , _, cfg ) or
651
+ basicFlowStepNoBarrier ( pred , succ , _, cfg ) or
619
652
basicStoreStep ( pred , succ , _) or
620
653
basicLoadStep ( pred , succ , _) or
621
654
isAdditionalStoreStep ( pred , succ , _, cfg ) or
@@ -1442,6 +1475,7 @@ private class BarrierGuardFunction extends Function {
1442
1475
string label ;
1443
1476
1444
1477
BarrierGuardFunction ( ) {
1478
+ barrierGuardIsRelevant ( guard ) and
1445
1479
exists ( Expr e |
1446
1480
exists ( Expr returnExpr |
1447
1481
returnExpr = guard .asExpr ( )
0 commit comments