-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathInlineCallGraphTest.ql
More file actions
75 lines (66 loc) · 2.48 KB
/
InlineCallGraphTest.ql
File metadata and controls
75 lines (66 loc) · 2.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import python
import TestUtilities.InlineExpectationsTest
private import semmle.python.dataflow.new.internal.DataFlowDispatch as TT
/** Holds when `call` is resolved to `callable` using points-to based call-graph. */
predicate pointsToCallEdge(CallNode call, Function callable) {
exists(PythonFunctionValue funcValue |
funcValue.getScope() = callable and
call = funcValue.getACall()
)
}
/** Holds when `call` is resolved to `callable` using type-tracking based call-graph. */
predicate typeTrackerCallEdge(CallNode call, Function callable) {
exists(TT::DataFlowCallable dfCallable, TT::DataFlowCall dfCall |
dfCallable.getScope() = callable and
dfCall.getNode() = call and
dfCallable = TT::viableCallable(dfCall)
)
}
class CallGraphTest extends InlineExpectationsTest {
CallGraphTest() { this = "CallGraphTest" }
override string getARelevantTag() { result in ["pt", "tt"] }
override predicate hasActualResult(Location location, string element, string tag, string value) {
exists(location.getFile().getRelativePath()) and
exists(CallNode call, Function target |
tag = "tt" and
typeTrackerCallEdge(call, target)
or
tag = "pt" and
pointsToCallEdge(call, target)
|
location = call.getLocation() and
element = call.toString() and
value = betterQualName(target)
)
}
}
bindingset[func]
string betterQualName(Function func) {
// note: `target.getQualifiedName` for Lambdas is just "lambda", so is not very useful :|
not func.isLambda() and
result = func.getQualifiedName()
or
func.isLambda() and
result =
"lambda[" + func.getLocation().getFile().getShortName() + ":" +
func.getLocation().getStartLine() + ":" + func.getLocation().getStartColumn() + "]"
}
query predicate debug_callableNotUnique(Function callable, string message) {
exists(Function f | f != callable and f.getQualifiedName() = callable.getQualifiedName()) and
message =
"Qualified function name '" + callable.getQualifiedName() + "' is not unique. Please fix."
}
query predicate pointsTo_found_typeTracker_notFound(CallNode call, string qualname) {
exists(Function target |
pointsToCallEdge(call, target) and
not typeTrackerCallEdge(call, target) and
qualname = betterQualName(target)
)
}
query predicate typeTracker_found_pointsTo_notFound(CallNode call, string qualname) {
exists(Function target |
not pointsToCallEdge(call, target) and
typeTrackerCallEdge(call, target) and
qualname = betterQualName(target)
)
}