codeql-development-mcp-server 2.24.1-rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +178 -0
- package/README.md +113 -0
- package/dist/codeql-development-mcp-server.js +9474 -0
- package/dist/codeql-development-mcp-server.js.map +7 -0
- package/package.json +101 -0
- package/ql/README.md +57 -0
- package/ql/actions/tools/src/PrintAST/PrintAST.ql +40 -0
- package/ql/actions/tools/src/PrintCFG/PrintCFG.md +53 -0
- package/ql/actions/tools/src/PrintCFG/PrintCFG.ql +23 -0
- package/ql/actions/tools/src/codeql-pack.lock.yml +32 -0
- package/ql/actions/tools/src/codeql-pack.yml +6 -0
- package/ql/cpp/tools/src/CallGraphFrom/CallGraphFrom.ql +55 -0
- package/ql/cpp/tools/src/CallGraphTo/CallGraphTo.ql +55 -0
- package/ql/cpp/tools/src/PrintAST/PrintAST.ql +57 -0
- package/ql/cpp/tools/src/PrintCFG/PrintCFG.md +56 -0
- package/ql/cpp/tools/src/PrintCFG/PrintCFG.ql +22 -0
- package/ql/cpp/tools/src/codeql-pack.lock.yml +28 -0
- package/ql/cpp/tools/src/codeql-pack.yml +6 -0
- package/ql/csharp/tools/src/CallGraphFrom/CallGraphFrom.ql +50 -0
- package/ql/csharp/tools/src/CallGraphTo/CallGraphTo.ql +50 -0
- package/ql/csharp/tools/src/PrintAST/PrintAST.ql +57 -0
- package/ql/csharp/tools/src/PrintCFG/PrintCFG.md +55 -0
- package/ql/csharp/tools/src/PrintCFG/PrintCFG.ql +22 -0
- package/ql/csharp/tools/src/codeql-pack.lock.yml +24 -0
- package/ql/csharp/tools/src/codeql-pack.yml +6 -0
- package/ql/go/tools/src/CallGraphFrom/CallGraphFrom.ql +39 -0
- package/ql/go/tools/src/CallGraphTo/CallGraphTo.ql +47 -0
- package/ql/go/tools/src/PrintAST/PrintAST.ql +58 -0
- package/ql/go/tools/src/PrintCFG/PrintCFG.md +55 -0
- package/ql/go/tools/src/PrintCFG/PrintCFG.ql +22 -0
- package/ql/go/tools/src/codeql-pack.lock.yml +24 -0
- package/ql/go/tools/src/codeql-pack.yml +6 -0
- package/ql/java/tools/src/CallGraphFrom/CallGraphFrom.ql +50 -0
- package/ql/java/tools/src/CallGraphTo/CallGraphTo.ql +50 -0
- package/ql/java/tools/src/PrintAST/PrintAST.ql +57 -0
- package/ql/java/tools/src/PrintCFG/PrintCFG.md +55 -0
- package/ql/java/tools/src/PrintCFG/PrintCFG.ql +35 -0
- package/ql/java/tools/src/codeql-pack.lock.yml +32 -0
- package/ql/java/tools/src/codeql-pack.yml +6 -0
- package/ql/javascript/tools/src/CallGraphFrom/CallGraphFrom.ql +49 -0
- package/ql/javascript/tools/src/CallGraphTo/CallGraphTo.ql +47 -0
- package/ql/javascript/tools/src/PrintAST/PrintAST.ql +60 -0
- package/ql/javascript/tools/src/PrintCFG/PrintCFG.md +57 -0
- package/ql/javascript/tools/src/PrintCFG/PrintCFG.ql +21 -0
- package/ql/javascript/tools/src/codeql-pack.lock.yml +30 -0
- package/ql/javascript/tools/src/codeql-pack.yml +6 -0
- package/ql/python/tools/src/CallGraphFrom/CallGraphFrom.ql +49 -0
- package/ql/python/tools/src/CallGraphTo/CallGraphTo.ql +47 -0
- package/ql/python/tools/src/PrintAST/PrintAST.ql +62 -0
- package/ql/python/tools/src/PrintCFG/PrintCFG.md +52 -0
- package/ql/python/tools/src/PrintCFG/PrintCFG.ql +21 -0
- package/ql/python/tools/src/codeql-pack.lock.yml +30 -0
- package/ql/python/tools/src/codeql-pack.yml +6 -0
- package/ql/ruby/tools/src/CallGraphFrom/CallGraphFrom.ql +40 -0
- package/ql/ruby/tools/src/CallGraphTo/CallGraphTo.ql +48 -0
- package/ql/ruby/tools/src/PrintAST/PrintAST.ql +57 -0
- package/ql/ruby/tools/src/PrintCFG/PrintCFG.md +55 -0
- package/ql/ruby/tools/src/PrintCFG/PrintCFG.ql +22 -0
- package/ql/ruby/tools/src/codeql-pack.lock.yml +24 -0
- package/ql/ruby/tools/src/codeql-pack.yml +6 -0
- package/ql/swift/tools/src/CallGraphFrom/CallGraphFrom.ql +53 -0
- package/ql/swift/tools/src/CallGraphTo/CallGraphTo.ql +49 -0
- package/ql/swift/tools/src/PrintAST/PrintAST.ql +58 -0
- package/ql/swift/tools/src/PrintCFG/PrintCFG.ql +68 -0
- package/ql/swift/tools/src/codeql-pack.lock.yml +24 -0
- package/ql/swift/tools/src/codeql-pack.yml +6 -0
- package/scripts/setup-packs.sh +150 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @name Call Graph To for csharp
|
|
3
|
+
* @description Displays calls made to a specified method, showing the call graph inbound to the target method.
|
|
4
|
+
* @id csharp/tools/call-graph-to
|
|
5
|
+
* @kind problem
|
|
6
|
+
* @problem.severity recommendation
|
|
7
|
+
* @tags call-graph
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import csharp
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Gets the target method name for which to generate the call graph.
|
|
14
|
+
* Can be a single method name or comma-separated list of method names.
|
|
15
|
+
*/
|
|
16
|
+
external string targetFunction();
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Gets a single target method name from the comma-separated list.
|
|
20
|
+
*/
|
|
21
|
+
string getTargetFunctionName() {
|
|
22
|
+
result = targetFunction().splitAt(",").trim()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Gets a method by matching against the selected target method names.
|
|
27
|
+
*/
|
|
28
|
+
Callable getTargetFunction() {
|
|
29
|
+
exists(string selectedFunc |
|
|
30
|
+
selectedFunc = getTargetFunctionName() and
|
|
31
|
+
result.getName() = selectedFunc
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
from Call call, Callable target, Callable caller
|
|
36
|
+
where
|
|
37
|
+
call.getTarget() = target and
|
|
38
|
+
call.getEnclosingCallable() = caller and
|
|
39
|
+
(
|
|
40
|
+
// Use external predicate if available
|
|
41
|
+
target = getTargetFunction()
|
|
42
|
+
or
|
|
43
|
+
// Fallback for unit tests: include test files
|
|
44
|
+
(
|
|
45
|
+
not exists(getTargetFunction()) and
|
|
46
|
+
target.getFile().getParentContainer().getParentContainer().getBaseName() = "test"
|
|
47
|
+
)
|
|
48
|
+
)
|
|
49
|
+
select call,
|
|
50
|
+
"Call to `" + target.getName() + "` from `" + caller.getName() + "`"
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @name Print AST for csharp
|
|
3
|
+
* @description Outputs a representation of the Abstract Syntax Tree for specified source files.
|
|
4
|
+
* @id csharp/tools/print-ast
|
|
5
|
+
* @kind graph
|
|
6
|
+
* @tags ast
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import csharp
|
|
10
|
+
import semmle.code.csharp.PrintAst
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Gets the source files to generate AST from.
|
|
14
|
+
* Can be a single file path or comma-separated list of file paths.
|
|
15
|
+
*/
|
|
16
|
+
external string selectedSourceFiles();
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Gets a single source file from the comma-separated list.
|
|
20
|
+
*/
|
|
21
|
+
string getSelectedSourceFile() {
|
|
22
|
+
result = selectedSourceFiles().splitAt(",").trim()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Gets a file by matching against the selected source file paths.
|
|
27
|
+
*/
|
|
28
|
+
File getSelectedFile() {
|
|
29
|
+
exists(string selectedFile |
|
|
30
|
+
selectedFile = getSelectedSourceFile() and
|
|
31
|
+
(
|
|
32
|
+
// Match by exact relative path from source root
|
|
33
|
+
result.getRelativePath() = selectedFile or
|
|
34
|
+
// Match by file name if no path separators
|
|
35
|
+
(not selectedFile.matches("%/%") and result.getBaseName() = selectedFile) or
|
|
36
|
+
// Match by ending path component
|
|
37
|
+
result.getAbsolutePath().suffix(result.getAbsolutePath().length() - selectedFile.length()) = selectedFile
|
|
38
|
+
)
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Configuration for PrintAST that uses external predicates to specify source files.
|
|
44
|
+
* Falls back to all files when external predicates are not available (for unit tests).
|
|
45
|
+
*/
|
|
46
|
+
class Cfg extends PrintAstConfiguration {
|
|
47
|
+
override predicate shouldPrint(Element e, Location l) {
|
|
48
|
+
super.shouldPrint(e, l) and
|
|
49
|
+
(
|
|
50
|
+
// Use external predicate if available
|
|
51
|
+
l.getFile() = getSelectedFile()
|
|
52
|
+
or
|
|
53
|
+
// Fallback for unit tests: include all files
|
|
54
|
+
not exists(getSelectedFile())
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Print CFG for `csharp` Source Files
|
|
2
|
+
|
|
3
|
+
Produces a representation of a file's Control Flow Graph (CFG) for specified source files.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The Control Flow Graph represents the order in which statements and expressions are executed in a program. Each node in the graph represents a control-flow element (statement or expression), and edges represent possible execution paths between them.
|
|
8
|
+
|
|
9
|
+
This query outputs all CFG nodes and their successor relationships for C# code, which is useful for understanding program execution flow, debugging control flow issues, and analyzing code paths.
|
|
10
|
+
|
|
11
|
+
## Use Cases
|
|
12
|
+
|
|
13
|
+
This query is primarily used for:
|
|
14
|
+
|
|
15
|
+
- Visualizing program execution flow
|
|
16
|
+
- Understanding complex branching logic
|
|
17
|
+
- Debugging control flow issues
|
|
18
|
+
- Analysis of code paths and reachability
|
|
19
|
+
- IDE integration for control flow visualization
|
|
20
|
+
|
|
21
|
+
## Example
|
|
22
|
+
|
|
23
|
+
The following C# code demonstrates control flow through conditional statements and loops:
|
|
24
|
+
|
|
25
|
+
```csharp
|
|
26
|
+
public void Example(int x) {
|
|
27
|
+
if (x > 0) { // COMPLIANT - Branching creates CFG edges
|
|
28
|
+
Console.WriteLine("Positive");
|
|
29
|
+
} else {
|
|
30
|
+
Console.WriteLine("Non-positive");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
for (int i = 0; i < 3; i++) { // COMPLIANT - Loop creates cyclic CFG
|
|
34
|
+
Console.WriteLine(i);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
In the resulting CFG:
|
|
40
|
+
|
|
41
|
+
- The `if` condition creates two outgoing edges (true/false branches)
|
|
42
|
+
- The `for` loop creates a cycle back to the condition check
|
|
43
|
+
- Each statement connects to its successor in execution order
|
|
44
|
+
|
|
45
|
+
## Output Format
|
|
46
|
+
|
|
47
|
+
The query produces two relations:
|
|
48
|
+
|
|
49
|
+
- `nodes(ControlFlow::Node, string, string)`: Each CFG node with its label
|
|
50
|
+
- `edges(ControlFlow::Node, ControlFlow::Node)`: Successor relationships between nodes
|
|
51
|
+
|
|
52
|
+
## References
|
|
53
|
+
|
|
54
|
+
- [C# Control Flow](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/selection-statements)
|
|
55
|
+
- [CodeQL Control Flow Graph](https://codeql.github.com/docs/writing-codeql-queries/about-control-flow-in-codeql/)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @name Print CFG for csharp
|
|
3
|
+
* @description Produces a representation of a file's Control Flow Graph for specified source files.
|
|
4
|
+
* @id csharp/tools/print-cfg
|
|
5
|
+
* @kind graph
|
|
6
|
+
* @tags cfg
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import csharp
|
|
10
|
+
import semmle.code.csharp.controlflow.ControlFlowGraph
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Configuration for PrintCFG that outputs all CFG nodes and edges.
|
|
14
|
+
*/
|
|
15
|
+
query predicate nodes(ControlFlow::Node node, string property, string value) {
|
|
16
|
+
property = "semmle.label" and
|
|
17
|
+
value = node.toString()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
query predicate edges(ControlFlow::Node pred, ControlFlow::Node succ) {
|
|
21
|
+
pred.getASuccessor() = succ
|
|
22
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
lockVersion: 1.0.0
|
|
3
|
+
dependencies:
|
|
4
|
+
codeql/controlflow:
|
|
5
|
+
version: 2.0.25
|
|
6
|
+
codeql/csharp-all:
|
|
7
|
+
version: 5.4.6
|
|
8
|
+
codeql/dataflow:
|
|
9
|
+
version: 2.0.25
|
|
10
|
+
codeql/mad:
|
|
11
|
+
version: 1.0.41
|
|
12
|
+
codeql/ssa:
|
|
13
|
+
version: 2.0.17
|
|
14
|
+
codeql/threat-models:
|
|
15
|
+
version: 1.0.41
|
|
16
|
+
codeql/tutorial:
|
|
17
|
+
version: 1.0.41
|
|
18
|
+
codeql/typetracking:
|
|
19
|
+
version: 2.0.25
|
|
20
|
+
codeql/util:
|
|
21
|
+
version: 2.0.28
|
|
22
|
+
codeql/xml:
|
|
23
|
+
version: 1.0.41
|
|
24
|
+
compiled: false
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @name Call Graph From for go
|
|
3
|
+
* @description Displays calls made from a specified function, showing the call graph outbound from the source function.
|
|
4
|
+
* @id go/tools/call-graph-from
|
|
5
|
+
* @kind problem
|
|
6
|
+
* @problem.severity recommendation
|
|
7
|
+
* @tags call-graph
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import go
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Gets the source function name for which to generate the call graph.
|
|
14
|
+
* Can be a single function name or comma-separated list of function names.
|
|
15
|
+
*/
|
|
16
|
+
external string sourceFunction();
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Gets a single source function name from the comma-separated list.
|
|
20
|
+
*/
|
|
21
|
+
string getSourceFunctionName() {
|
|
22
|
+
result = sourceFunction().splitAt(",").trim()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
from CallExpr call, FuncDecl source
|
|
26
|
+
where
|
|
27
|
+
call.getEnclosingFunction() = source and
|
|
28
|
+
(
|
|
29
|
+
// Use external predicate if available
|
|
30
|
+
source.getName() = getSourceFunctionName()
|
|
31
|
+
or
|
|
32
|
+
// Fallback for unit tests: include test files
|
|
33
|
+
(
|
|
34
|
+
not exists(getSourceFunctionName()) and
|
|
35
|
+
source.getFile().getParentContainer().getParentContainer().getBaseName() = "test"
|
|
36
|
+
)
|
|
37
|
+
)
|
|
38
|
+
select call,
|
|
39
|
+
"Call from `" + source.getName() + "` to `" + call.getTarget().getName() + "`"
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @name Call Graph To for go
|
|
3
|
+
* @description Displays calls made to a specified function, showing the call graph inbound to the target function.
|
|
4
|
+
* @id go/tools/call-graph-to
|
|
5
|
+
* @kind problem
|
|
6
|
+
* @problem.severity recommendation
|
|
7
|
+
* @tags call-graph
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import go
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Gets the target function name for which to generate the call graph.
|
|
14
|
+
* Can be a single function name or comma-separated list of function names.
|
|
15
|
+
*/
|
|
16
|
+
external string targetFunction();
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Gets a single target function name from the comma-separated list.
|
|
20
|
+
*/
|
|
21
|
+
string getTargetFunctionName() {
|
|
22
|
+
result = targetFunction().splitAt(",").trim()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Gets the caller name for a call expression.
|
|
27
|
+
*/
|
|
28
|
+
string getCallerName(CallExpr call) {
|
|
29
|
+
if exists(call.getEnclosingFunction())
|
|
30
|
+
then result = call.getEnclosingFunction().getName()
|
|
31
|
+
else result = "Top-level"
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
from CallExpr call
|
|
35
|
+
where
|
|
36
|
+
(
|
|
37
|
+
// Use external predicate if available
|
|
38
|
+
call.getTarget().getName() = getTargetFunctionName()
|
|
39
|
+
or
|
|
40
|
+
// Fallback for unit tests: include test files
|
|
41
|
+
(
|
|
42
|
+
not exists(getTargetFunctionName()) and
|
|
43
|
+
call.getFile().getParentContainer().getParentContainer().getBaseName() = "test"
|
|
44
|
+
)
|
|
45
|
+
)
|
|
46
|
+
select call,
|
|
47
|
+
"Call to `" + call.getTarget().getName() + "` from `" + getCallerName(call) + "`"
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @name Print AST for go
|
|
3
|
+
* @description Outputs a representation of the Abstract Syntax Tree for specified source files.
|
|
4
|
+
* @id go/tools/print-ast
|
|
5
|
+
* @kind graph
|
|
6
|
+
* @tags ast
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import go
|
|
10
|
+
import semmle.go.PrintAst
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Gets the source files to generate AST from.
|
|
14
|
+
* Can be a single file path or comma-separated list of file paths.
|
|
15
|
+
*/
|
|
16
|
+
external string selectedSourceFiles();
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Gets a single source file from the comma-separated list.
|
|
20
|
+
*/
|
|
21
|
+
string getSelectedSourceFile() {
|
|
22
|
+
result = selectedSourceFiles().splitAt(",").trim()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Gets a file by matching against the selected source file paths.
|
|
27
|
+
*/
|
|
28
|
+
File getSelectedFile() {
|
|
29
|
+
exists(string selectedFile |
|
|
30
|
+
selectedFile = getSelectedSourceFile() and
|
|
31
|
+
(
|
|
32
|
+
// Match by exact relative path from source root
|
|
33
|
+
result.getRelativePath() = selectedFile or
|
|
34
|
+
// Match by file name if no path separators
|
|
35
|
+
(not selectedFile.matches("%/%") and result.getBaseName() = selectedFile) or
|
|
36
|
+
// Match by ending path component
|
|
37
|
+
result.getAbsolutePath().suffix(result.getAbsolutePath().length() - selectedFile.length()) = selectedFile
|
|
38
|
+
)
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Configuration for PrintAST that uses external predicates to specify source files.
|
|
44
|
+
* Falls back to test file selection when external predicates are not available.
|
|
45
|
+
*/
|
|
46
|
+
class Cfg extends PrintAstConfiguration {
|
|
47
|
+
override predicate shouldPrintFunction(FuncDecl func) { this.shouldPrintFile(func.getFile()) }
|
|
48
|
+
|
|
49
|
+
override predicate shouldPrintFile(File file) {
|
|
50
|
+
// Use external predicate if available
|
|
51
|
+
file = getSelectedFile()
|
|
52
|
+
or
|
|
53
|
+
// Fallback for unit tests: include specific test files
|
|
54
|
+
(not exists(getSelectedFile()) and file.getBaseName() = "Example1.go")
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
override predicate shouldPrintComments(File file) { none() }
|
|
58
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Print CFG for Go
|
|
2
|
+
|
|
3
|
+
Produces a representation of a file's Control Flow Graph (CFG) for specified source files.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The Control Flow Graph represents the order in which statements and expressions are executed in a program. Each node in the graph represents a control-flow element (statement or expression), and edges represent possible execution paths between them.
|
|
8
|
+
|
|
9
|
+
This query outputs all CFG nodes and their successor relationships for Go code, which is useful for understanding program execution flow, debugging control flow issues, and analyzing code paths.
|
|
10
|
+
|
|
11
|
+
## Use Cases
|
|
12
|
+
|
|
13
|
+
This query is primarily used for:
|
|
14
|
+
|
|
15
|
+
- Visualizing program execution flow
|
|
16
|
+
- Understanding complex branching logic
|
|
17
|
+
- Debugging control flow issues
|
|
18
|
+
- Analysis of code paths and reachability
|
|
19
|
+
- IDE integration for control flow visualization
|
|
20
|
+
|
|
21
|
+
## Example
|
|
22
|
+
|
|
23
|
+
The following Go code demonstrates control flow through conditional statements and loops:
|
|
24
|
+
|
|
25
|
+
```go
|
|
26
|
+
func example(x int) {
|
|
27
|
+
if x > 0 { // COMPLIANT - Branching creates CFG edges
|
|
28
|
+
fmt.Println("Positive")
|
|
29
|
+
} else {
|
|
30
|
+
fmt.Println("Non-positive")
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
for i := 0; i < 3; i++ { // COMPLIANT - Loop creates cyclic CFG
|
|
34
|
+
fmt.Println(i)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
In the resulting CFG:
|
|
40
|
+
|
|
41
|
+
- The `if` condition creates two outgoing edges (true/false branches)
|
|
42
|
+
- The `for` loop creates a cycle back to the condition check
|
|
43
|
+
- Each statement connects to its successor in execution order
|
|
44
|
+
|
|
45
|
+
## Output Format
|
|
46
|
+
|
|
47
|
+
The query produces two relations:
|
|
48
|
+
|
|
49
|
+
- `nodes(ControlFlow::Node, string, string)`: Each CFG node with its label
|
|
50
|
+
- `edges(ControlFlow::Node, ControlFlow::Node)`: Successor relationships between nodes
|
|
51
|
+
|
|
52
|
+
## References
|
|
53
|
+
|
|
54
|
+
- [Go Control Structures](https://go.dev/doc/effective_go#control-structures)
|
|
55
|
+
- [CodeQL Control Flow Graph](https://codeql.github.com/docs/writing-codeql-queries/about-control-flow-in-codeql/)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @name Print CFG for go
|
|
3
|
+
* @description Produces a representation of a file's Control Flow Graph for specified source files.
|
|
4
|
+
* @id go/tools/print-cfg
|
|
5
|
+
* @kind graph
|
|
6
|
+
* @tags cfg
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import go
|
|
10
|
+
import semmle.go.controlflow.ControlFlowGraph
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Configuration for PrintCFG that outputs all CFG nodes and edges.
|
|
14
|
+
*/
|
|
15
|
+
query predicate nodes(ControlFlow::Node node, string property, string value) {
|
|
16
|
+
property = "semmle.label" and
|
|
17
|
+
value = node.toString()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
query predicate edges(ControlFlow::Node pred, ControlFlow::Node succ) {
|
|
21
|
+
pred.getASuccessor() = succ
|
|
22
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
lockVersion: 1.0.0
|
|
3
|
+
dependencies:
|
|
4
|
+
codeql/concepts:
|
|
5
|
+
version: 0.0.15
|
|
6
|
+
codeql/controlflow:
|
|
7
|
+
version: 2.0.25
|
|
8
|
+
codeql/dataflow:
|
|
9
|
+
version: 2.0.25
|
|
10
|
+
codeql/go-all:
|
|
11
|
+
version: 6.0.1
|
|
12
|
+
codeql/mad:
|
|
13
|
+
version: 1.0.41
|
|
14
|
+
codeql/ssa:
|
|
15
|
+
version: 2.0.17
|
|
16
|
+
codeql/threat-models:
|
|
17
|
+
version: 1.0.41
|
|
18
|
+
codeql/tutorial:
|
|
19
|
+
version: 1.0.41
|
|
20
|
+
codeql/typetracking:
|
|
21
|
+
version: 2.0.25
|
|
22
|
+
codeql/util:
|
|
23
|
+
version: 2.0.28
|
|
24
|
+
compiled: false
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @name Call Graph From for java
|
|
3
|
+
* @description Displays calls made from a specified method, showing the call graph outbound from the source method.
|
|
4
|
+
* @id java/tools/call-graph-from
|
|
5
|
+
* @kind problem
|
|
6
|
+
* @problem.severity recommendation
|
|
7
|
+
* @tags call-graph
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import java
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Gets the source method name for which to generate the call graph.
|
|
14
|
+
* Can be a single method name or comma-separated list of method names.
|
|
15
|
+
*/
|
|
16
|
+
external string sourceFunction();
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Gets a single source method name from the comma-separated list.
|
|
20
|
+
*/
|
|
21
|
+
string getSourceFunctionName() {
|
|
22
|
+
result = sourceFunction().splitAt(",").trim()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Gets a method by matching against the selected source method names.
|
|
27
|
+
*/
|
|
28
|
+
Callable getSourceFunction() {
|
|
29
|
+
exists(string selectedFunc |
|
|
30
|
+
selectedFunc = getSourceFunctionName() and
|
|
31
|
+
result.getName() = selectedFunc
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
from Call call, Callable source, Callable callee
|
|
36
|
+
where
|
|
37
|
+
call.getCaller() = source and
|
|
38
|
+
call.getCallee() = callee and
|
|
39
|
+
(
|
|
40
|
+
// Use external predicate if available
|
|
41
|
+
source = getSourceFunction()
|
|
42
|
+
or
|
|
43
|
+
// Fallback for unit tests: include test files
|
|
44
|
+
(
|
|
45
|
+
not exists(getSourceFunction()) and
|
|
46
|
+
source.getFile().getParentContainer().getParentContainer().getBaseName() = "test"
|
|
47
|
+
)
|
|
48
|
+
)
|
|
49
|
+
select call,
|
|
50
|
+
"Call from `" + source.getName() + "` to `" + callee.getName() + "`"
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @name Call Graph To for java
|
|
3
|
+
* @description Displays calls made to a specified method, showing the call graph inbound to the target method.
|
|
4
|
+
* @id java/tools/call-graph-to
|
|
5
|
+
* @kind problem
|
|
6
|
+
* @problem.severity recommendation
|
|
7
|
+
* @tags call-graph
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import java
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Gets the target method name for which to generate the call graph.
|
|
14
|
+
* Can be a single method name or comma-separated list of method names.
|
|
15
|
+
*/
|
|
16
|
+
external string targetFunction();
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Gets a single target method name from the comma-separated list.
|
|
20
|
+
*/
|
|
21
|
+
string getTargetFunctionName() {
|
|
22
|
+
result = targetFunction().splitAt(",").trim()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Gets a method by matching against the selected target method names.
|
|
27
|
+
*/
|
|
28
|
+
Callable getTargetFunction() {
|
|
29
|
+
exists(string selectedFunc |
|
|
30
|
+
selectedFunc = getTargetFunctionName() and
|
|
31
|
+
result.getName() = selectedFunc
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
from Call call, Callable target, Callable caller
|
|
36
|
+
where
|
|
37
|
+
call.getCallee() = target and
|
|
38
|
+
call.getCaller() = caller and
|
|
39
|
+
(
|
|
40
|
+
// Use external predicate if available
|
|
41
|
+
target = getTargetFunction()
|
|
42
|
+
or
|
|
43
|
+
// Fallback for unit tests: include test files
|
|
44
|
+
(
|
|
45
|
+
not exists(getTargetFunction()) and
|
|
46
|
+
target.getFile().getParentContainer().getParentContainer().getBaseName() = "test"
|
|
47
|
+
)
|
|
48
|
+
)
|
|
49
|
+
select call,
|
|
50
|
+
"Call to `" + target.getName() + "` from `" + caller.getName() + "`"
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @name Print AST for java
|
|
3
|
+
* @description Outputs a representation of the Abstract Syntax Tree for specified source files.
|
|
4
|
+
* @id java/tools/print-ast
|
|
5
|
+
* @kind graph
|
|
6
|
+
* @tags ast
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import java
|
|
10
|
+
import semmle.code.java.PrintAst
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Gets the source files to generate AST from.
|
|
14
|
+
* Can be a single file path or comma-separated list of file paths.
|
|
15
|
+
*/
|
|
16
|
+
external string selectedSourceFiles();
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Gets a single source file from the comma-separated list.
|
|
20
|
+
*/
|
|
21
|
+
string getSelectedSourceFile() {
|
|
22
|
+
result = selectedSourceFiles().splitAt(",").trim()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Gets a file by matching against the selected source file paths.
|
|
27
|
+
*/
|
|
28
|
+
File getSelectedFile() {
|
|
29
|
+
exists(string selectedFile |
|
|
30
|
+
selectedFile = getSelectedSourceFile() and
|
|
31
|
+
(
|
|
32
|
+
// Match by exact relative path from source root
|
|
33
|
+
result.getRelativePath() = selectedFile or
|
|
34
|
+
// Match by file name if no path separators
|
|
35
|
+
(not selectedFile.matches("%/%") and result.getBaseName() = selectedFile) or
|
|
36
|
+
// Match by ending path component
|
|
37
|
+
result.getAbsolutePath().suffix(result.getAbsolutePath().length() - selectedFile.length()) = selectedFile
|
|
38
|
+
)
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Configuration for PrintAST that uses external predicates to specify source files.
|
|
44
|
+
* Falls back to test files when external predicates are not available.
|
|
45
|
+
*/
|
|
46
|
+
class Cfg extends PrintAstConfiguration {
|
|
47
|
+
override predicate shouldPrint(Element e, Location l) {
|
|
48
|
+
super.shouldPrint(e, l) and
|
|
49
|
+
(
|
|
50
|
+
// Use external predicate if available
|
|
51
|
+
l.getFile() = getSelectedFile()
|
|
52
|
+
or
|
|
53
|
+
// Fallback for unit tests: include specific test files
|
|
54
|
+
(not exists(getSelectedFile()) and l.getFile().getBaseName() = "Example1.java")
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Print CFG for Java
|
|
2
|
+
|
|
3
|
+
Produces a representation of a file's Control Flow Graph (CFG) for specified source files.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The Control Flow Graph represents the order in which statements and expressions are executed in a program. Each node in the graph represents a control-flow element (statement or expression), and edges represent possible execution paths between them.
|
|
8
|
+
|
|
9
|
+
This query outputs all CFG nodes and their successor relationships for Java code, which is useful for understanding program execution flow, debugging control flow issues, and analyzing code paths.
|
|
10
|
+
|
|
11
|
+
## Use Cases
|
|
12
|
+
|
|
13
|
+
This query is primarily used for:
|
|
14
|
+
|
|
15
|
+
- Visualizing program execution flow
|
|
16
|
+
- Understanding complex branching logic
|
|
17
|
+
- Debugging control flow issues
|
|
18
|
+
- Analysis of code paths and reachability
|
|
19
|
+
- IDE integration for control flow visualization
|
|
20
|
+
|
|
21
|
+
## Example
|
|
22
|
+
|
|
23
|
+
The following Java code demonstrates control flow through conditional statements and loops:
|
|
24
|
+
|
|
25
|
+
```java
|
|
26
|
+
public void example(int x) {
|
|
27
|
+
if (x > 0) { // COMPLIANT - Branching creates CFG edges
|
|
28
|
+
System.out.println("Positive");
|
|
29
|
+
} else {
|
|
30
|
+
System.out.println("Non-positive");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
for (int i = 0; i < 3; i++) { // COMPLIANT - Loop creates cyclic CFG
|
|
34
|
+
System.out.println(i);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
In the resulting CFG:
|
|
40
|
+
|
|
41
|
+
- The `if` condition creates two outgoing edges (true/false branches)
|
|
42
|
+
- The `for` loop creates a cycle back to the condition check
|
|
43
|
+
- Each statement connects to its successor in execution order
|
|
44
|
+
|
|
45
|
+
## Output Format
|
|
46
|
+
|
|
47
|
+
The query produces two relations:
|
|
48
|
+
|
|
49
|
+
- `nodes(ControlFlow::Node, string, string)`: Each CFG node with its label
|
|
50
|
+
- `edges(ControlFlow::Node, ControlFlow::Node)`: Successor relationships between nodes
|
|
51
|
+
|
|
52
|
+
## References
|
|
53
|
+
|
|
54
|
+
- [Java Control Flow Statements](https://docs.oracle.com/javase/tutorial/java/nutsandbolts/flow.html)
|
|
55
|
+
- [CodeQL Control Flow Graph](https://codeql.github.com/docs/writing-codeql-queries/about-control-flow-in-codeql/)
|