@@ -435,37 +435,70 @@ module AccessPath {
435435 /**
436436 * Gets the `ranking`th access-path with `root` and `path` within `bb`.
437437 * 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`.
438440 */
439441 private ControlFlowNode rankedAccessPath (
440442 ReachableBasicBlock bb , Root root , string path , int ranking , AccessPathKind type
441443 ) {
442444 result =
443445 rank [ ranking ] ( ControlFlowNode ref |
444446 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 )
446451 |
447452 ref order by any ( int i | ref = bb .getNode ( i ) )
448453 ) and
449454 result = getAccessTo ( root , path , type )
450455 }
451456
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+
452477 /**
453478 * Gets a `ControlFlowNode` for an access to `path` from `root` with type `type`.
454479 *
455480 * This predicate uses both the AccessPath API, and the SourceNode API.
456481 * 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.
457484 */
458485 pragma [ nomagic]
459486 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+ )
465496 }
466497
467498 /**
468499 * Gets a `ControlFlowNode` for a read to `path` from `root`.
500+ *
501+ * Only used within `getAccessTo`.
469502 */
470503 private ControlFlowNode getAReadNode ( Root root , string path ) {
471504 exists ( DataFlow:: PropRead read | read .asExpr ( ) = result |
@@ -476,6 +509,8 @@ module AccessPath {
476509
477510 /**
478511 * Gets a `ControlFlowNode` for a write to `path` from `root`.
512+ *
513+ * Only used within `getAccessTo`.
479514 */
480515 private ControlFlowNode getAWriteNode ( Root root , string path ) {
481516 result = root .getAPropertyWrite ( path ) .getWriteNode ( )
0 commit comments