@@ -435,37 +435,70 @@ module AccessPath {
435
435
/**
436
436
* Gets the `ranking`th access-path with `root` and `path` within `bb`.
437
437
* And the access-path has type `type`.
438
+ *
439
+ * Only has a result if there exists both a read and write of the access-path within `bb`.
438
440
*/
439
441
private ControlFlowNode rankedAccessPath (
440
442
ReachableBasicBlock bb , Root root , string path , int ranking , AccessPathKind type
441
443
) {
442
444
result =
443
445
rank [ ranking ] ( ControlFlowNode ref |
444
446
ref = getAccessTo ( root , path , _) and
445
- ref .getBasicBlock ( ) = bb
447
+ ref .getBasicBlock ( ) = bb and
448
+ // Prunes the accesses where there does not exists a read and write within the same basicblock.
449
+ // This could be more precise, but doing it like this avoids massive joins.
450
+ hasRead ( bb ) and hasWrite ( bb )
446
451
|
447
452
ref order by any ( int i | ref = bb .getNode ( i ) )
448
453
) and
449
454
result = getAccessTo ( root , path , type )
450
455
}
451
456
457
+ /**
458
+ * Holds if there exists an access-path read inside the basic-block `bb`.
459
+ *
460
+ * INTERNAL: This predicate is only meant to be used inside `rankedAccessPath`.
461
+ */
462
+ pragma [ noinline]
463
+ private predicate hasRead ( ReachableBasicBlock bb ) {
464
+ bb = getAccessTo ( _, _, AccessPathRead ( ) ) .getBasicBlock ( )
465
+ }
466
+
467
+ /**
468
+ * Holds if there exists an access-path write inside the basic-block `bb`.
469
+ *
470
+ * INTERNAL: This predicate is only meant to be used inside `rankedAccessPath`.
471
+ */
472
+ pragma [ noinline]
473
+ private predicate hasWrite ( ReachableBasicBlock bb ) {
474
+ bb = getAccessTo ( _, _, AccessPathRead ( ) ) .getBasicBlock ( )
475
+ }
476
+
452
477
/**
453
478
* Gets a `ControlFlowNode` for an access to `path` from `root` with type `type`.
454
479
*
455
480
* This predicate uses both the AccessPath API, and the SourceNode API.
456
481
* This ensures that we have basic support for access-paths with ambiguous roots.
482
+ *
483
+ * There is only a result if both a read and a write of the access-path exists.
457
484
*/
458
485
pragma [ nomagic]
459
486
private ControlFlowNode getAccessTo ( Root root , string path , AccessPathKind type ) {
460
- type = AccessPathRead ( ) and
461
- result = getAReadNode ( root , path )
462
- or
463
- type = AccessPathWrite ( ) and
464
- result = getAWriteNode ( root , path )
487
+ exists ( getAReadNode ( root , path ) ) and
488
+ exists ( getAWriteNode ( root , path ) ) and
489
+ (
490
+ type = AccessPathRead ( ) and
491
+ result = getAReadNode ( root , path )
492
+ or
493
+ type = AccessPathWrite ( ) and
494
+ result = getAWriteNode ( root , path )
495
+ )
465
496
}
466
497
467
498
/**
468
499
* Gets a `ControlFlowNode` for a read to `path` from `root`.
500
+ *
501
+ * Only used within `getAccessTo`.
469
502
*/
470
503
private ControlFlowNode getAReadNode ( Root root , string path ) {
471
504
exists ( DataFlow:: PropRead read | read .asExpr ( ) = result |
@@ -476,6 +509,8 @@ module AccessPath {
476
509
477
510
/**
478
511
* Gets a `ControlFlowNode` for a write to `path` from `root`.
512
+ *
513
+ * Only used within `getAccessTo`.
479
514
*/
480
515
private ControlFlowNode getAWriteNode ( Root root , string path ) {
481
516
result = root .getAPropertyWrite ( path ) .getWriteNode ( )
0 commit comments