|
| 1 | +private import semmle.code.cpp.ir.IR |
| 2 | + |
| 3 | +Function viableImpl(CallInstruction call) { result = viableCallable(call) } |
| 4 | + |
| 5 | +/** |
| 6 | + * Gets a function that might be called by `call`. |
| 7 | + */ |
| 8 | +Function viableCallable(CallInstruction call) { |
| 9 | + result = call.getStaticCallTarget() |
| 10 | + or |
| 11 | + // If the target of the call does not have a body in the snapshot, it might |
| 12 | + // be because the target is just a header declaration, and the real target |
| 13 | + // will be determined at run time when the caller and callee are linked |
| 14 | + // together by the operating system's dynamic linker. In case a _unique_ |
| 15 | + // function with the right signature is present in the database, we return |
| 16 | + // that as a potential callee. |
| 17 | + exists(string qualifiedName, int nparams | |
| 18 | + callSignatureWithoutBody(qualifiedName, nparams, call) and |
| 19 | + functionSignatureWithBody(qualifiedName, nparams, result) and |
| 20 | + strictcount(Function other | functionSignatureWithBody(qualifiedName, nparams, other)) = 1 |
| 21 | + ) |
| 22 | +} |
| 23 | + |
| 24 | +/** |
| 25 | + * Holds if `f` is a function with a body that has name `qualifiedName` and |
| 26 | + * `nparams` parameter count. See `functionSignature`. |
| 27 | + */ |
| 28 | +private predicate functionSignatureWithBody(string qualifiedName, int nparams, Function f) { |
| 29 | + functionSignature(f, qualifiedName, nparams) and |
| 30 | + exists(f.getBlock()) |
| 31 | +} |
| 32 | + |
| 33 | +/** |
| 34 | + * Holds if the target of `call` is a function _with no definition_ that has |
| 35 | + * name `qualifiedName` and `nparams` parameter count. See `functionSignature`. |
| 36 | + */ |
| 37 | +pragma[noinline] |
| 38 | +private predicate callSignatureWithoutBody(string qualifiedName, int nparams, CallInstruction call) { |
| 39 | + exists(Function target | |
| 40 | + target = call.getStaticCallTarget() and |
| 41 | + not exists(target.getBlock()) and |
| 42 | + functionSignature(target, qualifiedName, nparams) |
| 43 | + ) |
| 44 | +} |
| 45 | + |
| 46 | +/** |
| 47 | + * Holds if `f` has name `qualifiedName` and `nparams` parameter count. This is |
| 48 | + * an approximation of its signature for the purpose of matching functions that |
| 49 | + * might be the same across link targets. |
| 50 | + */ |
| 51 | +private predicate functionSignature(Function f, string qualifiedName, int nparams) { |
| 52 | + qualifiedName = f.getQualifiedName() and |
| 53 | + nparams = f.getNumberOfParameters() and |
| 54 | + not f.isStatic() |
| 55 | +} |
| 56 | + |
| 57 | +/** |
| 58 | + * Holds if the call context `ctx` reduces the set of viable dispatch |
| 59 | + * targets of `ma` in `c`. |
| 60 | + */ |
| 61 | +predicate reducedViableImplInCallContext(CallInstruction call, Function f, CallInstruction ctx) { none() } |
| 62 | + |
| 63 | +/** |
| 64 | + * Gets a viable dispatch target of `ma` in the context `ctx`. This is |
| 65 | + * restricted to those `ma`s for which the context makes a difference. |
| 66 | + */ |
| 67 | +Function prunedViableImplInCallContext(CallInstruction call, CallInstruction ctx) { none() } |
| 68 | + |
| 69 | +/** |
| 70 | + * Holds if flow returning from `m` to `ma` might return further and if |
| 71 | + * this path restricts the set of call sites that can be returned to. |
| 72 | + */ |
| 73 | +predicate reducedViableImplInReturn(Function f, CallInstruction call) { none() } |
| 74 | + |
| 75 | +/** |
| 76 | + * Gets a viable dispatch target of `ma` in the context `ctx`. This is |
| 77 | + * restricted to those `ma`s and results for which the return flow from the |
| 78 | + * result to `ma` restricts the possible context `ctx`. |
| 79 | + */ |
| 80 | +Function prunedViableImplInCallContextReverse(CallInstruction call, CallInstruction ctx) { none() } |
0 commit comments