Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,12 @@ private module TrackVirtualDispatch<methodDispatchSig/1 virtualDispatch0> {

private import TypeTracking<Location, TtInput>::TypeTrack<qualifierSource/1>::Graph<qualifierOfVirtualCall/1>

private predicate edgePlus(PathNode n1, PathNode n2) = fastTC(edges/2)(n1, n2)
private predicate isSource(PathNode n) { n.isSource() }

private predicate isSink(PathNode n) { n.isSink() }

private predicate edgePlus(PathNode n1, PathNode n2) =
doublyBoundedFastTC(edges/2, isSource/1, isSink/1)(n1, n2)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've never seen a definition of doublyBoundedFastTC, but I think I see what's going on. It's computing a transitive closure of edges, but limited to those edges that connect somewhere between sources and sinks (presumably via a forwards-backwards passes type algorithm).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, exactly. doublyBoundedFastTC is also the HOP that's used when you evaluate any dataflow flowPath predicate.


/**
* Gets the most specific implementation of `mf` that may be called when the
Expand All @@ -255,6 +260,15 @@ private module TrackVirtualDispatch<methodDispatchSig/1 virtualDispatch0> {
)
}

pragma[nomagic]
private MemberFunction mostSpecificForSource(PathNode p1, MemberFunction mf) {
p1.isSource() and
exists(Class derived |
qualifierSourceImpl(p1.getNode(), derived) and
result = mostSpecific(mf, derived)
)
}

/**
* Gets a possible pair of end-points `(p1, p2)` where:
* - `p1` is a derived-to-base conversion that converts from some
Expand All @@ -264,16 +278,16 @@ private module TrackVirtualDispatch<methodDispatchSig/1 virtualDispatch0> {
* - `callable` is the most specific implementation that may be called when
* the qualifier has type `derived`.
*/
bindingset[p1, p2]
pragma[inline_late]
private predicate pairCand(
PathNode p1, PathNode p2, DataFlowPrivate::DataFlowCallable callable,
DataFlowPrivate::DataFlowCall call
) {
exists(Class derived, MemberFunction mf |
qualifierSourceImpl(p1.getNode(), derived) and
p2.isSink() and
exists(MemberFunction mf |
qualifierOfVirtualCallImpl(p2.getNode(), call.asCallInstruction(), mf) and
p1.isSource() and
p2.isSink() and
callable.asSourceCallable() = mostSpecific(mf, derived)
callable.asSourceCallable() = mostSpecificForSource(p1, mf)
)
}

Expand Down
Loading