Skip to content

Commit 14f1ecb

Browse files
committed
C++: Data flow dispatch across link targets
1 parent 9d595aa commit 14f1ecb

File tree

1 file changed

+49
-1
lines changed

1 file changed

+49
-1
lines changed

cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowDispatch.qll

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,59 @@ private import cpp
22
private import DataFlowPrivate
33

44
Function viableImpl(MethodAccess ma) {
5-
result = ma.getTarget()
5+
result = viableCallable(ma)
66
}
77

8+
/**
9+
* Gets a function that might be called by `call`.
10+
*/
811
Function viableCallable(Call call) {
912
result = call.getTarget()
13+
or
14+
// If the target of the call does not have a body in the snapshot, it might
15+
// be because the target is just a header declaration, and the real target
16+
// will be determined at run time when the caller and callee are linked
17+
// together by the operating system's dynamic linker. In case a _unique_
18+
// function with the right signature is present in the database, we return
19+
// that as a potential callee.
20+
exists(string qualifiedName, int nparams |
21+
callSignatureWithoutBody(qualifiedName, nparams, call) and
22+
functionSignatureWithBody(qualifiedName, nparams, result) and
23+
strictcount(Function other | functionSignatureWithBody(qualifiedName, nparams, other)) = 1
24+
)
25+
}
26+
27+
/**
28+
* Holds if `f` is a function with a body that has name `qualifiedName` and
29+
* `nparams` parameter count. See `functionSignature`.
30+
*/
31+
private predicate functionSignatureWithBody(string qualifiedName, int nparams, Function f) {
32+
functionSignature(f, qualifiedName, nparams) and
33+
exists(f.getBlock())
34+
}
35+
36+
/**
37+
* Holds if the target of `call` is a function _with no definition_ that has
38+
* name `qualifiedName` and `nparams` parameter count. See `functionSignature`.
39+
*/
40+
pragma[noinline]
41+
private predicate callSignatureWithoutBody(string qualifiedName, int nparams, Call call) {
42+
exists(Function target |
43+
target = call.getTarget() and
44+
not exists(target.getBlock()) and
45+
functionSignature(target, qualifiedName, nparams)
46+
)
47+
}
48+
49+
/**
50+
* Holds if `f` has name `qualifiedName` and `nparams` parameter count. This is
51+
* an approximation of its signature for the purpose of matching functions that
52+
* might be the same across link targets.
53+
*/
54+
private predicate functionSignature(Function f, string qualifiedName, int nparams) {
55+
qualifiedName = f.getQualifiedName() and
56+
nparams = f.getNumberOfParameters() and
57+
not f.isStatic()
1058
}
1159

1260
/**

0 commit comments

Comments
 (0)