Skip to content

Commit d578cec

Browse files
committed
Add CallGraphFromTo queries for all supported languages
- Add CallGraphFromTo.ql for cpp, csharp, go, java, javascript, python, ruby, swift - Each query supports sourceFunction and targetFunction external predicates - Include documentation (.md) and test suites with expected outputs - Update QL pack dependencies to latest versions - Fix go PrintAST query for compatibility with v2.25.0 - Fix java PrintCFG query for compatibility with v2.25.0 Closes #164
1 parent 93d646d commit d578cec

File tree

70 files changed

+1993
-465
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+1993
-465
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# CallGraphFromTo for C++
2+
3+
Displays calls on reachable paths from a source function to a target function, showing transitive call graph connectivity.
4+
5+
## Overview
6+
7+
This query identifies all function calls that lie on any transitive call path from a specified source function to a specified target function. Given both a source and target function name, it reports each call site along the connecting paths, which is useful for understanding indirect call chains, security-relevant data flow paths, and function reachability.
8+
9+
The query uses transitive closure (`calls*`) to determine reachability, then reports only the direct call sites that contribute to paths between the source and target. It accepts function names via external predicates (`sourceFunction` and `targetFunction`) and supports both simple and qualified name matching.
10+
11+
## Use Cases
12+
13+
This query is primarily used for:
14+
15+
- Determining if a call path exists between two functions
16+
- Mapping indirect call chains from a source to a target function
17+
- Analyzing security-relevant paths (e.g., from user input handlers to sensitive operations)
18+
- Understanding transitive dependencies between functions
19+
20+
## Example
21+
22+
The following C++ code demonstrates a transitive call chain from `source` through `intermediate` to `target`:
23+
24+
```cpp
25+
void target() {}
26+
27+
void intermediate() {
28+
target();
29+
}
30+
31+
void source() {
32+
intermediate();
33+
}
34+
```
35+
36+
Running with `sourceFunction = "source"` and `targetFunction = "target"` produces results showing each call site on the path with the message pattern ``Reachable call from `source`to`intermediate```.
37+
38+
## Output Format
39+
40+
The query is a `@kind problem` query producing rows of:
41+
42+
- ``select call, "Reachable call from `caller` to `callee`"``
43+
44+
## References
45+
46+
- [C++ Functions](https://en.cppreference.com/w/cpp/language/functions)
47+
- [CodeQL Call Graph Analysis](https://codeql.github.com/docs/writing-codeql-queries/about-data-flow-analysis/)
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/**
2+
* @name Call Graph From To for cpp
3+
* @description Displays calls on reachable paths from a source function to a target function, showing transitive call graph connectivity.
4+
* @id cpp/tools/call-graph-from-to
5+
* @kind problem
6+
* @problem.severity recommendation
7+
* @tags call-graph
8+
*/
9+
10+
import cpp
11+
12+
/**
13+
* Gets the source function name for call graph reachability analysis.
14+
* Can be a single function name or comma-separated list of function names.
15+
*/
16+
external string sourceFunction();
17+
18+
/**
19+
* Gets the target function name for call graph reachability analysis.
20+
* Can be a single function name or comma-separated list of function names.
21+
*/
22+
external string targetFunction();
23+
24+
/**
25+
* Gets a single source function name from the comma-separated list.
26+
*/
27+
string getSourceFunctionName() { result = sourceFunction().splitAt(",").trim() }
28+
29+
/**
30+
* Gets a single target function name from the comma-separated list.
31+
*/
32+
string getTargetFunctionName() { result = targetFunction().splitAt(",").trim() }
33+
34+
/**
35+
* Gets a function by matching against the selected source function names.
36+
*/
37+
Function getSourceFunction() {
38+
exists(string selectedFunc |
39+
selectedFunc = getSourceFunctionName() and
40+
(
41+
// Match by exact function name
42+
result.getName() = selectedFunc or
43+
// Match by qualified name
44+
result.getQualifiedName() = selectedFunc
45+
)
46+
)
47+
}
48+
49+
/**
50+
* Gets a function by matching against the selected target function names.
51+
*/
52+
Function getTargetFunction() {
53+
exists(string selectedFunc |
54+
selectedFunc = getTargetFunctionName() and
55+
(
56+
// Match by exact function name
57+
result.getName() = selectedFunc or
58+
// Match by qualified name
59+
result.getQualifiedName() = selectedFunc
60+
)
61+
)
62+
}
63+
64+
/**
65+
* Holds if function `caller` directly calls function `callee`.
66+
*/
67+
predicate calls(Function caller_, Function callee_) {
68+
exists(FunctionCall c | c.getEnclosingFunction() = caller_ and c.getTarget() = callee_)
69+
}
70+
71+
from FunctionCall call, Function caller, Function callee
72+
where
73+
call.getTarget() = callee and
74+
call.getEnclosingFunction() = caller and
75+
(
76+
// Use external predicates if available: show calls on paths from source to target
77+
exists(Function source, Function target |
78+
source = getSourceFunction() and
79+
target = getTargetFunction() and
80+
calls*(source, caller) and
81+
calls*(callee, target)
82+
)
83+
or
84+
// Fallback for unit tests: include test files
85+
(
86+
not exists(getSourceFunctionName()) and
87+
not exists(getTargetFunctionName()) and
88+
caller.getFile().getParentContainer().getParentContainer().getBaseName() = "test"
89+
)
90+
)
91+
select call,
92+
"Reachable call from `" + caller.getQualifiedName() + "` to `" + callee.getQualifiedName() + "`"

server/ql/cpp/tools/src/codeql-pack.lock.yml

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,27 @@
22
lockVersion: 1.0.0
33
dependencies:
44
codeql/controlflow:
5-
version: 2.0.25
5+
version: 2.0.28
66
codeql/cpp-all:
7-
version: 7.1.0
7+
version: 8.0.1
88
codeql/dataflow:
9-
version: 2.0.25
9+
version: 2.1.0
1010
codeql/mad:
11-
version: 1.0.41
11+
version: 1.0.44
1212
codeql/quantum:
13-
version: 0.0.19
13+
version: 0.0.22
1414
codeql/rangeanalysis:
15-
version: 1.0.41
15+
version: 1.0.44
1616
codeql/ssa:
17-
version: 2.0.17
17+
version: 2.0.20
1818
codeql/tutorial:
19-
version: 1.0.41
19+
version: 1.0.44
2020
codeql/typeflow:
21-
version: 1.0.41
21+
version: 1.0.44
2222
codeql/typetracking:
23-
version: 2.0.25
24-
codeql/util:
2523
version: 2.0.28
24+
codeql/util:
25+
version: 2.0.31
2626
codeql/xml:
27-
version: 1.0.41
27+
version: 1.0.44
2828
compiled: false

server/ql/cpp/tools/src/codeql-pack.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ version: 2.25.0
33
description: 'Queries for codeql-development-mcp-server tools for cpp language'
44
library: false
55
dependencies:
6-
codeql/cpp-all: 7.1.0
6+
codeql/cpp-all: 8.0.1
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
| Example1.cpp:6:5:6:13 | call to unrelated | Reachable call from `target` to `unrelated` |
2+
| Example1.cpp:10:5:10:10 | call to target | Reachable call from `intermediate` to `target` |
3+
| Example1.cpp:14:5:14:16 | call to intermediate | Reachable call from `source` to `intermediate` |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CallGraphFromTo/CallGraphFromTo.ql
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
void unrelated() {
2+
// No calls
3+
}
4+
5+
void target() {
6+
unrelated();
7+
}
8+
9+
void intermediate() {
10+
target();
11+
}
12+
13+
void source() {
14+
intermediate();
15+
}

server/ql/cpp/tools/test/codeql-pack.lock.yml

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,27 @@
22
lockVersion: 1.0.0
33
dependencies:
44
codeql/controlflow:
5-
version: 2.0.25
5+
version: 2.0.28
66
codeql/cpp-all:
7-
version: 7.1.0
7+
version: 8.0.1
88
codeql/dataflow:
9-
version: 2.0.25
9+
version: 2.1.0
1010
codeql/mad:
11-
version: 1.0.41
11+
version: 1.0.44
1212
codeql/quantum:
13-
version: 0.0.19
13+
version: 0.0.22
1414
codeql/rangeanalysis:
15-
version: 1.0.41
15+
version: 1.0.44
1616
codeql/ssa:
17-
version: 2.0.17
17+
version: 2.0.20
1818
codeql/tutorial:
19-
version: 1.0.41
19+
version: 1.0.44
2020
codeql/typeflow:
21-
version: 1.0.41
21+
version: 1.0.44
2222
codeql/typetracking:
23-
version: 2.0.25
24-
codeql/util:
2523
version: 2.0.28
24+
codeql/util:
25+
version: 2.0.31
2626
codeql/xml:
27-
version: 1.0.41
27+
version: 1.0.44
2828
compiled: false
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# CallGraphFromTo for `csharp` Source Files
2+
3+
Displays calls on reachable paths from a source method to a target method, showing transitive call graph connectivity.
4+
5+
## Overview
6+
7+
This query identifies all method calls that lie on any transitive call path from a specified source method to a specified target method. Given both a source and target method name, it reports each call site along the connecting paths, which is useful for understanding indirect call chains, security-relevant data flow paths, and method reachability.
8+
9+
The query uses transitive closure (`calls*`) to determine reachability, then reports only the direct call sites that contribute to paths between the source and target. It accepts method names via external predicates (`sourceFunction` and `targetFunction`).
10+
11+
## Use Cases
12+
13+
This query is primarily used for:
14+
15+
- Determining if a call path exists between two methods
16+
- Mapping indirect call chains from a source to a target method
17+
- Analyzing security-relevant paths (e.g., from user input handlers to sensitive operations)
18+
- Understanding transitive dependencies between methods
19+
20+
## Example
21+
22+
The following C# code demonstrates a transitive call chain from `Source` through `Intermediate` to `Target`:
23+
24+
```csharp
25+
class Example {
26+
void Target() {}
27+
28+
void Intermediate() {
29+
Target();
30+
}
31+
32+
void Source() {
33+
Intermediate();
34+
}
35+
}
36+
```
37+
38+
Running with `sourceFunction = "Source"` and `targetFunction = "Target"` produces results showing each call site on the path with the message pattern ``Reachable call from `Source`to`Intermediate```.
39+
40+
## Output Format
41+
42+
The query is a `@kind problem` query producing rows of:
43+
44+
- ``select call, "Reachable call from `caller` to `callee`"``
45+
46+
## References
47+
48+
- [C# Methods](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/methods)
49+
- [CodeQL Call Graph Analysis](https://codeql.github.com/docs/writing-codeql-queries/about-data-flow-analysis/)
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/**
2+
* @name Call Graph From To for csharp
3+
* @description Displays calls on reachable paths from a source method to a target method, showing transitive call graph connectivity.
4+
* @id csharp/tools/call-graph-from-to
5+
* @kind problem
6+
* @problem.severity recommendation
7+
* @tags call-graph
8+
*/
9+
10+
import csharp
11+
12+
/**
13+
* Gets the source method name for call graph reachability analysis.
14+
* Can be a single method name or comma-separated list of method names.
15+
*/
16+
external string sourceFunction();
17+
18+
/**
19+
* Gets the target method name for call graph reachability analysis.
20+
* Can be a single method name or comma-separated list of method names.
21+
*/
22+
external string targetFunction();
23+
24+
/**
25+
* Gets a single source method name from the comma-separated list.
26+
*/
27+
string getSourceFunctionName() { result = sourceFunction().splitAt(",").trim() }
28+
29+
/**
30+
* Gets a single target method name from the comma-separated list.
31+
*/
32+
string getTargetFunctionName() { result = targetFunction().splitAt(",").trim() }
33+
34+
/**
35+
* Gets a method by matching against the selected source method names.
36+
*/
37+
Callable getSourceFunction() {
38+
exists(string selectedFunc |
39+
selectedFunc = getSourceFunctionName() and
40+
result.getName() = selectedFunc
41+
)
42+
}
43+
44+
/**
45+
* Gets a method by matching against the selected target method names.
46+
*/
47+
Callable getTargetFunction() {
48+
exists(string selectedFunc |
49+
selectedFunc = getTargetFunctionName() and
50+
result.getName() = selectedFunc
51+
)
52+
}
53+
54+
/**
55+
* Holds if callable `caller` directly calls callable `callee`.
56+
*/
57+
predicate calls(Callable caller_, Callable callee_) {
58+
exists(Call c | c.getEnclosingCallable() = caller_ and c.getTarget() = callee_)
59+
}
60+
61+
from Call call, Callable caller, Callable callee
62+
where
63+
call.getEnclosingCallable() = caller and
64+
call.getTarget() = callee and
65+
(
66+
// Use external predicates if available: show calls on paths from source to target
67+
exists(Callable source, Callable target |
68+
source = getSourceFunction() and
69+
target = getTargetFunction() and
70+
calls*(source, caller) and
71+
calls*(callee, target)
72+
)
73+
or
74+
// Fallback for unit tests: include test files
75+
(
76+
not exists(getSourceFunctionName()) and
77+
not exists(getTargetFunctionName()) and
78+
caller.getFile().getParentContainer().getParentContainer().getBaseName() = "test"
79+
)
80+
)
81+
select call,
82+
"Reachable call from `" + caller.getName() + "` to `" + callee.getName() + "`"

0 commit comments

Comments
 (0)