private import cpp /** * Gets a function that might be called by `call`. */ Function viableCallable(Call call) { result = call.getTarget() or // If the target of the call does not have a body in the snapshot, it might // be because the target is just a header declaration, and the real target // will be determined at run time when the caller and callee are linked // together by the operating system's dynamic linker. In case a _unique_ // function with the right signature is present in the database, we return // that as a potential callee. exists(string qualifiedName, int nparams | callSignatureWithoutBody(qualifiedName, nparams, call) and functionSignatureWithBody(qualifiedName, nparams, result) and strictcount(Function other | functionSignatureWithBody(qualifiedName, nparams, other)) = 1 ) } /** * Holds if `f` is a function with a body that has name `qualifiedName` and * `nparams` parameter count. See `functionSignature`. */ private predicate functionSignatureWithBody(string qualifiedName, int nparams, Function f) { functionSignature(f, qualifiedName, nparams) and exists(f.getBlock()) } /** * Holds if the target of `call` is a function _with no definition_ that has * name `qualifiedName` and `nparams` parameter count. See `functionSignature`. */ pragma[noinline] private predicate callSignatureWithoutBody(string qualifiedName, int nparams, Call call) { exists(Function target | target = call.getTarget() and not exists(target.getBlock()) and functionSignature(target, qualifiedName, nparams) ) } /** * Holds if `f` has name `qualifiedName` and `nparams` parameter count. This is * an approximation of its signature for the purpose of matching functions that * might be the same across link targets. */ private predicate functionSignature(Function f, string qualifiedName, int nparams) { qualifiedName = f.getQualifiedName() and nparams = f.getNumberOfParameters() and not f.isStatic() } /** * Holds if the set of viable implementations that can be called by `call` * might be improved by knowing the call context. */ predicate mayBenefitFromCallContext(Call call, Function f) { none() } /** * Gets a viable dispatch target of `call` in the context `ctx`. This is * restricted to those `call`s for which a context might make a difference. */ Function viableImplInCallContext(Call call, Call ctx) { none() }