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
package/package.json
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "codeql-development-mcp-server",
|
|
3
|
+
"version": "2.24.1-rc1",
|
|
4
|
+
"description": "An MCP server supporting LLM requests for CodeQL development tools and resources.",
|
|
5
|
+
"main": "dist/codeql-development-mcp-server.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"codeql-development-mcp-server": "dist/codeql-development-mcp-server.js",
|
|
9
|
+
"codeql-development-mcp-server-setup-packs": "scripts/setup-packs.sh"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist/",
|
|
13
|
+
"ql/actions/tools/src/",
|
|
14
|
+
"ql/cpp/tools/src/",
|
|
15
|
+
"ql/csharp/tools/src/",
|
|
16
|
+
"ql/go/tools/src/",
|
|
17
|
+
"ql/java/tools/src/",
|
|
18
|
+
"ql/javascript/tools/src/",
|
|
19
|
+
"ql/python/tools/src/",
|
|
20
|
+
"ql/ruby/tools/src/",
|
|
21
|
+
"ql/swift/tools/src/",
|
|
22
|
+
"scripts/setup-packs.sh",
|
|
23
|
+
"package.json",
|
|
24
|
+
"README.md"
|
|
25
|
+
],
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public",
|
|
28
|
+
"registry": "https://registry.npmjs.org"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"codeql",
|
|
32
|
+
"development",
|
|
33
|
+
"llm",
|
|
34
|
+
"mcp",
|
|
35
|
+
"model-context-protocol",
|
|
36
|
+
"ql",
|
|
37
|
+
"sast",
|
|
38
|
+
"security",
|
|
39
|
+
"static-analysis",
|
|
40
|
+
"typescript"
|
|
41
|
+
],
|
|
42
|
+
"author": "@github/ps-codeql",
|
|
43
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
44
|
+
"repository": {
|
|
45
|
+
"type": "git",
|
|
46
|
+
"url": "git+https://github.com/advanced-security/codeql-development-mcp-server.git",
|
|
47
|
+
"directory": "server"
|
|
48
|
+
},
|
|
49
|
+
"homepage": "https://github.com/advanced-security/codeql-development-mcp-server#readme",
|
|
50
|
+
"bugs": {
|
|
51
|
+
"url": "https://github.com/advanced-security/codeql-development-mcp-server/issues"
|
|
52
|
+
},
|
|
53
|
+
"engines": {
|
|
54
|
+
"node": ">=24.13.0",
|
|
55
|
+
"npm": ">=11.6.2"
|
|
56
|
+
},
|
|
57
|
+
"dependencies": {
|
|
58
|
+
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
59
|
+
"cors": "^2.8.6",
|
|
60
|
+
"dotenv": "^17.2.4",
|
|
61
|
+
"express": "^5.2.1",
|
|
62
|
+
"js-yaml": "^4.1.1",
|
|
63
|
+
"lowdb": "^7.0.1",
|
|
64
|
+
"zod": "^3.25.76"
|
|
65
|
+
},
|
|
66
|
+
"devDependencies": {
|
|
67
|
+
"@eslint/js": "^9.39.2",
|
|
68
|
+
"@types/cors": "^2.8.19",
|
|
69
|
+
"@types/express": "^5.0.6",
|
|
70
|
+
"@types/js-yaml": "^4.0.9",
|
|
71
|
+
"@types/node": "^25.2.1",
|
|
72
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
73
|
+
"esbuild": "^0.27.3",
|
|
74
|
+
"eslint": "^9.39.2",
|
|
75
|
+
"eslint-config-prettier": "^10.1.8",
|
|
76
|
+
"eslint-plugin-prettier": "^5.5.5",
|
|
77
|
+
"prettier": "^3.8.1",
|
|
78
|
+
"typescript": "^5.9.3",
|
|
79
|
+
"typescript-eslint": "^8.54.0",
|
|
80
|
+
"vitest": "^4.0.18"
|
|
81
|
+
},
|
|
82
|
+
"scripts": {
|
|
83
|
+
"build": "npm run clean && npm run lint && npm run bundle",
|
|
84
|
+
"build:all": "npm run build && npm run test:ql:fail-fast",
|
|
85
|
+
"bundle": "node esbuild.config.js",
|
|
86
|
+
"clean": "rm -rf dist .tmp",
|
|
87
|
+
"dev:stdio": "npm run build && TRANSPORT_MODE=stdio node dist/codeql-development-mcp-server.js",
|
|
88
|
+
"dev:http": "npm run build && TRANSPORT_MODE=http node dist/codeql-development-mcp-server.js",
|
|
89
|
+
"format": "prettier --write 'src/**/*.ts'",
|
|
90
|
+
"lint": "eslint src test --ext .ts",
|
|
91
|
+
"lint:fix": "eslint src test --ext .ts --fix",
|
|
92
|
+
"start": "npm run build && node dist/codeql-development-mcp-server.js",
|
|
93
|
+
"test": "npm run build && npm run test:ts:coverage",
|
|
94
|
+
"test:coverage": "npm run test:ts:coverage",
|
|
95
|
+
"test:ql": "./scripts/run-query-unit-tests.sh",
|
|
96
|
+
"test:ql:fail-fast": "./scripts/run-query-unit-tests.sh --fail-fast",
|
|
97
|
+
"test:ts": "vitest --run",
|
|
98
|
+
"test:ts:coverage": "vitest --run --coverage",
|
|
99
|
+
"test:watch": "vitest --watch"
|
|
100
|
+
}
|
|
101
|
+
}
|
package/ql/README.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# CodeQL Language Query Structure
|
|
2
|
+
|
|
3
|
+
This directory contains language-specific CodeQL queries -- organized by programming `<language>` -- used in the implementation and/or testing of (CodeQL) MCP server tools.
|
|
4
|
+
|
|
5
|
+
Each `<language>` subdirectory is expected to follow a standardized structure to ensure consistency and maintainability, though there is flexibility to accommodate different subsets of queries and/or tests for each code `<language>`.
|
|
6
|
+
|
|
7
|
+
## Directory Structure
|
|
8
|
+
|
|
9
|
+
Each subdirectory of the `server/ql/<language>/` must implement the following structure:
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
server/ql/<language>/
|
|
13
|
+
├── tools/
|
|
14
|
+
│ ├── src/
|
|
15
|
+
│ │ └── <query-name>.ql # Query implementation files
|
|
16
|
+
│ └── test/
|
|
17
|
+
│ ├── codeql-pack.yml # Test pack configuration
|
|
18
|
+
│ ├── codeql-pack.lock.yml # Lock file for dependencies
|
|
19
|
+
│ └── <query-name>/ # Test directory for each query
|
|
20
|
+
│ ├── <query-name>.qlref # Reference to the query being tested
|
|
21
|
+
│ ├── <query-name>.expected # Expected test output
|
|
22
|
+
│ ├── <test-files> # Test source code files
|
|
23
|
+
│ └── <query-name>.testproj/ # Optional test project directory
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Language Support
|
|
27
|
+
|
|
28
|
+
Currently supported languages:
|
|
29
|
+
|
|
30
|
+
- `actions/` - GitHub Actions workflows
|
|
31
|
+
- `cpp/` - C/C++
|
|
32
|
+
- `csharp/` - C#
|
|
33
|
+
- `go/` - Go
|
|
34
|
+
- `java/` - Java
|
|
35
|
+
- `javascript/` - JavaScript/TypeScript
|
|
36
|
+
- `python/` - Python
|
|
37
|
+
- `ruby/` - Ruby
|
|
38
|
+
- `swift/` - Swift
|
|
39
|
+
|
|
40
|
+
## Testing
|
|
41
|
+
|
|
42
|
+
The `server/scripts/run-query-unit-tests.sh` script automatically discovers and tests all language directories that follow this structure. It will:
|
|
43
|
+
|
|
44
|
+
- Iterate through all subdirectories in `server/ql/`
|
|
45
|
+
- Look for a `tools/` directory in each language
|
|
46
|
+
- Run `codeql test run` on the `tools/test/` directory
|
|
47
|
+
- Count and report the number of `.qlref` files found
|
|
48
|
+
|
|
49
|
+
No manual configuration is required when adding new languages - the test script will automatically include them.
|
|
50
|
+
|
|
51
|
+
## Best Practices
|
|
52
|
+
|
|
53
|
+
- **Consistent naming**: Use descriptive names for queries that reflect their purpose
|
|
54
|
+
- **Comprehensive testing**: Each query should have corresponding test cases
|
|
55
|
+
- **Documentation**: Include comments in query files explaining their purpose and usage
|
|
56
|
+
- **Test coverage**: Ensure test cases cover edge cases and expected behaviors
|
|
57
|
+
- **Pack configuration**: Maintain proper `codeql-pack.yml` files for dependency management
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @name Print AST for actions
|
|
3
|
+
* @description Outputs a representation of the Abstract Syntax Tree for specified source files.
|
|
4
|
+
* @id actions/tools/print-ast
|
|
5
|
+
* @kind graph
|
|
6
|
+
* @tags ast
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
private import codeql.actions.ideContextual.IDEContextual
|
|
10
|
+
import codeql.actions.ideContextual.printAst
|
|
11
|
+
private import codeql.actions.Ast
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Configuration for PrintAST that uses test directory structure (maintains original behavior for unit tests).
|
|
15
|
+
*/
|
|
16
|
+
class Cfg extends PrintAstConfiguration {
|
|
17
|
+
override predicate shouldPrintNode(PrintAstNode n) {
|
|
18
|
+
super.shouldPrintNode(n) and
|
|
19
|
+
// Only include source files with a `test` directory structure
|
|
20
|
+
(
|
|
21
|
+
// For a file located under some `test/*/.github/workflows` directory structure
|
|
22
|
+
n.getLocation()
|
|
23
|
+
.getFile()
|
|
24
|
+
.getParentContainer()
|
|
25
|
+
.getParentContainer()
|
|
26
|
+
.getParentContainer()
|
|
27
|
+
.getParentContainer()
|
|
28
|
+
.getBaseName() = "test"
|
|
29
|
+
or
|
|
30
|
+
// For a file located under some `test/*/*/action.yml` directory structure
|
|
31
|
+
n.getLocation()
|
|
32
|
+
.getFile()
|
|
33
|
+
.getParentContainer()
|
|
34
|
+
.getParentContainer()
|
|
35
|
+
.getParentContainer()
|
|
36
|
+
.getBaseName() = "test" and
|
|
37
|
+
n.getLocation().getFile().getBaseName() = "action.yml"
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Print CFG for GitHub Actions
|
|
2
|
+
|
|
3
|
+
Produces a representation of a file's Control Flow Graph (CFG) for GitHub Actions workflows and composite actions.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The Control Flow Graph represents the order in which steps and jobs are executed in a GitHub Actions workflow. Each node in the graph represents a control-flow element (job, step, or action component), and edges represent possible execution paths between them.
|
|
8
|
+
|
|
9
|
+
This query outputs all CFG nodes and their successor relationships for GitHub Actions YAML files, which is useful for understanding workflow execution flow and analyzing action dependencies.
|
|
10
|
+
|
|
11
|
+
## Use Cases
|
|
12
|
+
|
|
13
|
+
This query is primarily used for:
|
|
14
|
+
|
|
15
|
+
- Visualizing workflow execution flow
|
|
16
|
+
- Understanding job and step dependencies
|
|
17
|
+
- Debugging workflow execution issues
|
|
18
|
+
- Analysis of action execution paths
|
|
19
|
+
- IDE integration for workflow visualization
|
|
20
|
+
|
|
21
|
+
## Example
|
|
22
|
+
|
|
23
|
+
The following GitHub Actions workflow demonstrates control flow through jobs and steps:
|
|
24
|
+
|
|
25
|
+
```yaml
|
|
26
|
+
name: Example Workflow
|
|
27
|
+
on: [push]
|
|
28
|
+
jobs:
|
|
29
|
+
test: # COMPLIANT - Job creates CFG node
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@v2 # COMPLIANT - Step creates CFG node
|
|
33
|
+
- name: Run tests # COMPLIANT - Steps execute sequentially
|
|
34
|
+
run: echo "Testing"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
In the resulting CFG:
|
|
38
|
+
|
|
39
|
+
- Each job creates a CFG scope
|
|
40
|
+
- Steps within a job execute sequentially
|
|
41
|
+
- Actions and run commands create control flow nodes
|
|
42
|
+
|
|
43
|
+
## Output Format
|
|
44
|
+
|
|
45
|
+
The query produces two relations:
|
|
46
|
+
|
|
47
|
+
- `nodes(Node, string, string)`: Each CFG node with its label
|
|
48
|
+
- `edges(Node, Node)`: Successor relationships between nodes
|
|
49
|
+
|
|
50
|
+
## References
|
|
51
|
+
|
|
52
|
+
- [GitHub Actions Workflow Syntax](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions)
|
|
53
|
+
- [CodeQL Control Flow Graph](https://codeql.github.com/docs/writing-codeql-queries/about-control-flow-in-codeql/)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @name Print CFG for actions
|
|
3
|
+
* @description Produces a representation of a file's Control Flow Graph for specified source files.
|
|
4
|
+
* @id actions/tools/print-cfg
|
|
5
|
+
* @kind graph
|
|
6
|
+
* @tags cfg
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import codeql.actions.Ast
|
|
10
|
+
private import codeql.actions.Cfg
|
|
11
|
+
import codeql.actions.controlflow.BasicBlocks
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Configuration for PrintCFG that outputs all CFG nodes and edges.
|
|
15
|
+
*/
|
|
16
|
+
query predicate nodes(Node node, string property, string value) {
|
|
17
|
+
property = "semmle.label" and
|
|
18
|
+
value = node.toString()
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
query predicate edges(Node pred, Node succ) {
|
|
22
|
+
pred.getASuccessor() = succ
|
|
23
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
lockVersion: 1.0.0
|
|
3
|
+
dependencies:
|
|
4
|
+
codeql/actions-all:
|
|
5
|
+
version: 0.4.27
|
|
6
|
+
codeql/concepts:
|
|
7
|
+
version: 0.0.15
|
|
8
|
+
codeql/controlflow:
|
|
9
|
+
version: 2.0.25
|
|
10
|
+
codeql/dataflow:
|
|
11
|
+
version: 2.0.25
|
|
12
|
+
codeql/javascript-all:
|
|
13
|
+
version: 2.6.21
|
|
14
|
+
codeql/mad:
|
|
15
|
+
version: 1.0.41
|
|
16
|
+
codeql/regex:
|
|
17
|
+
version: 1.0.41
|
|
18
|
+
codeql/ssa:
|
|
19
|
+
version: 2.0.17
|
|
20
|
+
codeql/threat-models:
|
|
21
|
+
version: 1.0.41
|
|
22
|
+
codeql/tutorial:
|
|
23
|
+
version: 1.0.41
|
|
24
|
+
codeql/typetracking:
|
|
25
|
+
version: 2.0.25
|
|
26
|
+
codeql/util:
|
|
27
|
+
version: 2.0.28
|
|
28
|
+
codeql/xml:
|
|
29
|
+
version: 1.0.41
|
|
30
|
+
codeql/yaml:
|
|
31
|
+
version: 1.0.41
|
|
32
|
+
compiled: false
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @name Call Graph From for cpp
|
|
3
|
+
* @description Displays calls made from a specified function, showing the call graph outbound from the source function.
|
|
4
|
+
* @id cpp/tools/call-graph-from
|
|
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 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
|
+
/**
|
|
26
|
+
* Gets a function by matching against the selected source function names.
|
|
27
|
+
*/
|
|
28
|
+
Function getSourceFunction() {
|
|
29
|
+
exists(string selectedFunc |
|
|
30
|
+
selectedFunc = getSourceFunctionName() and
|
|
31
|
+
(
|
|
32
|
+
// Match by exact function name
|
|
33
|
+
result.getName() = selectedFunc or
|
|
34
|
+
// Match by qualified name
|
|
35
|
+
result.getQualifiedName() = selectedFunc
|
|
36
|
+
)
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
from FunctionCall call, Function source, Function callee
|
|
41
|
+
where
|
|
42
|
+
call.getTarget() = callee and
|
|
43
|
+
call.getEnclosingFunction() = source and
|
|
44
|
+
(
|
|
45
|
+
// Use external predicate if available
|
|
46
|
+
source = getSourceFunction()
|
|
47
|
+
or
|
|
48
|
+
// Fallback for unit tests: include test files
|
|
49
|
+
(
|
|
50
|
+
not exists(getSourceFunction()) and
|
|
51
|
+
source.getFile().getParentContainer().getParentContainer().getBaseName() = "test"
|
|
52
|
+
)
|
|
53
|
+
)
|
|
54
|
+
select call,
|
|
55
|
+
"Call from `" + source.getQualifiedName() + "` to `" + callee.getQualifiedName() + "`"
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @name Call Graph To for cpp
|
|
3
|
+
* @description Displays calls made to a specified function, showing the call graph inbound to the target function.
|
|
4
|
+
* @id cpp/tools/call-graph-to
|
|
5
|
+
* @kind problem
|
|
6
|
+
* @problem.severity recommendation
|
|
7
|
+
* @tags call-graph
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import cpp
|
|
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 a function by matching against the selected target function names.
|
|
27
|
+
*/
|
|
28
|
+
Function getTargetFunction() {
|
|
29
|
+
exists(string selectedFunc |
|
|
30
|
+
selectedFunc = getTargetFunctionName() and
|
|
31
|
+
(
|
|
32
|
+
// Match by exact function name
|
|
33
|
+
result.getName() = selectedFunc or
|
|
34
|
+
// Match by qualified name
|
|
35
|
+
result.getQualifiedName() = selectedFunc
|
|
36
|
+
)
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
from FunctionCall call, Function target, Function caller
|
|
41
|
+
where
|
|
42
|
+
call.getTarget() = target and
|
|
43
|
+
call.getEnclosingFunction() = caller and
|
|
44
|
+
(
|
|
45
|
+
// Use external predicate if available
|
|
46
|
+
target = getTargetFunction()
|
|
47
|
+
or
|
|
48
|
+
// Fallback for unit tests: include test files
|
|
49
|
+
(
|
|
50
|
+
not exists(getTargetFunction()) and
|
|
51
|
+
target.getFile().getParentContainer().getParentContainer().getBaseName() = "test"
|
|
52
|
+
)
|
|
53
|
+
)
|
|
54
|
+
select call,
|
|
55
|
+
"Call to `" + target.getQualifiedName() + "` from `" + caller.getQualifiedName() + "`"
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @name Print AST for cpp
|
|
3
|
+
* @description Outputs a representation of the Abstract Syntax Tree for specified source files.
|
|
4
|
+
* @id cpp/tools/print-ast
|
|
5
|
+
* @kind graph
|
|
6
|
+
* @tags ast
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import cpp
|
|
10
|
+
import semmle.code.cpp.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 directory structure when external predicates are not available.
|
|
45
|
+
*/
|
|
46
|
+
class Cfg extends PrintAstConfiguration {
|
|
47
|
+
override predicate shouldPrintDeclaration(Declaration decl) {
|
|
48
|
+
// Use external predicate if available
|
|
49
|
+
decl.getFile() = getSelectedFile()
|
|
50
|
+
or
|
|
51
|
+
// Fallback for unit tests: include test files
|
|
52
|
+
(
|
|
53
|
+
not exists(getSelectedFile()) and
|
|
54
|
+
decl.getFile().getParentContainer().getParentContainer().getBaseName() = "test"
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Print CFG for C++
|
|
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
|
+
```cpp
|
|
26
|
+
void example(int x) {
|
|
27
|
+
int result = 0;
|
|
28
|
+
if (x > 0) { // COMPLIANT - Branching creates CFG edges
|
|
29
|
+
result = 1;
|
|
30
|
+
} else {
|
|
31
|
+
result = -1;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
for (int i = 0; i < 3; i++) { // COMPLIANT - Loop creates cyclic CFG
|
|
35
|
+
result = result + i;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
In the resulting CFG:
|
|
41
|
+
|
|
42
|
+
- The `if` condition creates two outgoing edges (true/false branches)
|
|
43
|
+
- The `for` loop creates a cycle back to the condition check
|
|
44
|
+
- Each statement and expression connects to its successor in evaluation order
|
|
45
|
+
|
|
46
|
+
## Output Format
|
|
47
|
+
|
|
48
|
+
The query produces two relations:
|
|
49
|
+
|
|
50
|
+
- `nodes(ControlFlowNode, string, string)`: Each CFG node with its label
|
|
51
|
+
- `edges(ControlFlowNode, ControlFlowNode)`: Successor relationships between nodes
|
|
52
|
+
|
|
53
|
+
## References
|
|
54
|
+
|
|
55
|
+
- [C++ Control Structures](https://en.cppreference.com/w/cpp/language/statements)
|
|
56
|
+
- [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 cpp
|
|
3
|
+
* @description Produces a representation of a file's Control Flow Graph for specified source files.
|
|
4
|
+
* @id cpp/tools/print-cfg
|
|
5
|
+
* @kind graph
|
|
6
|
+
* @tags cfg
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import cpp
|
|
10
|
+
import semmle.code.cpp.controlflow.ControlFlowGraph
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Configuration for PrintCFG that outputs all CFG nodes and edges.
|
|
14
|
+
*/
|
|
15
|
+
query predicate nodes(ControlFlowNode node, string property, string value) {
|
|
16
|
+
property = "semmle.label" and
|
|
17
|
+
value = node.toString()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
query predicate edges(ControlFlowNode pred, ControlFlowNode succ) {
|
|
21
|
+
pred.getASuccessor() = succ
|
|
22
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
lockVersion: 1.0.0
|
|
3
|
+
dependencies:
|
|
4
|
+
codeql/controlflow:
|
|
5
|
+
version: 2.0.25
|
|
6
|
+
codeql/cpp-all:
|
|
7
|
+
version: 7.1.0
|
|
8
|
+
codeql/dataflow:
|
|
9
|
+
version: 2.0.25
|
|
10
|
+
codeql/mad:
|
|
11
|
+
version: 1.0.41
|
|
12
|
+
codeql/quantum:
|
|
13
|
+
version: 0.0.19
|
|
14
|
+
codeql/rangeanalysis:
|
|
15
|
+
version: 1.0.41
|
|
16
|
+
codeql/ssa:
|
|
17
|
+
version: 2.0.17
|
|
18
|
+
codeql/tutorial:
|
|
19
|
+
version: 1.0.41
|
|
20
|
+
codeql/typeflow:
|
|
21
|
+
version: 1.0.41
|
|
22
|
+
codeql/typetracking:
|
|
23
|
+
version: 2.0.25
|
|
24
|
+
codeql/util:
|
|
25
|
+
version: 2.0.28
|
|
26
|
+
codeql/xml:
|
|
27
|
+
version: 1.0.41
|
|
28
|
+
compiled: false
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @name Call Graph From for csharp
|
|
3
|
+
* @description Displays calls made from a specified method, showing the call graph outbound from the source method.
|
|
4
|
+
* @id csharp/tools/call-graph-from
|
|
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 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.getEnclosingCallable() = source and
|
|
38
|
+
call.getTarget() = 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() + "`"
|