Java: Make more finegrained dataflow dispatch viable callable heuristic.

This commit is contained in:
Michael Nebel
2024-08-15 15:33:03 +02:00
parent 3a864d3de2
commit fe6693739a
2 changed files with 29 additions and 4 deletions

View File

@@ -36,6 +36,13 @@ class Element extends @element, Top {
*/
predicate fromSource() { this.getCompilationUnit().isSourceFile() }
/**
* Holds if this element is from source and classified as a stub implementation.
* An implementation is considered a stub, if the the path to the
* source file contains `/stubs/`.
*/
predicate isStub() { this.fromSource() and this.getFile().getAbsolutePath().matches("%/stubs/%") }
/** Gets the compilation unit that this element belongs to. */
CompilationUnit getCompilationUnit() { result = this.getFile() }

View File

@@ -40,11 +40,29 @@ private module DispatchImpl {
else any()
}
/** Gets a viable implementation of the target of the given `Call`. */
/**
* Gets a viable implementation of the target of the given `Call`.
* The following heuristic is applied for finding the appropriate callable:
* 1. If an exact manual model exists, only dispatch to the summarized callable.
* 2. If a (non exact) manual model exists and/or if the source code is available, dispatch to both/either.
* 3. Only dispatch to a summarized callable (based on a generated model) if neither of the above apply.
*/
DataFlowCallable viableCallable(DataFlowCall c) {
result.asCallable() = sourceDispatch(c.asCall())
or
result.asSummarizedCallable().getACall() = c.asCall()
exists(Call call | call = c.asCall() |
result.asCallable() = sourceDispatch(call)
or
not (
// Only use summarized callables with generated summaries in case
// we are not able to dispatch to a source declaration.
// Note that if applyGeneratedModel holds it implies that there doesn't
// exist a manual (exact) model.
exists(Callable callable | callable = sourceDispatch(call) |
callable.fromSource() and not callable.isStub()
) and
result.asSummarizedCallable().applyGeneratedModel()
) and
result.asSummarizedCallable().getACall() = call
)
}
/**