mirror of
https://github.com/github/codeql.git
synced 2026-04-29 10:45:15 +02:00
Java: Remove low confidence dispatch for which we have a manual summary.
This commit is contained in:
@@ -8,9 +8,27 @@ private import semmle.code.java.dataflow.TypeFlow
|
||||
private import semmle.code.java.dispatch.internal.Unification
|
||||
|
||||
private module DispatchImpl {
|
||||
private predicate hasHighConfidenceTarget(Call c) {
|
||||
exists(SummarizedCallable sc |
|
||||
sc = c.getCallee().getSourceDeclaration() and not sc.isAutoGenerated()
|
||||
)
|
||||
or
|
||||
exists(Callable srcTgt |
|
||||
srcTgt = VirtualDispatch::viableCallable(c) and
|
||||
not VirtualDispatch::lowConfidenceDispatchTarget(c, srcTgt)
|
||||
)
|
||||
}
|
||||
|
||||
private Callable sourceDispatch(Call c) {
|
||||
result = VirtualDispatch::viableCallable(c) and
|
||||
if VirtualDispatch::lowConfidenceDispatchTarget(c, result)
|
||||
then not hasHighConfidenceTarget(c)
|
||||
else any()
|
||||
}
|
||||
|
||||
/** Gets a viable implementation of the target of the given `Call`. */
|
||||
DataFlowCallable viableCallable(DataFlowCall c) {
|
||||
result.asCallable() = VirtualDispatch::viableCallable(c.asCall())
|
||||
result.asCallable() = sourceDispatch(c.asCall())
|
||||
or
|
||||
result.asSummarizedCallable() = c.asCall().getCallee().getSourceDeclaration()
|
||||
}
|
||||
@@ -22,7 +40,7 @@ private module DispatchImpl {
|
||||
*/
|
||||
private predicate mayBenefitFromCallContext(MethodAccess ma, Callable c, int i) {
|
||||
exists(Parameter p |
|
||||
2 <= strictcount(VirtualDispatch::viableImpl(ma)) and
|
||||
2 <= strictcount(sourceDispatch(ma)) and
|
||||
ma.getQualifier().(VarAccess).getVariable() = p and
|
||||
p.getPosition() = i and
|
||||
c.getAParameter() = p and
|
||||
@@ -31,7 +49,7 @@ private module DispatchImpl {
|
||||
)
|
||||
or
|
||||
exists(OwnInstanceAccess ia |
|
||||
2 <= strictcount(VirtualDispatch::viableImpl(ma)) and
|
||||
2 <= strictcount(sourceDispatch(ma)) and
|
||||
(ia.isExplicit(ma.getQualifier()) or ia.isImplicitMethodQualifier(ma)) and
|
||||
i = -1 and
|
||||
c = ma.getEnclosingCallable()
|
||||
@@ -47,7 +65,7 @@ private module DispatchImpl {
|
||||
private predicate relevantContext(Call ctx, int i) {
|
||||
exists(Callable c |
|
||||
mayBenefitFromCallContext(_, c, i) and
|
||||
c = VirtualDispatch::viableCallable(ctx)
|
||||
c = sourceDispatch(ctx)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -54,6 +54,16 @@ private module Dispatch {
|
||||
cached
|
||||
Method viableImpl(MethodAccess ma) { result = ObjFlow::viableImpl_out(ma) }
|
||||
|
||||
/**
|
||||
* Holds if `m` is a viable implementation of the method called in `ma` for
|
||||
* which we only have imprecise open-world type-based dispatch resolution, and
|
||||
* the dispatch type is likely to yield implausible dispatch targets.
|
||||
*/
|
||||
cached
|
||||
predicate lowConfidenceDispatchTarget(MethodAccess ma, Method m) {
|
||||
m = viableImpl(ma) and lowConfidenceDispatch(ma)
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Use `viableImpl` instead.
|
||||
*
|
||||
@@ -62,6 +72,42 @@ private module Dispatch {
|
||||
cached
|
||||
Method viableImpl_v3(MethodAccess ma) { result = DispatchFlow::viableImpl_out(ma) }
|
||||
|
||||
/**
|
||||
* Holds if the best type bounds for the qualifier of `ma` are likely to
|
||||
* contain implausible dispatch targets.
|
||||
*/
|
||||
private predicate lowConfidenceDispatch(VirtualMethodAccess ma) {
|
||||
exists(RefType t | hasQualifierType(ma, t, false) |
|
||||
lowConfidenceDispatchType(t.getSourceDeclaration())
|
||||
) and
|
||||
(
|
||||
not qualType(ma, _, _)
|
||||
or
|
||||
exists(RefType t | qualType(ma, t, false) |
|
||||
lowConfidenceDispatchType(t.getSourceDeclaration())
|
||||
)
|
||||
) and
|
||||
(
|
||||
not qualUnionType(ma, _, _)
|
||||
or
|
||||
exists(RefType t | qualUnionType(ma, t, false) |
|
||||
lowConfidenceDispatchType(t.getSourceDeclaration())
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate lowConfidenceDispatchType(SrcRefType t) {
|
||||
t instanceof TypeObject
|
||||
or
|
||||
t instanceof FunctionalInterface
|
||||
or
|
||||
t.hasQualifiedName("java.io", "Serializable")
|
||||
or
|
||||
t.hasQualifiedName("java.lang", "Cloneable")
|
||||
or
|
||||
t.getPackage().hasName("java.util") and t instanceof Interface
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Use `viableImpl` instead.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user