CPP: Speed up VirtualDispatch.qll's getAViableTarget.

This commit is contained in:
Geoffrey White
2019-10-25 11:19:31 +01:00
parent c40c88ec4b
commit 2d64fedeb0

View File

@@ -28,6 +28,19 @@ module VirtualDispatch {
not result.hasName("IUnknown")
}
/**
* Helper predicate for `getAViableTarget`, which computes the viable targets for
* virtual calls based on the qualifier type.
*/
private Function getAViableVirtualCallTarget(Class qualifierType, MemberFunction staticTarget) {
exists(Class qualifierSubType |
result = getAPossibleImplementation(staticTarget) and
qualifierType = qualifierSubType.getABaseClass*() and
mayInherit(qualifierSubType, result) and
not cannotInherit(qualifierSubType, result)
)
}
/**
* Gets a viable target for the given function call.
*
@@ -42,18 +55,9 @@ module VirtualDispatch {
* If `c` is not a virtual call, the result will be `c.getTarget()`.
*/
Function getAViableTarget(Call c) {
exists(Function staticTarget | staticTarget = c.getTarget() |
if c.(FunctionCall).isVirtual() and staticTarget instanceof MemberFunction
then
exists(Class qualifierType, Class qualifierSubType |
result = getAPossibleImplementation(staticTarget) and
qualifierType = getCallQualifierType(c) and
qualifierType = qualifierSubType.getABaseClass*() and
mayInherit(qualifierSubType, result) and
not cannotInherit(qualifierSubType, result)
)
else result = staticTarget
)
if c.(FunctionCall).isVirtual() and c.getTarget() instanceof MemberFunction
then result = getAViableVirtualCallTarget(getCallQualifierType(c), c.getTarget())
else result = c.getTarget()
}
/** Holds if `f` is declared in `c` or a transitive base class of `c`. */