diff --git a/actions/ql/lib/change-notes/2025-07-11-artifact-poisoning.md b/actions/ql/lib/change-notes/2025-07-11-artifact-poisoning.md
new file mode 100644
index 00000000000..893a695a22c
--- /dev/null
+++ b/actions/ql/lib/change-notes/2025-07-11-artifact-poisoning.md
@@ -0,0 +1,4 @@
+---
+category: fix
+---
+* The `actions/artifact-poisoning/critical` and `actions/artifact-poisoning/medium` queries now exclude artifacts downloaded to `$[{ runner.temp }}` in addition to `/tmp`.
diff --git a/actions/ql/lib/codeql/actions/Helper.qll b/actions/ql/lib/codeql/actions/Helper.qll
index 48b70061ec0..348ec75a519 100644
--- a/actions/ql/lib/codeql/actions/Helper.qll
+++ b/actions/ql/lib/codeql/actions/Helper.qll
@@ -72,7 +72,7 @@ string normalizePath(string path) {
then result = path
else
// foo -> GITHUB_WORKSPACE/foo
- if path.regexpMatch("^[^/~].*")
+ if path.regexpMatch("^[^$/~].*")
then result = "GITHUB_WORKSPACE/" + path.regexpReplaceAll("/$", "")
else
// ~/foo -> ~/foo
diff --git a/actions/ql/lib/codeql/actions/security/ArtifactPoisoningQuery.qll b/actions/ql/lib/codeql/actions/security/ArtifactPoisoningQuery.qll
index d8d5f83c867..f0649bb8174 100644
--- a/actions/ql/lib/codeql/actions/security/ArtifactPoisoningQuery.qll
+++ b/actions/ql/lib/codeql/actions/security/ArtifactPoisoningQuery.qll
@@ -262,8 +262,10 @@ class ArtifactPoisoningSink extends DataFlow::Node {
ArtifactPoisoningSink() {
download.getAFollowingStep() = poisonable and
- // excluding artifacts downloaded to /tmp
+ // excluding artifacts downloaded to the temporary directory
not download.getPath().regexpMatch("^/tmp.*") and
+ not download.getPath().regexpMatch("^\\$\\{\\{\\s*runner\\.temp\\s*}}.*") and
+ not download.getPath().regexpMatch("^\\$RUNNER_TEMP.*") and
(
poisonable.(Run).getScript() = this.asExpr() and
(
diff --git a/actions/ql/test/query-tests/Security/CWE-829/.github/workflows/artifactpoisoning93.yml b/actions/ql/test/query-tests/Security/CWE-829/.github/workflows/artifactpoisoning93.yml
new file mode 100644
index 00000000000..5bebc3484e6
--- /dev/null
+++ b/actions/ql/test/query-tests/Security/CWE-829/.github/workflows/artifactpoisoning93.yml
@@ -0,0 +1,19 @@
+on:
+ workflow_run:
+ workflows:
+ - Benchmark
+ types:
+ - completed
+
+jobs:
+ benchmark:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Download From PR
+ uses: actions/download-artifact@v4
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ run-id: ${{ github.event.workflow_run.id }}
+ path: ${{ runner.temp }}/artifacts/
+ - run: npm install
\ No newline at end of file
diff --git a/actions/ql/test/query-tests/Security/CWE-829/.github/workflows/artifactpoisoning94.yml b/actions/ql/test/query-tests/Security/CWE-829/.github/workflows/artifactpoisoning94.yml
new file mode 100644
index 00000000000..bee8abd4120
--- /dev/null
+++ b/actions/ql/test/query-tests/Security/CWE-829/.github/workflows/artifactpoisoning94.yml
@@ -0,0 +1,19 @@
+on:
+ workflow_run:
+ workflows:
+ - Benchmark
+ types:
+ - completed
+
+jobs:
+ benchmark:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Download From PR
+ uses: actions/download-artifact@v4
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ run-id: ${{ github.event.workflow_run.id }}
+ path: /tmp/artifacts/
+ - run: npm install
\ No newline at end of file
diff --git a/actions/ql/test/query-tests/Security/CWE-829/.github/workflows/artifactpoisoning95.yml b/actions/ql/test/query-tests/Security/CWE-829/.github/workflows/artifactpoisoning95.yml
new file mode 100644
index 00000000000..7a1aca46760
--- /dev/null
+++ b/actions/ql/test/query-tests/Security/CWE-829/.github/workflows/artifactpoisoning95.yml
@@ -0,0 +1,19 @@
+on:
+ workflow_run:
+ workflows:
+ - Benchmark
+ types:
+ - completed
+
+jobs:
+ benchmark:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Download From PR
+ uses: actions/download-artifact@v4
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ run-id: ${{ github.event.workflow_run.id }}
+ path: $RUNNER_TEMP/artifacts/
+ - run: npm install
\ No newline at end of file
diff --git a/actions/ql/test/query-tests/Security/CWE-829/.github/workflows/artifactpoisoning96.yml b/actions/ql/test/query-tests/Security/CWE-829/.github/workflows/artifactpoisoning96.yml
new file mode 100644
index 00000000000..f970a3fa197
--- /dev/null
+++ b/actions/ql/test/query-tests/Security/CWE-829/.github/workflows/artifactpoisoning96.yml
@@ -0,0 +1,18 @@
+on:
+ workflow_run:
+ workflows:
+ - Benchmark
+ types:
+ - completed
+
+jobs:
+ benchmark:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Download From PR
+ uses: actions/download-artifact@v4
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ run-id: ${{ github.event.workflow_run.id }}
+ - run: npm install
\ No newline at end of file
diff --git a/actions/ql/test/query-tests/Security/CWE-829/.github/workflows/artifactpoisoning97.yml b/actions/ql/test/query-tests/Security/CWE-829/.github/workflows/artifactpoisoning97.yml
new file mode 100644
index 00000000000..1bd28bafdd6
--- /dev/null
+++ b/actions/ql/test/query-tests/Security/CWE-829/.github/workflows/artifactpoisoning97.yml
@@ -0,0 +1,19 @@
+on:
+ workflow_run:
+ workflows:
+ - Benchmark
+ types:
+ - completed
+
+jobs:
+ benchmark:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Download From PR
+ uses: actions/download-artifact@v4
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ run-id: ${{ github.event.workflow_run.id }}
+ path: ${{ runner.temp }}/artifacts/
+ - run: npm install
diff --git a/actions/ql/test/query-tests/Security/CWE-829/ArtifactPoisoningCritical.expected b/actions/ql/test/query-tests/Security/CWE-829/ArtifactPoisoningCritical.expected
index aa0057d60a1..2d29cd9b79b 100644
--- a/actions/ql/test/query-tests/Security/CWE-829/ArtifactPoisoningCritical.expected
+++ b/actions/ql/test/query-tests/Security/CWE-829/ArtifactPoisoningCritical.expected
@@ -13,6 +13,7 @@ edges
| .github/workflows/artifactpoisoning42.yml:13:9:21:6 | Run Step | .github/workflows/artifactpoisoning42.yml:22:14:22:18 | ./cmd | provenance | Config |
| .github/workflows/artifactpoisoning71.yml:9:9:16:6 | Uses Step | .github/workflows/artifactpoisoning71.yml:17:14:18:40 | sed -f config foo.md > bar.md\n | provenance | Config |
| .github/workflows/artifactpoisoning81.yml:28:9:31:6 | Uses Step | .github/workflows/artifactpoisoning81.yml:31:14:31:27 | python test.py | provenance | Config |
+| .github/workflows/artifactpoisoning96.yml:13:9:18:6 | Uses Step | .github/workflows/artifactpoisoning96.yml:18:14:18:24 | npm install | provenance | Config |
| .github/workflows/artifactpoisoning101.yml:10:9:16:6 | Uses Step | .github/workflows/artifactpoisoning101.yml:17:14:19:59 | PR_NUMBER=$(./get_pull_request_number.sh pr_number.txt)\necho "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT \n | provenance | Config |
| .github/workflows/test18.yml:12:15:33:12 | Uses Step | .github/workflows/test18.yml:36:15:40:58 | Uses Step | provenance | Config |
| .github/workflows/test25.yml:22:9:32:6 | Uses Step: downloadBuildScan | .github/workflows/test25.yml:39:14:40:45 | ./gradlew buildScanPublishPrevious\n | provenance | Config |
@@ -44,6 +45,8 @@ nodes
| .github/workflows/artifactpoisoning81.yml:31:14:31:27 | python test.py | semmle.label | python test.py |
| .github/workflows/artifactpoisoning92.yml:28:9:29:6 | Uses Step | semmle.label | Uses Step |
| .github/workflows/artifactpoisoning92.yml:29:14:29:26 | make snapshot | semmle.label | make snapshot |
+| .github/workflows/artifactpoisoning96.yml:13:9:18:6 | Uses Step | semmle.label | Uses Step |
+| .github/workflows/artifactpoisoning96.yml:18:14:18:24 | npm install | semmle.label | npm install |
| .github/workflows/artifactpoisoning101.yml:10:9:16:6 | Uses Step | semmle.label | Uses Step |
| .github/workflows/artifactpoisoning101.yml:17:14:19:59 | PR_NUMBER=$(./get_pull_request_number.sh pr_number.txt)\necho "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT \n | semmle.label | PR_NUMBER=$(./get_pull_request_number.sh pr_number.txt)\necho "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT \n |
| .github/workflows/test18.yml:12:15:33:12 | Uses Step | semmle.label | Uses Step |
@@ -66,6 +69,7 @@ subpaths
| .github/workflows/artifactpoisoning81.yml:31:14:31:27 | python test.py | .github/workflows/artifactpoisoning81.yml:28:9:31:6 | Uses Step | .github/workflows/artifactpoisoning81.yml:31:14:31:27 | python test.py | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning81.yml:31:14:31:27 | python test.py | python test.py | .github/workflows/artifactpoisoning81.yml:3:5:3:23 | pull_request_target | pull_request_target |
| .github/workflows/artifactpoisoning92.yml:28:9:29:6 | Uses Step | .github/actions/download-artifact-2/action.yaml:6:7:25:4 | Uses Step | .github/workflows/artifactpoisoning92.yml:28:9:29:6 | Uses Step | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning92.yml:28:9:29:6 | Uses Step | Uses Step | .github/workflows/artifactpoisoning92.yml:3:3:3:14 | workflow_run | workflow_run |
| .github/workflows/artifactpoisoning92.yml:29:14:29:26 | make snapshot | .github/actions/download-artifact-2/action.yaml:6:7:25:4 | Uses Step | .github/workflows/artifactpoisoning92.yml:29:14:29:26 | make snapshot | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning92.yml:29:14:29:26 | make snapshot | make snapshot | .github/workflows/artifactpoisoning92.yml:3:3:3:14 | workflow_run | workflow_run |
+| .github/workflows/artifactpoisoning96.yml:18:14:18:24 | npm install | .github/workflows/artifactpoisoning96.yml:13:9:18:6 | Uses Step | .github/workflows/artifactpoisoning96.yml:18:14:18:24 | npm install | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning96.yml:18:14:18:24 | npm install | npm install | .github/workflows/artifactpoisoning96.yml:2:3:2:14 | workflow_run | workflow_run |
| .github/workflows/artifactpoisoning101.yml:17:14:19:59 | PR_NUMBER=$(./get_pull_request_number.sh pr_number.txt)\necho "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT \n | .github/workflows/artifactpoisoning101.yml:10:9:16:6 | Uses Step | .github/workflows/artifactpoisoning101.yml:17:14:19:59 | PR_NUMBER=$(./get_pull_request_number.sh pr_number.txt)\necho "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT \n | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning101.yml:17:14:19:59 | PR_NUMBER=$(./get_pull_request_number.sh pr_number.txt)\necho "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT \n | PR_NUMBER=$(./get_pull_request_number.sh pr_number.txt)\necho "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT \n | .github/workflows/artifactpoisoning101.yml:4:3:4:21 | pull_request_target | pull_request_target |
| .github/workflows/test18.yml:36:15:40:58 | Uses Step | .github/workflows/test18.yml:12:15:33:12 | Uses Step | .github/workflows/test18.yml:36:15:40:58 | Uses Step | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/test18.yml:36:15:40:58 | Uses Step | Uses Step | .github/workflows/test18.yml:3:5:3:16 | workflow_run | workflow_run |
| .github/workflows/test25.yml:39:14:40:45 | ./gradlew buildScanPublishPrevious\n | .github/workflows/test25.yml:22:9:32:6 | Uses Step: downloadBuildScan | .github/workflows/test25.yml:39:14:40:45 | ./gradlew buildScanPublishPrevious\n | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/test25.yml:39:14:40:45 | ./gradlew buildScanPublishPrevious\n | ./gradlew buildScanPublishPrevious\n | .github/workflows/test25.yml:2:3:2:14 | workflow_run | workflow_run |
diff --git a/actions/ql/test/query-tests/Security/CWE-829/ArtifactPoisoningMedium.expected b/actions/ql/test/query-tests/Security/CWE-829/ArtifactPoisoningMedium.expected
index 09aed9e34a1..c0c52e47f5b 100644
--- a/actions/ql/test/query-tests/Security/CWE-829/ArtifactPoisoningMedium.expected
+++ b/actions/ql/test/query-tests/Security/CWE-829/ArtifactPoisoningMedium.expected
@@ -13,6 +13,7 @@ edges
| .github/workflows/artifactpoisoning42.yml:13:9:21:6 | Run Step | .github/workflows/artifactpoisoning42.yml:22:14:22:18 | ./cmd | provenance | Config |
| .github/workflows/artifactpoisoning71.yml:9:9:16:6 | Uses Step | .github/workflows/artifactpoisoning71.yml:17:14:18:40 | sed -f config foo.md > bar.md\n | provenance | Config |
| .github/workflows/artifactpoisoning81.yml:28:9:31:6 | Uses Step | .github/workflows/artifactpoisoning81.yml:31:14:31:27 | python test.py | provenance | Config |
+| .github/workflows/artifactpoisoning96.yml:13:9:18:6 | Uses Step | .github/workflows/artifactpoisoning96.yml:18:14:18:24 | npm install | provenance | Config |
| .github/workflows/artifactpoisoning101.yml:10:9:16:6 | Uses Step | .github/workflows/artifactpoisoning101.yml:17:14:19:59 | PR_NUMBER=$(./get_pull_request_number.sh pr_number.txt)\necho "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT \n | provenance | Config |
| .github/workflows/test18.yml:12:15:33:12 | Uses Step | .github/workflows/test18.yml:36:15:40:58 | Uses Step | provenance | Config |
| .github/workflows/test25.yml:22:9:32:6 | Uses Step: downloadBuildScan | .github/workflows/test25.yml:39:14:40:45 | ./gradlew buildScanPublishPrevious\n | provenance | Config |
@@ -44,6 +45,8 @@ nodes
| .github/workflows/artifactpoisoning81.yml:31:14:31:27 | python test.py | semmle.label | python test.py |
| .github/workflows/artifactpoisoning92.yml:28:9:29:6 | Uses Step | semmle.label | Uses Step |
| .github/workflows/artifactpoisoning92.yml:29:14:29:26 | make snapshot | semmle.label | make snapshot |
+| .github/workflows/artifactpoisoning96.yml:13:9:18:6 | Uses Step | semmle.label | Uses Step |
+| .github/workflows/artifactpoisoning96.yml:18:14:18:24 | npm install | semmle.label | npm install |
| .github/workflows/artifactpoisoning101.yml:10:9:16:6 | Uses Step | semmle.label | Uses Step |
| .github/workflows/artifactpoisoning101.yml:17:14:19:59 | PR_NUMBER=$(./get_pull_request_number.sh pr_number.txt)\necho "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT \n | semmle.label | PR_NUMBER=$(./get_pull_request_number.sh pr_number.txt)\necho "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT \n |
| .github/workflows/test18.yml:12:15:33:12 | Uses Step | semmle.label | Uses Step |
diff --git a/actions/ql/test/query-tests/Security/CWE-829/UntrustedCheckoutCritical.expected b/actions/ql/test/query-tests/Security/CWE-829/UntrustedCheckoutCritical.expected
index 5d7a94aead0..39e54b2bbae 100644
--- a/actions/ql/test/query-tests/Security/CWE-829/UntrustedCheckoutCritical.expected
+++ b/actions/ql/test/query-tests/Security/CWE-829/UntrustedCheckoutCritical.expected
@@ -51,6 +51,16 @@ edges
| .github/workflows/artifactpoisoning92.yml:19:9:25:6 | Run Step: metadata | .github/workflows/artifactpoisoning92.yml:25:9:28:6 | Uses Step |
| .github/workflows/artifactpoisoning92.yml:25:9:28:6 | Uses Step | .github/workflows/artifactpoisoning92.yml:28:9:29:6 | Uses Step |
| .github/workflows/artifactpoisoning92.yml:28:9:29:6 | Uses Step | .github/workflows/artifactpoisoning92.yml:29:9:29:27 | Run Step |
+| .github/workflows/artifactpoisoning93.yml:12:9:13:6 | Uses Step | .github/workflows/artifactpoisoning93.yml:13:9:19:6 | Uses Step |
+| .github/workflows/artifactpoisoning93.yml:13:9:19:6 | Uses Step | .github/workflows/artifactpoisoning93.yml:19:9:19:24 | Run Step |
+| .github/workflows/artifactpoisoning94.yml:12:9:13:6 | Uses Step | .github/workflows/artifactpoisoning94.yml:13:9:19:6 | Uses Step |
+| .github/workflows/artifactpoisoning94.yml:13:9:19:6 | Uses Step | .github/workflows/artifactpoisoning94.yml:19:9:19:24 | Run Step |
+| .github/workflows/artifactpoisoning95.yml:12:9:13:6 | Uses Step | .github/workflows/artifactpoisoning95.yml:13:9:19:6 | Uses Step |
+| .github/workflows/artifactpoisoning95.yml:13:9:19:6 | Uses Step | .github/workflows/artifactpoisoning95.yml:19:9:19:24 | Run Step |
+| .github/workflows/artifactpoisoning96.yml:12:9:13:6 | Uses Step | .github/workflows/artifactpoisoning96.yml:13:9:18:6 | Uses Step |
+| .github/workflows/artifactpoisoning96.yml:13:9:18:6 | Uses Step | .github/workflows/artifactpoisoning96.yml:18:9:18:24 | Run Step |
+| .github/workflows/artifactpoisoning97.yml:12:9:13:6 | Uses Step | .github/workflows/artifactpoisoning97.yml:13:9:19:6 | Uses Step |
+| .github/workflows/artifactpoisoning97.yml:13:9:19:6 | Uses Step | .github/workflows/artifactpoisoning97.yml:19:9:19:25 | Run Step |
| .github/workflows/artifactpoisoning101.yml:10:9:16:6 | Uses Step | .github/workflows/artifactpoisoning101.yml:16:9:19:59 | Run Step: pr_number |
| .github/workflows/auto_ci.yml:20:9:27:6 | Uses Step | .github/workflows/auto_ci.yml:27:9:32:6 | Uses Step |
| .github/workflows/auto_ci.yml:27:9:32:6 | Uses Step | .github/workflows/auto_ci.yml:32:9:37:6 | Run Step |
diff --git a/config/identical-files.json b/config/identical-files.json
index 56aac560473..89beb48acd4 100644
--- a/config/identical-files.json
+++ b/config/identical-files.json
@@ -231,35 +231,10 @@
"java/ql/src/experimental/Security/CWE/CWE-400/LocalThreadResourceAbuse.qhelp",
"java/ql/src/experimental/Security/CWE/CWE-400/ThreadResourceAbuse.qhelp"
],
- "CryptoAlgorithms Python/JS/Ruby": [
- "javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll",
- "python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll",
- "ruby/ql/lib/codeql/ruby/security/CryptoAlgorithms.qll",
- "rust/ql/lib/codeql/rust/security/CryptoAlgorithms.qll"
- ],
- "CryptoAlgorithmNames Python/JS/Ruby": [
- "javascript/ql/lib/semmle/javascript/security/internal/CryptoAlgorithmNames.qll",
- "python/ql/lib/semmle/python/concepts/internal/CryptoAlgorithmNames.qll",
- "ruby/ql/lib/codeql/ruby/security/internal/CryptoAlgorithmNames.qll",
- "rust/ql/lib/codeql/rust/security/internal/CryptoAlgorithmNames.qll"
- ],
- "SensitiveDataHeuristics Python/JS": [
- "javascript/ql/lib/semmle/javascript/security/internal/SensitiveDataHeuristics.qll",
- "python/ql/lib/semmle/python/security/internal/SensitiveDataHeuristics.qll",
- "ruby/ql/lib/codeql/ruby/security/internal/SensitiveDataHeuristics.qll",
- "swift/ql/lib/codeql/swift/security/internal/SensitiveDataHeuristics.qll",
- "rust/ql/lib/codeql/rust/security/internal/SensitiveDataHeuristics.qll"
- ],
"IncompleteUrlSubstringSanitization": [
"javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qll",
"ruby/ql/src/queries/security/cwe-020/IncompleteUrlSubstringSanitization.qll"
],
- "Concepts Python/Ruby/JS": [
- "python/ql/lib/semmle/python/internal/ConceptsShared.qll",
- "ruby/ql/lib/codeql/ruby/internal/ConceptsShared.qll",
- "javascript/ql/lib/semmle/javascript/internal/ConceptsShared.qll",
- "rust/ql/lib/codeql/rust/internal/ConceptsShared.qll"
- ],
"ApiGraphModels": [
"javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll",
"ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll",
diff --git a/cpp/ql/lib/change-notes/2025-07-10-final.md b/cpp/ql/lib/change-notes/2025-07-10-final.md
new file mode 100644
index 00000000000..8e6b3dba266
--- /dev/null
+++ b/cpp/ql/lib/change-notes/2025-07-10-final.md
@@ -0,0 +1,4 @@
+---
+category: feature
+---
+* Added a `isFinalValueOfParameter` predicate to DataFlow::Node which holds when a dataflow node represents the final value of an output parameter of a function.
diff --git a/cpp/ql/lib/change-notes/2025-07-16-FunctionWithWrappers.md b/cpp/ql/lib/change-notes/2025-07-16-FunctionWithWrappers.md
new file mode 100644
index 00000000000..80b70a8c80f
--- /dev/null
+++ b/cpp/ql/lib/change-notes/2025-07-16-FunctionWithWrappers.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* The `FunctionWithWrappers` library (`semmle.code.cpp.security.FunctionWithWrappers`) no longer considers calls through function pointers as wrapper functions.
\ No newline at end of file
diff --git a/cpp/ql/lib/ext/pthread.model.yml b/cpp/ql/lib/ext/pthread.model.yml
new file mode 100644
index 00000000000..fcdb0c45d00
--- /dev/null
+++ b/cpp/ql/lib/ext/pthread.model.yml
@@ -0,0 +1,6 @@
+extensions:
+ - addsTo:
+ pack: codeql/cpp-all
+ extensible: summaryModel
+ data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
+ - ["", "", False, "pthread_create", "", "", "Argument[@3]", "Argument[2].Parameter[@0]", "value", "manual"]
diff --git a/cpp/ql/lib/ext/std.thread.model.yml b/cpp/ql/lib/ext/std.thread.model.yml
new file mode 100644
index 00000000000..77062fae3d0
--- /dev/null
+++ b/cpp/ql/lib/ext/std.thread.model.yml
@@ -0,0 +1,11 @@
+extensions:
+ - addsTo:
+ pack: codeql/cpp-all
+ extensible: summaryModel
+ data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
+ - ["std", "thread", True, "thread", "", "", "Argument[*@1]", "Argument[0].Parameter[@0]", "value", "manual"]
+ - ["std", "thread", True, "thread", "", "", "Argument[*@2]", "Argument[0].Parameter[@1]", "value", "manual"]
+ - ["std", "thread", True, "thread", "", "", "Argument[*@3]", "Argument[0].Parameter[@2]", "value", "manual"]
+ - ["std", "thread", True, "thread", "", "", "Argument[*@4]", "Argument[0].Parameter[@3]", "value", "manual"]
+ - ["std", "thread", True, "thread", "", "", "Argument[*@5]", "Argument[0].Parameter[@4]", "value", "manual"]
+
\ No newline at end of file
diff --git a/cpp/ql/lib/semmle/code/cpp/Concept.qll b/cpp/ql/lib/semmle/code/cpp/Concept.qll
index 5d7cd96ee38..1770c1965ed 100644
--- a/cpp/ql/lib/semmle/code/cpp/Concept.qll
+++ b/cpp/ql/lib/semmle/code/cpp/Concept.qll
@@ -57,7 +57,9 @@ class RequiresExpr extends Expr, @requires_expr {
/**
* A C++ requirement in a requires expression.
*/
-class RequirementExpr extends Expr { }
+class RequirementExpr extends Expr {
+ RequirementExpr() { this.getParent() instanceof RequiresExpr }
+}
/**
* A C++ simple requirement in a requires expression.
@@ -70,7 +72,6 @@ class RequirementExpr extends Expr { }
*/
class SimpleRequirementExpr extends RequirementExpr {
SimpleRequirementExpr() {
- this.getParent() instanceof RequiresExpr and
not this instanceof TypeRequirementExpr and
not this instanceof CompoundRequirementExpr and
not this instanceof NestedRequirementExpr
@@ -89,8 +90,6 @@ class SimpleRequirementExpr extends RequirementExpr {
* with `T` a template parameter, then `typename T::a_field;` is a type requirement.
*/
class TypeRequirementExpr extends RequirementExpr, TypeName {
- TypeRequirementExpr() { this.getParent() instanceof RequiresExpr }
-
override string getAPrimaryQlClass() { result = "TypeRequirementExpr" }
}
@@ -140,7 +139,7 @@ class CompoundRequirementExpr extends RequirementExpr, @compound_requirement {
* with `T` a template parameter, then `requires std::is_same::value;` is
* a nested requirement.
*/
-class NestedRequirementExpr extends Expr, @nested_requirement {
+class NestedRequirementExpr extends RequirementExpr, @nested_requirement {
override string toString() { result = "requires ..." }
override string getAPrimaryQlClass() { result = "NestedRequirementExpr" }
@@ -163,7 +162,7 @@ class NestedRequirementExpr extends Expr, @nested_requirement {
* then `C` is a concept id expression that refers to
* the concept `C`.
*/
-class ConceptIdExpr extends RequirementExpr, @concept_id {
+class ConceptIdExpr extends Expr, @concept_id {
override string toString() {
result = this.getConcept().getName() + "<...>"
or
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll
index d776985720a..d7f26dd0051 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll
@@ -1382,16 +1382,89 @@ predicate neverSkipInPathGraph(Node n) {
exists(n.asIndirectDefinition())
}
-class LambdaCallKind = Unit;
+private newtype TLambdaCallKind =
+ TFunctionPointer() or
+ TFunctor()
+
+class LambdaCallKind extends TLambdaCallKind {
+ predicate isFunctionPointer() { this = TFunctionPointer() }
+
+ predicate isFunctor() { this = TFunctor() }
+
+ string toString() {
+ this.isFunctionPointer() and
+ result = "Function pointer kind"
+ or
+ this.isFunctor() and
+ result = "Functor kind"
+ }
+}
+
+private class ConstructorCallInstruction extends CallInstruction {
+ Cpp::Class constructedType;
+
+ ConstructorCallInstruction() {
+ this.getStaticCallTarget().(Cpp::Constructor).getDeclaringType() = constructedType
+ }
+
+ Cpp::Class getConstructedType() { result = constructedType }
+}
+
+private class OperatorCall extends Cpp::MemberFunction {
+ OperatorCall() { this.hasName("operator()") }
+}
+
+private predicate isFunctorCreationWithoutConstructor(Node creation, OperatorCall operator) {
+ exists(UninitializedInstruction init, Instruction dest |
+ // A construction of an object with no constructor. In this case we use
+ // the `UninitializedInstruction` as the creation node.
+ init = creation.asInstruction() and
+ dest = init.getDestinationAddress() and
+ not any(ConstructorCallInstruction constructorCall).getThisArgument() = dest and
+ operator.getDeclaringType() = init.getResultType()
+ )
+ or
+ // Workaround for an extractor bug. In this snippet:
+ // ```
+ // struct S { };
+ // void f(S);
+ // f(S());
+ // ```
+ // The expression `S()` is represented as a 0 literal in the database.
+ exists(ConstantValueInstruction constant |
+ constant.getValue() = "0" and
+ creation.asInstruction() = constant and
+ constant.getResultType() = operator.getDeclaringType()
+ )
+}
+
+private predicate isFunctorCreationWithConstructor(Node creation, OperatorCall operator) {
+ exists(DataFlowCall constructorCall, IndirectionPosition pos |
+ // A construction of an object with a constructor. In this case we use
+ // the post-update node of the qualifier
+ pos.getArgumentIndex() = -1 and
+ isArgumentNode(creation.(PostUpdateNode).getPreUpdateNode(), constructorCall, pos) and
+ operator.getDeclaringType() =
+ constructorCall.asCallInstruction().(ConstructorCallInstruction).getConstructedType()
+ )
+}
/** Holds if `creation` is an expression that creates a lambda of kind `kind` for `c`. */
predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) {
- creation.asInstruction().(FunctionAddressInstruction).getFunctionSymbol() = c.asSourceCallable() and
- exists(kind)
+ kind.isFunctionPointer() and
+ creation.asInstruction().(FunctionAddressInstruction).getFunctionSymbol() = c.asSourceCallable()
+ or
+ kind.isFunctor() and
+ exists(OperatorCall operator | operator = c.asSourceCallable() |
+ isFunctorCreationWithoutConstructor(creation, operator)
+ or
+ isFunctorCreationWithConstructor(creation, operator)
+ )
}
/** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
+ kind.isFunctionPointer() and
(
call.(SummaryCall).getReceiver() = receiver.(FlowSummaryNode).getSummaryNode()
or
@@ -1400,8 +1473,15 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
// has a result for `getStaticCallTarget`.
not exists(call.getStaticCallTarget()) and
call.asCallInstruction().getCallTargetOperand() = receiver.asOperand()
- ) and
- exists(kind)
+ )
+ or
+ kind.isFunctor() and
+ (
+ call.(SummaryCall).getReceiver() = receiver.(FlowSummaryNode).getSummaryNode()
+ or
+ not exists(call.getStaticCallTarget()) and
+ call.asCallInstruction().getThisArgumentOperand() = receiver.asOperand()
+ )
}
/** Extra data-flow steps needed for lambda flow analysis. */
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll
index c72614ac5c3..38a4d827a4d 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll
@@ -488,6 +488,23 @@ class Node extends TIRDataFlowNode {
result = this.(IndirectParameterNode).getParameter()
}
+ /**
+ * Holds if this node represents the `indirectionIndex`'th indirection of
+ * the value of an output parameter `p` just before reaching the end of a function.
+ */
+ predicate isFinalValueOfParameter(Parameter p, int indirectionIndex) {
+ exists(FinalParameterNode n | n = this |
+ p = n.getParameter() and
+ indirectionIndex = n.getIndirectionIndex()
+ )
+ }
+
+ /**
+ * Holds if this node represents the value of an output parameter `p`
+ * just before reaching the end of a function.
+ */
+ predicate isFinalValueOfParameter(Parameter p) { this.isFinalValueOfParameter(p, _) }
+
/**
* Gets the variable corresponding to this node, if any. This can be used for
* modeling flow in and out of global variables.
@@ -1225,7 +1242,7 @@ import RawIndirectNodes
/**
* INTERNAL: do not use.
*
- * A node representing the value of an update parameter
+ * A node representing the value of an output parameter
* just before reaching the end of a function.
*/
class FinalParameterNode extends Node, TFinalParameterNode {
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll
index 863825b375e..fd9ba967a13 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll
@@ -153,6 +153,10 @@ private predicate isGlobalDefImpl(
GlobalLikeVariable v, IRFunction f, int indirection, int indirectionIndex
) {
exists(VariableAddressInstruction vai |
+ // The right-hand side of an initialization of a global variable
+ // creates its own `IRFunction`. We don't want flow into that `IRFunction`
+ // since the variable is only initialized once.
+ not vai.getEnclosingFunction() = v and
vai.getEnclosingIRFunction() = f and
vai.getAstVariable() = v and
isUse(_, _, vai, indirection, indirectionIndex) and
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/Opcode.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/Opcode.qll
index bd1ffcd5ce1..d8c1c6115c8 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/Opcode.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/Opcode.qll
@@ -42,6 +42,7 @@ private newtype TOpcode =
TCompareGT() or
TCompareLE() or
TCompareGE() or
+ TSpaceship() or
TPointerAdd() or
TPointerSub() or
TPointerDiff() or
@@ -92,7 +93,9 @@ private newtype TOpcode =
TUninitializedGroup() or
TInlineAsm() or
TUnreached() or
- TNewObj()
+ TNewObj() or
+ TTypeidExpr() or
+ TTypeidType()
/**
* An opcode that specifies the operation performed by an `Instruction`.
@@ -763,6 +766,15 @@ module Opcode {
final override string toString() { result = "CompareGE" }
}
+ /**
+ * The `Opcode` for a `SpaceshipInstruction`.
+ *
+ * See the `SpaceshipInstruction` documentation for more details.
+ */
+ class Spaceship extends BinaryOpcode, TSpaceship {
+ final override string toString() { result = "Spaceship" }
+ }
+
/**
* The `Opcode` for a `PointerAddInstruction`.
*
@@ -1281,4 +1293,29 @@ module Opcode {
class NewObj extends Opcode, TNewObj {
final override string toString() { result = "NewObj" }
}
+
+ /**
+ * The `Opcode` for a `TypeidInstruction`.
+ *
+ * See the `TypeidInstruction` documentation for more details.
+ */
+ abstract class Typeid extends Opcode { }
+
+ /**
+ * The `Opcode` for a `TypeidExprInstruction`.
+ *
+ * See the `TypeidExprInstruction` documentation for more details.
+ */
+ class TypeidExpr extends Typeid, UnaryOpcode, TTypeidExpr {
+ final override string toString() { result = "TypeidExpr" }
+ }
+
+ /**
+ * The `Opcode` for a `TypeidTypeInstruction`.
+ *
+ * See the `TypeidTypeInstruction` documentation for more details.
+ */
+ class TypeidType extends Typeid, TTypeidType {
+ final override string toString() { result = "TypeidType" }
+ }
}
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll
index af5dd419985..a564508e16b 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll
@@ -725,6 +725,20 @@ class UninitializedInstruction extends VariableInstruction {
* Gets the variable that is uninitialized.
*/
final Language::Variable getLocalVariable() { result = var.(IRUserVariable).getVariable() }
+
+ /**
+ * Gets the operand that provides the address of the location to which the
+ * uninitialized value will be stored.
+ */
+ final AddressOperand getDestinationAddressOperand() { result = this.getAnOperand() }
+
+ /**
+ * Gets the instruction whose result provides the address of the location to
+ * which the value will be stored, if an exact definition is available.
+ */
+ final Instruction getDestinationAddress() {
+ result = this.getDestinationAddressOperand().getDef()
+ }
}
/**
@@ -1590,6 +1604,13 @@ class CompareGEInstruction extends RelationalInstruction {
override predicate isStrict() { none() }
}
+/**
+ * An instruction that represents a three-way comparison operator.
+ */
+class SpaceshipInstruction extends BinaryInstruction {
+ SpaceshipInstruction() { this.getOpcode() instanceof Opcode::Spaceship }
+}
+
/**
* An instruction that branches to one of multiple successor instructions based on the value of an
* integer operand.
@@ -2279,3 +2300,26 @@ class NextVarArgInstruction extends UnaryInstruction {
class NewObjInstruction extends Instruction {
NewObjInstruction() { this.getOpcode() instanceof Opcode::NewObj }
}
+
+/**
+ * An instruction that returns the type info for its operand.
+ */
+class TypeidInstruction extends Instruction {
+ TypeidInstruction() { this.getOpcode() instanceof Opcode::Typeid }
+}
+
+/**
+ * An instruction that returns the type info for its operand, where the
+ * operand occurs as an expression in the AST.
+ */
+class TypeidExprInstruction extends TypeidInstruction, UnaryInstruction {
+ TypeidExprInstruction() { this.getOpcode() instanceof Opcode::TypeidExpr }
+}
+
+/**
+ * An instruction that returns the type info for its operand, where the
+ * operand occurs as a type in the AST.
+ */
+class TypeidTypeInstruction extends TypeidInstruction {
+ TypeidTypeInstruction() { this.getOpcode() instanceof Opcode::TypeidType }
+}
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll
index af5dd419985..a564508e16b 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll
@@ -725,6 +725,20 @@ class UninitializedInstruction extends VariableInstruction {
* Gets the variable that is uninitialized.
*/
final Language::Variable getLocalVariable() { result = var.(IRUserVariable).getVariable() }
+
+ /**
+ * Gets the operand that provides the address of the location to which the
+ * uninitialized value will be stored.
+ */
+ final AddressOperand getDestinationAddressOperand() { result = this.getAnOperand() }
+
+ /**
+ * Gets the instruction whose result provides the address of the location to
+ * which the value will be stored, if an exact definition is available.
+ */
+ final Instruction getDestinationAddress() {
+ result = this.getDestinationAddressOperand().getDef()
+ }
}
/**
@@ -1590,6 +1604,13 @@ class CompareGEInstruction extends RelationalInstruction {
override predicate isStrict() { none() }
}
+/**
+ * An instruction that represents a three-way comparison operator.
+ */
+class SpaceshipInstruction extends BinaryInstruction {
+ SpaceshipInstruction() { this.getOpcode() instanceof Opcode::Spaceship }
+}
+
/**
* An instruction that branches to one of multiple successor instructions based on the value of an
* integer operand.
@@ -2279,3 +2300,26 @@ class NextVarArgInstruction extends UnaryInstruction {
class NewObjInstruction extends Instruction {
NewObjInstruction() { this.getOpcode() instanceof Opcode::NewObj }
}
+
+/**
+ * An instruction that returns the type info for its operand.
+ */
+class TypeidInstruction extends Instruction {
+ TypeidInstruction() { this.getOpcode() instanceof Opcode::Typeid }
+}
+
+/**
+ * An instruction that returns the type info for its operand, where the
+ * operand occurs as an expression in the AST.
+ */
+class TypeidExprInstruction extends TypeidInstruction, UnaryInstruction {
+ TypeidExprInstruction() { this.getOpcode() instanceof Opcode::TypeidExpr }
+}
+
+/**
+ * An instruction that returns the type info for its operand, where the
+ * operand occurs as a type in the AST.
+ */
+class TypeidTypeInstruction extends TypeidInstruction {
+ TypeidTypeInstruction() { this.getOpcode() instanceof Opcode::TypeidType }
+}
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll
index dea86499e7c..a7e85fe9b1a 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll
@@ -1808,6 +1808,11 @@ private Opcode comparisonOpcode(ComparisonOperation expr) {
expr instanceof GEExpr and result instanceof Opcode::CompareGE
}
+private Opcode spaceShipOpcode(SpaceshipExpr expr) {
+ exists(expr) and
+ result instanceof Opcode::Spaceship
+}
+
/**
* IR translation of a simple binary operation.
*/
@@ -1867,7 +1872,8 @@ class TranslatedBinaryOperation extends TranslatedSingleInstructionExpr {
override Opcode getOpcode() {
result = binaryArithmeticOpcode(expr) or
result = binaryBitwiseOpcode(expr) or
- result = comparisonOpcode(expr)
+ result = comparisonOpcode(expr) or
+ result = spaceShipOpcode(expr)
}
override Type getExprType() {
@@ -4185,3 +4191,52 @@ class TranslatedAssumeExpr extends TranslatedSingleInstructionExpr {
none()
}
}
+
+class TranslatedTypeidExpr extends TranslatedSingleInstructionExpr {
+ override TypeidOperator expr;
+
+ final override Opcode getOpcode() {
+ exists(this.getOperand()) and
+ result instanceof Opcode::TypeidExpr
+ or
+ not exists(this.getOperand()) and
+ result instanceof Opcode::TypeidType
+ }
+
+ final override Instruction getFirstInstruction(EdgeKind kind) {
+ result = this.getOperand().getFirstInstruction(kind)
+ or
+ not exists(this.getOperand()) and
+ result = this.getInstruction(OnlyInstructionTag()) and
+ kind instanceof GotoEdge
+ }
+
+ override Instruction getALastInstructionInternal() {
+ result = this.getInstruction(OnlyInstructionTag())
+ }
+
+ final override TranslatedElement getChildInternal(int id) {
+ id = 0 and result = this.getOperand()
+ }
+
+ final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
+ tag = OnlyInstructionTag() and
+ result = this.getParent().getChildSuccessor(this, kind)
+ }
+
+ final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
+ child = this.getOperand() and
+ result = this.getInstruction(OnlyInstructionTag()) and
+ kind instanceof GotoEdge
+ }
+
+ final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
+ tag = OnlyInstructionTag() and
+ result = this.getOperand().getResult() and
+ operandTag instanceof UnaryOperandTag
+ }
+
+ private TranslatedExpr getOperand() {
+ result = getTranslatedExpr(expr.getExpr().getFullyConverted())
+ }
+}
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll
index af5dd419985..a564508e16b 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll
@@ -725,6 +725,20 @@ class UninitializedInstruction extends VariableInstruction {
* Gets the variable that is uninitialized.
*/
final Language::Variable getLocalVariable() { result = var.(IRUserVariable).getVariable() }
+
+ /**
+ * Gets the operand that provides the address of the location to which the
+ * uninitialized value will be stored.
+ */
+ final AddressOperand getDestinationAddressOperand() { result = this.getAnOperand() }
+
+ /**
+ * Gets the instruction whose result provides the address of the location to
+ * which the value will be stored, if an exact definition is available.
+ */
+ final Instruction getDestinationAddress() {
+ result = this.getDestinationAddressOperand().getDef()
+ }
}
/**
@@ -1590,6 +1604,13 @@ class CompareGEInstruction extends RelationalInstruction {
override predicate isStrict() { none() }
}
+/**
+ * An instruction that represents a three-way comparison operator.
+ */
+class SpaceshipInstruction extends BinaryInstruction {
+ SpaceshipInstruction() { this.getOpcode() instanceof Opcode::Spaceship }
+}
+
/**
* An instruction that branches to one of multiple successor instructions based on the value of an
* integer operand.
@@ -2279,3 +2300,26 @@ class NextVarArgInstruction extends UnaryInstruction {
class NewObjInstruction extends Instruction {
NewObjInstruction() { this.getOpcode() instanceof Opcode::NewObj }
}
+
+/**
+ * An instruction that returns the type info for its operand.
+ */
+class TypeidInstruction extends Instruction {
+ TypeidInstruction() { this.getOpcode() instanceof Opcode::Typeid }
+}
+
+/**
+ * An instruction that returns the type info for its operand, where the
+ * operand occurs as an expression in the AST.
+ */
+class TypeidExprInstruction extends TypeidInstruction, UnaryInstruction {
+ TypeidExprInstruction() { this.getOpcode() instanceof Opcode::TypeidExpr }
+}
+
+/**
+ * An instruction that returns the type info for its operand, where the
+ * operand occurs as a type in the AST.
+ */
+class TypeidTypeInstruction extends TypeidInstruction {
+ TypeidTypeInstruction() { this.getOpcode() instanceof Opcode::TypeidType }
+}
diff --git a/cpp/ql/lib/semmle/code/cpp/security/FunctionWithWrappers.qll b/cpp/ql/lib/semmle/code/cpp/security/FunctionWithWrappers.qll
index b7a7a95a427..b6673167847 100644
--- a/cpp/ql/lib/semmle/code/cpp/security/FunctionWithWrappers.qll
+++ b/cpp/ql/lib/semmle/code/cpp/security/FunctionWithWrappers.qll
@@ -17,7 +17,6 @@
import cpp
import PrintfLike
-private import semmle.code.cpp.ir.dataflow.ResolveCall
bindingset[index]
private string toCause(Function func, int index) {
@@ -37,9 +36,9 @@ private predicate wrapperFunctionStep(
not target.isVirtual() and
not source.isVirtual() and
source.hasDefinition() and
- exists(Call call, Expr arg, Parameter sourceParam |
+ exists(FunctionCall call, Expr arg, Parameter sourceParam |
// there is a 'call' to 'target' with argument 'arg' at index 'targetParamIndex'
- target = resolveCall(call) and
+ target = call.getTarget() and
arg = call.getArgument(targetParamIndex) and
// 'call' is enclosed in 'source'
source = call.getEnclosingFunction() and
@@ -154,8 +153,8 @@ abstract class FunctionWithWrappers extends Function {
* Whether 'arg' is an argument in a call to an outermost wrapper function of 'this' function.
*/
predicate outermostWrapperFunctionCall(Expr arg, string callChain) {
- exists(Function targetFunc, Call call, int argIndex |
- targetFunc = resolveCall(call) and
+ exists(Function targetFunc, FunctionCall call, int argIndex |
+ targetFunc = call.getTarget() and
this.wrapperFunction(targetFunc, argIndex, callChain) and
(
exists(Function sourceFunc | sourceFunc = call.getEnclosingFunction() |
diff --git a/cpp/ql/src/CHANGELOG.md b/cpp/ql/src/CHANGELOG.md
index b59e9fb9130..8fd203bea4f 100644
--- a/cpp/ql/src/CHANGELOG.md
+++ b/cpp/ql/src/CHANGELOG.md
@@ -11,7 +11,7 @@
### Minor Analysis Improvements
-* Added flow model for the following libraries: `madler/zlib`, `google/brotli`, `libidn/libidn2`, `libssh2/libssh2/`, `nghttp2/nghttp2`, `libuv/libuv/`, and `curl/curl`. This may result in more alerts when running queries on codebases that use these libraries.
+* Added flow models for the following libraries: `madler/zlib`, `google/brotli`, `libidn/libidn2`, `libssh2/libssh2`, `nghttp2/nghttp2`, `libuv/libuv`, and `curl/curl`. This may result in more alerts when running queries on codebases that use these libraries.
## 1.4.2
@@ -21,7 +21,7 @@ No user-facing changes.
### Minor Analysis Improvements
-* Added flow model for the `SQLite` and `OpenSSL` libraries. This may result in more alerts when running queries on codebases that use these libraries.
+* Added flow models for the `SQLite` and `OpenSSL` libraries. This may result in more alerts when running queries on codebases that use these libraries.
## 1.4.0
diff --git a/cpp/ql/src/Metrics/Classes/CNumberOfFunctions.qhelp b/cpp/ql/src/Metrics/Classes/CNumberOfFunctions.qhelp
index cc62cb50f49..8ef045c7092 100644
--- a/cpp/ql/src/Metrics/Classes/CNumberOfFunctions.qhelp
+++ b/cpp/ql/src/Metrics/Classes/CNumberOfFunctions.qhelp
@@ -49,21 +49,16 @@ need to be part of the class. (A classic example of this is the
observes, there are at least two key problems with this approach:
-
--
-It may be possible to generalize some of the utility functions beyond the
+1. It may be possible to generalize some of the utility functions beyond the
narrow context of the class in question -- by bundling them with the class,
the class author reduces the scope for functionality reuse.
-
--
-It's usually impossible for the class author to know every possible
+2. It's usually impossible for the class author to know every possible
operation that the user might want to perform on the class, so the public
interface will inherently be incomplete. New utility functions will end up
having a different syntax to the privileged public functions in the class,
negatively impacting on code consistency.
-
-
+
To refactor a class like this, simply move its utility functions elsewhere,
paring its public interface down to the bare minimum.
diff --git a/cpp/ql/src/Metrics/Classes/CSizeOfAPI.qhelp b/cpp/ql/src/Metrics/Classes/CSizeOfAPI.qhelp
index 0d560f920aa..70c4c862fb6 100644
--- a/cpp/ql/src/Metrics/Classes/CSizeOfAPI.qhelp
+++ b/cpp/ql/src/Metrics/Classes/CSizeOfAPI.qhelp
@@ -46,21 +46,17 @@ need to be part of the class. (A classic example of this is the
std::string class in the C++ Standard Library.) As [Sutter]
observes, there are at least two key problems with this approach:
-
--
-It may be possible to generalize some of the utility functions beyond the
+
+1. It may be possible to generalize some of the utility functions beyond the
narrow context of the class in question -- by bundling them with the class,
the class author reduces the scope for functionality reuse.
-
--
-It's usually impossible for the class author to know every possible
+2. It's usually impossible for the class author to know every possible
operation that the user might want to perform on the class, so the public
interface will inherently be incomplete. New utility functions will end up
having a different syntax to the privileged public functions in the class,
negatively impacting on code consistency.
-
-
+
To refactor a class like this, simply move its utility functions elsewhere,
paring its public interface down to the bare minimum.
diff --git a/cpp/ql/src/Security/CWE/CWE-114/UncontrolledProcessOperation.ql b/cpp/ql/src/Security/CWE/CWE-114/UncontrolledProcessOperation.ql
index aedb21da516..7d2513d25e3 100644
--- a/cpp/ql/src/Security/CWE/CWE-114/UncontrolledProcessOperation.ql
+++ b/cpp/ql/src/Security/CWE/CWE-114/UncontrolledProcessOperation.ql
@@ -23,7 +23,7 @@ predicate isProcessOperationExplanation(DataFlow::Node arg, string processOperat
exists(int processOperationArg, FunctionCall call |
isProcessOperationArgument(processOperation, processOperationArg) and
call.getTarget().getName() = processOperation and
- call.getArgument(processOperationArg) = [arg.asExpr(), arg.asIndirectExpr()]
+ call.getArgument(processOperationArg) = arg.asIndirectExpr()
)
}
diff --git a/cpp/ql/src/Security/CWE/CWE-704/WcharCharConversion.ql b/cpp/ql/src/Security/CWE/CWE-704/WcharCharConversion.ql
index e3f15bd12b5..6fc91c1d669 100644
--- a/cpp/ql/src/Security/CWE/CWE-704/WcharCharConversion.ql
+++ b/cpp/ql/src/Security/CWE/CWE-704/WcharCharConversion.ql
@@ -14,6 +14,7 @@
import cpp
import semmle.code.cpp.controlflow.Guards
+import semmle.code.cpp.ir.IR
class WideCharPointerType extends PointerType {
WideCharPointerType() { this.getBaseType() instanceof WideCharType }
@@ -108,7 +109,9 @@ where
// Avoid cases where the cast is guarded by a check to determine if
// unicode encoding is enabled in such a way to disallow the dangerous cast
// at runtime.
- not isLikelyDynamicallyChecked(e1)
+ not isLikelyDynamicallyChecked(e1) and
+ // Avoid cases in unreachable blocks.
+ any(EnterFunctionInstruction e).getASuccessor+().getAst() = e1
select e1,
"Conversion from " + e1.getType().toString() + " to " + e2.getType().toString() +
". Use of invalid string can lead to undefined behavior."
diff --git a/cpp/ql/src/change-notes/2025-07-10-pthread-and-std-thread.md b/cpp/ql/src/change-notes/2025-07-10-pthread-and-std-thread.md
new file mode 100644
index 00000000000..8e8d0659fa6
--- /dev/null
+++ b/cpp/ql/src/change-notes/2025-07-10-pthread-and-std-thread.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* Added flow models for `pthread_create` and `std::thread`.
\ No newline at end of file
diff --git a/cpp/ql/src/change-notes/2025-07-10-wchar-fp.md b/cpp/ql/src/change-notes/2025-07-10-wchar-fp.md
new file mode 100644
index 00000000000..db940f18286
--- /dev/null
+++ b/cpp/ql/src/change-notes/2025-07-10-wchar-fp.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* The `cpp/incorrect-string-type-conversion` query no longer alerts on incorrect type conversions that occur in unreachable code.
diff --git a/cpp/ql/src/change-notes/2025-07-11-function-objects.md b/cpp/ql/src/change-notes/2025-07-11-function-objects.md
new file mode 100644
index 00000000000..48bc71f27ca
--- /dev/null
+++ b/cpp/ql/src/change-notes/2025-07-11-function-objects.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* Improved support for dataflow through function objects and lambda expressions.
\ No newline at end of file
diff --git a/cpp/ql/src/change-notes/2025-07-16-FunctionWithWrappers.md b/cpp/ql/src/change-notes/2025-07-16-FunctionWithWrappers.md
new file mode 100644
index 00000000000..0c3db774fa4
--- /dev/null
+++ b/cpp/ql/src/change-notes/2025-07-16-FunctionWithWrappers.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* Due to changes in the `FunctionWithWrappers` library (`semmle.code.cpp.security.FunctionWithWrappers`) the primary alert location generated by the queries `cpp/path-injection`, `cpp/sql-injection`, `cpp/tainted-format-string`, and `cpp/command-line-injection` may have changed.
\ No newline at end of file
diff --git a/cpp/ql/src/change-notes/released/1.4.1.md b/cpp/ql/src/change-notes/released/1.4.1.md
index 7d1ba66b92e..d055555fba0 100644
--- a/cpp/ql/src/change-notes/released/1.4.1.md
+++ b/cpp/ql/src/change-notes/released/1.4.1.md
@@ -2,4 +2,4 @@
### Minor Analysis Improvements
-* Added flow model for the `SQLite` and `OpenSSL` libraries. This may result in more alerts when running queries on codebases that use these libraries.
+* Added flow models for the `SQLite` and `OpenSSL` libraries. This may result in more alerts when running queries on codebases that use these libraries.
diff --git a/cpp/ql/src/change-notes/released/1.4.3.md b/cpp/ql/src/change-notes/released/1.4.3.md
index 2280196429b..46933b3c4e8 100644
--- a/cpp/ql/src/change-notes/released/1.4.3.md
+++ b/cpp/ql/src/change-notes/released/1.4.3.md
@@ -2,4 +2,4 @@
### Minor Analysis Improvements
-* Added flow model for the following libraries: `madler/zlib`, `google/brotli`, `libidn/libidn2`, `libssh2/libssh2/`, `nghttp2/nghttp2`, `libuv/libuv/`, and `curl/curl`. This may result in more alerts when running queries on codebases that use these libraries.
+* Added flow models for the following libraries: `madler/zlib`, `google/brotli`, `libidn/libidn2`, `libssh2/libssh2`, `nghttp2/nghttp2`, `libuv/libuv`, and `curl/curl`. This may result in more alerts when running queries on codebases that use these libraries.
diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected
index 9492b7dd276..9abcd6eeee7 100644
--- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected
+++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected
@@ -6,9 +6,15 @@ uniqueEnclosingCallable
| test.cpp:1126:33:1129:1 | {...} | Node should have one enclosing callable but has 0. |
| test.cpp:1127:3:1127:13 | reads_input | Node should have one enclosing callable but has 0. |
| test.cpp:1128:3:1128:21 | not_does_read_input | Node should have one enclosing callable but has 0. |
+| test.cpp:1158:18:1158:21 | call to sink | Node should have one enclosing callable but has 0. |
+| test.cpp:1158:18:1158:42 | ... , ... | Node should have one enclosing callable but has 0. |
+| test.cpp:1158:23:1158:31 | recursion | Node should have one enclosing callable but has 0. |
+| test.cpp:1158:35:1158:40 | call to source | Node should have one enclosing callable but has 0. |
uniqueCallEnclosingCallable
| test.cpp:864:47:864:54 | call to source | Call should have one enclosing callable but has 0. |
| test.cpp:872:46:872:51 | call to source | Call should have one enclosing callable but has 0. |
+| test.cpp:1158:18:1158:21 | call to sink | Call should have one enclosing callable but has 0. |
+| test.cpp:1158:35:1158:40 | call to source | Call should have one enclosing callable but has 0. |
uniqueType
uniqueNodeLocation
missingLocation
diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/has-parameter-flow-out.ql b/cpp/ql/test/library-tests/dataflow/dataflow-tests/has-parameter-flow-out.ql
index 34afffd8e58..8f534be558d 100644
--- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/has-parameter-flow-out.ql
+++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/has-parameter-flow-out.ql
@@ -24,10 +24,9 @@ module AstTest {
module IRTest {
private import semmle.code.cpp.ir.dataflow.DataFlow
- private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
private string stars(int k) {
- k = [0 .. max(FinalParameterNode n | | n.getIndirectionIndex())] and
+ k = [0 .. max(DataFlow::Node n, int i | n.isFinalValueOfParameter(_, i) | i)] and
(if k = 0 then result = "" else result = "*" + stars(k - 1))
}
@@ -35,14 +34,14 @@ module IRTest {
string getARelevantTag() { result = "ir-def" }
predicate hasActualResult(Location location, string element, string tag, string value) {
- exists(Function f, Parameter p, FinalParameterNode n |
+ exists(Function f, Parameter p, DataFlow::Node n, int i |
p.isNamed() and
- n.getParameter() = p and
+ n.isFinalValueOfParameter(p, i) and
n.getFunction() = f and
location = f.getLocation() and
element = p.toString() and
tag = "ir-def" and
- value = stars(n.getIndirectionIndex()) + p.getName()
+ value = stars(i) + p.getName()
)
}
}
diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp
index a65659191fb..b804159d858 100644
--- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp
+++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp
@@ -1153,4 +1153,6 @@ namespace conflation_regression {
*p = source(0);
read_deref_deref(p);
}
-}
\ No newline at end of file
+}
+
+int recursion = (sink(recursion), source()); // clean
\ No newline at end of file
diff --git a/cpp/ql/test/library-tests/dataflow/external-models/flow.expected b/cpp/ql/test/library-tests/dataflow/external-models/flow.expected
index 68d6aeeb6f4..bf9a4ed28d0 100644
--- a/cpp/ql/test/library-tests/dataflow/external-models/flow.expected
+++ b/cpp/ql/test/library-tests/dataflow/external-models/flow.expected
@@ -21,12 +21,14 @@ models
| 20 | Summary: ; ; false; CreateRemoteThreadEx; ; ; Argument[@4]; Argument[3].Parameter[@0]; value; manual |
| 21 | Summary: ; ; false; CreateThread; ; ; Argument[@3]; Argument[2].Parameter[@0]; value; manual |
| 22 | Summary: ; ; false; ReadFileEx; ; ; Argument[*3].Field[@hEvent]; Argument[4].Parameter[*2].Field[@hEvent]; value; manual |
-| 23 | Summary: ; ; false; ymlStepGenerated; ; ; Argument[0]; ReturnValue; taint; df-generated |
-| 24 | Summary: ; ; false; ymlStepManual; ; ; Argument[0]; ReturnValue; taint; manual |
-| 25 | Summary: ; ; false; ymlStepManual_with_body; ; ; Argument[0]; ReturnValue; taint; manual |
-| 26 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual |
+| 23 | Summary: ; ; false; callWithArgument; ; ; Argument[1]; Argument[0].Parameter[0]; value; manual |
+| 24 | Summary: ; ; false; pthread_create; ; ; Argument[@3]; Argument[2].Parameter[@0]; value; manual |
+| 25 | Summary: ; ; false; ymlStepGenerated; ; ; Argument[0]; ReturnValue; taint; df-generated |
+| 26 | Summary: ; ; false; ymlStepManual; ; ; Argument[0]; ReturnValue; taint; manual |
+| 27 | Summary: ; ; false; ymlStepManual_with_body; ; ; Argument[0]; ReturnValue; taint; manual |
+| 28 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual |
edges
-| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | provenance | MaD:26 |
+| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | provenance | MaD:28 |
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:91:7:91:17 | recv_buffer | provenance | Src:MaD:17 |
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:93:29:93:39 | *recv_buffer | provenance | Src:MaD:17 Sink:MaD:2 |
| asio_streams.cpp:97:37:97:44 | call to source | asio_streams.cpp:98:7:98:14 | send_str | provenance | TaintFunction |
@@ -35,10 +37,10 @@ edges
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:101:7:101:17 | send_buffer | provenance | |
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:103:29:103:39 | *send_buffer | provenance | Sink:MaD:2 |
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | provenance | |
-| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:26 |
-| test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | provenance | MaD:24 |
-| test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | provenance | MaD:23 |
-| test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | provenance | MaD:25 |
+| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:28 |
+| test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | provenance | MaD:26 |
+| test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | provenance | MaD:25 |
+| test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | provenance | MaD:27 |
| test.cpp:7:47:7:52 | value2 | test.cpp:7:64:7:69 | value2 | provenance | |
| test.cpp:7:64:7:69 | value2 | test.cpp:7:5:7:30 | *ymlStepGenerated_with_body | provenance | |
| test.cpp:10:10:10:18 | call to ymlSource | test.cpp:10:10:10:18 | call to ymlSource | provenance | Src:MaD:16 |
@@ -50,19 +52,49 @@ edges
| test.cpp:17:10:17:22 | call to ymlStepManual | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | |
| test.cpp:17:10:17:22 | call to ymlStepManual | test.cpp:18:10:18:10 | y | provenance | Sink:MaD:1 |
| test.cpp:17:24:17:24 | x | test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | provenance | |
-| test.cpp:17:24:17:24 | x | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | MaD:24 |
+| test.cpp:17:24:17:24 | x | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | MaD:26 |
| test.cpp:21:10:21:25 | call to ymlStepGenerated | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | |
| test.cpp:21:10:21:25 | call to ymlStepGenerated | test.cpp:22:10:22:10 | z | provenance | Sink:MaD:1 |
| test.cpp:21:27:21:27 | x | test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | provenance | |
-| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | MaD:23 |
+| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | MaD:25 |
| test.cpp:25:11:25:33 | call to ymlStepManual_with_body | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | |
| test.cpp:25:11:25:33 | call to ymlStepManual_with_body | test.cpp:26:10:26:11 | y2 | provenance | Sink:MaD:1 |
| test.cpp:25:35:25:35 | x | test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | provenance | |
-| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | MaD:25 |
+| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | MaD:27 |
| test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | provenance | |
| test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | test.cpp:33:10:33:11 | z2 | provenance | Sink:MaD:1 |
| test.cpp:32:41:32:41 | x | test.cpp:7:47:7:52 | value2 | provenance | |
| test.cpp:32:41:32:41 | x | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | provenance | |
+| test.cpp:46:30:46:32 | *arg [x] | test.cpp:47:12:47:19 | *arg [x] | provenance | |
+| test.cpp:47:12:47:19 | *arg [x] | test.cpp:48:13:48:13 | *s [x] | provenance | |
+| test.cpp:48:13:48:13 | *s [x] | test.cpp:48:16:48:16 | x | provenance | Sink:MaD:1 |
+| test.cpp:52:5:52:18 | [summary param] *3 in pthread_create [x] | test.cpp:52:5:52:18 | [summary] to write: Argument[2].Parameter[*0] in pthread_create [x] | provenance | MaD:24 |
+| test.cpp:52:5:52:18 | [summary] to write: Argument[2].Parameter[*0] in pthread_create [x] | test.cpp:46:30:46:32 | *arg [x] | provenance | |
+| test.cpp:56:2:56:2 | *s [post update] [x] | test.cpp:59:55:59:64 | *& ... [x] | provenance | |
+| test.cpp:56:2:56:18 | ... = ... | test.cpp:56:2:56:2 | *s [post update] [x] | provenance | |
+| test.cpp:56:8:56:16 | call to ymlSource | test.cpp:56:2:56:18 | ... = ... | provenance | Src:MaD:16 |
+| test.cpp:59:55:59:64 | *& ... [x] | test.cpp:52:5:52:18 | [summary param] *3 in pthread_create [x] | provenance | |
+| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | provenance | MaD:23 |
+| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | provenance | MaD:23 |
+| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | provenance | MaD:23 |
+| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | provenance | MaD:23 |
+| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | test.cpp:68:22:68:22 | y | provenance | |
+| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | test.cpp:74:22:74:22 | y | provenance | |
+| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | test.cpp:82:22:82:22 | y | provenance | |
+| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | test.cpp:88:22:88:22 | y | provenance | |
+| test.cpp:68:22:68:22 | y | test.cpp:69:11:69:11 | y | provenance | Sink:MaD:1 |
+| test.cpp:74:22:74:22 | y | test.cpp:75:11:75:11 | y | provenance | Sink:MaD:1 |
+| test.cpp:82:22:82:22 | y | test.cpp:83:11:83:11 | y | provenance | Sink:MaD:1 |
+| test.cpp:88:22:88:22 | y | test.cpp:89:11:89:11 | y | provenance | Sink:MaD:1 |
+| test.cpp:94:10:94:18 | call to ymlSource | test.cpp:94:10:94:18 | call to ymlSource | provenance | Src:MaD:16 |
+| test.cpp:94:10:94:18 | call to ymlSource | test.cpp:97:26:97:26 | x | provenance | |
+| test.cpp:94:10:94:18 | call to ymlSource | test.cpp:101:26:101:26 | x | provenance | |
+| test.cpp:94:10:94:18 | call to ymlSource | test.cpp:103:63:103:63 | x | provenance | |
+| test.cpp:94:10:94:18 | call to ymlSource | test.cpp:104:62:104:62 | x | provenance | |
+| test.cpp:97:26:97:26 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | |
+| test.cpp:101:26:101:26 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | |
+| test.cpp:103:63:103:63 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | |
+| test.cpp:104:62:104:62 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | |
| windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | provenance | MaD:18 |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:22:15:22:29 | *call to GetCommandLineA | provenance | Src:MaD:3 |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:24:8:24:11 | * ... | provenance | |
@@ -189,6 +221,38 @@ nodes
| test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | semmle.label | call to ymlStepGenerated_with_body |
| test.cpp:32:41:32:41 | x | semmle.label | x |
| test.cpp:33:10:33:11 | z2 | semmle.label | z2 |
+| test.cpp:46:30:46:32 | *arg [x] | semmle.label | *arg [x] |
+| test.cpp:47:12:47:19 | *arg [x] | semmle.label | *arg [x] |
+| test.cpp:48:13:48:13 | *s [x] | semmle.label | *s [x] |
+| test.cpp:48:16:48:16 | x | semmle.label | x |
+| test.cpp:52:5:52:18 | [summary param] *3 in pthread_create [x] | semmle.label | [summary param] *3 in pthread_create [x] |
+| test.cpp:52:5:52:18 | [summary] to write: Argument[2].Parameter[*0] in pthread_create [x] | semmle.label | [summary] to write: Argument[2].Parameter[*0] in pthread_create [x] |
+| test.cpp:56:2:56:2 | *s [post update] [x] | semmle.label | *s [post update] [x] |
+| test.cpp:56:2:56:18 | ... = ... | semmle.label | ... = ... |
+| test.cpp:56:8:56:16 | call to ymlSource | semmle.label | call to ymlSource |
+| test.cpp:59:55:59:64 | *& ... [x] | semmle.label | *& ... [x] |
+| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | semmle.label | [summary param] 1 in callWithArgument |
+| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | semmle.label | [summary param] 1 in callWithArgument |
+| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | semmle.label | [summary param] 1 in callWithArgument |
+| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | semmle.label | [summary param] 1 in callWithArgument |
+| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | semmle.label | [summary] to write: Argument[0].Parameter[0] in callWithArgument |
+| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | semmle.label | [summary] to write: Argument[0].Parameter[0] in callWithArgument |
+| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | semmle.label | [summary] to write: Argument[0].Parameter[0] in callWithArgument |
+| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | semmle.label | [summary] to write: Argument[0].Parameter[0] in callWithArgument |
+| test.cpp:68:22:68:22 | y | semmle.label | y |
+| test.cpp:69:11:69:11 | y | semmle.label | y |
+| test.cpp:74:22:74:22 | y | semmle.label | y |
+| test.cpp:75:11:75:11 | y | semmle.label | y |
+| test.cpp:82:22:82:22 | y | semmle.label | y |
+| test.cpp:83:11:83:11 | y | semmle.label | y |
+| test.cpp:88:22:88:22 | y | semmle.label | y |
+| test.cpp:89:11:89:11 | y | semmle.label | y |
+| test.cpp:94:10:94:18 | call to ymlSource | semmle.label | call to ymlSource |
+| test.cpp:94:10:94:18 | call to ymlSource | semmle.label | call to ymlSource |
+| test.cpp:97:26:97:26 | x | semmle.label | x |
+| test.cpp:101:26:101:26 | x | semmle.label | x |
+| test.cpp:103:63:103:63 | x | semmle.label | x |
+| test.cpp:104:62:104:62 | x | semmle.label | x |
| windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | semmle.label | [summary param] *0 in CommandLineToArgvA |
| windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | semmle.label | [summary] to write: ReturnValue[**] in CommandLineToArgvA |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | semmle.label | *call to GetCommandLineA |
diff --git a/cpp/ql/test/library-tests/dataflow/external-models/flow.ext.yml b/cpp/ql/test/library-tests/dataflow/external-models/flow.ext.yml
index 12dbf7d4cd2..f0df3e749e6 100644
--- a/cpp/ql/test/library-tests/dataflow/external-models/flow.ext.yml
+++ b/cpp/ql/test/library-tests/dataflow/external-models/flow.ext.yml
@@ -16,4 +16,5 @@ extensions:
- ["", "", False, "ymlStepManual", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["", "", False, "ymlStepGenerated", "", "", "Argument[0]", "ReturnValue", "taint", "df-generated"]
- ["", "", False, "ymlStepManual_with_body", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- - ["", "", False, "ymlStepGenerated_with_body", "", "", "Argument[0]", "ReturnValue", "taint", "df-generated"]
\ No newline at end of file
+ - ["", "", False, "ymlStepGenerated_with_body", "", "", "Argument[0]", "ReturnValue", "taint", "df-generated"]
+ - ["", "", False, "callWithArgument", "", "", "Argument[1]", "Argument[0].Parameter[0]", "value", "manual"]
\ No newline at end of file
diff --git a/cpp/ql/test/library-tests/dataflow/external-models/sinks.expected b/cpp/ql/test/library-tests/dataflow/external-models/sinks.expected
index 2c2338a7dcc..0cc01c8165e 100644
--- a/cpp/ql/test/library-tests/dataflow/external-models/sinks.expected
+++ b/cpp/ql/test/library-tests/dataflow/external-models/sinks.expected
@@ -8,3 +8,8 @@
| test.cpp:29:10:29:11 | y3 | test-sink |
| test.cpp:33:10:33:11 | z2 | test-sink |
| test.cpp:36:10:36:11 | z3 | test-sink |
+| test.cpp:48:16:48:16 | x | test-sink |
+| test.cpp:69:11:69:11 | y | test-sink |
+| test.cpp:75:11:75:11 | y | test-sink |
+| test.cpp:83:11:83:11 | y | test-sink |
+| test.cpp:89:11:89:11 | y | test-sink |
diff --git a/cpp/ql/test/library-tests/dataflow/external-models/sources.expected b/cpp/ql/test/library-tests/dataflow/external-models/sources.expected
index 8730083d016..401fffdbd59 100644
--- a/cpp/ql/test/library-tests/dataflow/external-models/sources.expected
+++ b/cpp/ql/test/library-tests/dataflow/external-models/sources.expected
@@ -1,5 +1,7 @@
| asio_streams.cpp:87:34:87:44 | read_until output argument | remote |
| test.cpp:10:10:10:18 | call to ymlSource | local |
+| test.cpp:56:8:56:16 | call to ymlSource | local |
+| test.cpp:94:10:94:18 | call to ymlSource | local |
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | local |
| windows.cpp:34:17:34:38 | *call to GetEnvironmentStringsA | local |
| windows.cpp:39:36:39:38 | GetEnvironmentVariableA output argument | local |
diff --git a/cpp/ql/test/library-tests/dataflow/external-models/test.cpp b/cpp/ql/test/library-tests/dataflow/external-models/test.cpp
index a0b12004074..f357b934b2f 100644
--- a/cpp/ql/test/library-tests/dataflow/external-models/test.cpp
+++ b/cpp/ql/test/library-tests/dataflow/external-models/test.cpp
@@ -35,3 +35,71 @@ void test() {
int z3 = ymlStepGenerated_with_body(x, 0);
ymlSink(z3); // clean
}
+
+struct S {
+ int x;
+};
+
+using pthread_t = unsigned long;
+using pthread_attr_t = void*;
+
+void *myThreadFunction(void *arg) {
+ S* s = (S *)arg;
+ ymlSink(s->x); // $ ir
+ return nullptr;
+}
+
+int pthread_create(pthread_t *thread, const pthread_attr_t * attr, void *(*start_routine)(void*), void *arg);
+
+int test_pthread_create() {
+ S s;
+ s.x = ymlSource();
+
+ pthread_t threadId;
+ pthread_create(&threadId, nullptr, myThreadFunction, (void *)&s);
+}
+
+template
+void callWithArgument(F f, int x);
+
+struct StructWithOperatorCall_has_constructor {
+ StructWithOperatorCall_has_constructor();
+
+ void operator()(int y) {
+ ymlSink(y); // $ ir
+ }
+};
+
+struct StructWithOperatorCall_no_constructor {
+ void operator()(int y) {
+ ymlSink(y); // $ ir
+ }
+};
+
+struct StructWithOperatorCall_has_constructor_2 {
+ StructWithOperatorCall_has_constructor_2();
+
+ void operator()(int y) {
+ ymlSink(y); // $ ir
+ }
+};
+
+struct StructWithOperatorCall_no_constructor_2 {
+ void operator()(int y) {
+ ymlSink(y); // $ ir
+ }
+};
+
+void test_callWithArgument() {
+ int x = ymlSource();
+ {
+ StructWithOperatorCall_has_constructor func;
+ callWithArgument(func, x);
+ }
+ {
+ StructWithOperatorCall_no_constructor func;
+ callWithArgument(func, x);
+ }
+ callWithArgument(StructWithOperatorCall_has_constructor_2(), x);
+ callWithArgument(StructWithOperatorCall_no_constructor_2(), x);
+}
\ No newline at end of file
diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected
index 1eab706df43..e19f34eb217 100644
--- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected
+++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected
@@ -7767,6 +7767,34 @@ WARNING: module 'TaintTracking' has been deprecated and may be removed in future
| taint.cpp:830:20:830:34 | call to indirect_source | taint.cpp:832:23:832:24 | in | |
| taint.cpp:831:15:831:17 | out | taint.cpp:832:18:832:20 | out | |
| taint.cpp:831:15:831:17 | out | taint.cpp:833:8:833:10 | out | |
+| thread.cpp:10:27:10:27 | s | thread.cpp:10:27:10:27 | s | |
+| thread.cpp:10:27:10:27 | s | thread.cpp:11:8:11:8 | s | |
+| thread.cpp:14:26:14:26 | s | thread.cpp:15:8:15:8 | s | |
+| thread.cpp:18:27:18:27 | s | thread.cpp:18:27:18:27 | s | |
+| thread.cpp:18:27:18:27 | s | thread.cpp:19:8:19:8 | s | |
+| thread.cpp:18:34:18:34 | y | thread.cpp:20:8:20:8 | y | |
+| thread.cpp:24:5:24:5 | s | thread.cpp:25:3:25:3 | s | |
+| thread.cpp:24:5:24:5 | s | thread.cpp:26:38:26:38 | s | |
+| thread.cpp:24:5:24:5 | s | thread.cpp:27:37:27:37 | s | |
+| thread.cpp:24:5:24:5 | s | thread.cpp:28:38:28:38 | s | |
+| thread.cpp:24:5:24:5 | s | thread.cpp:32:7:32:7 | s | |
+| thread.cpp:25:3:25:3 | s [post update] | thread.cpp:26:38:26:38 | s | |
+| thread.cpp:25:3:25:3 | s [post update] | thread.cpp:27:37:27:37 | s | |
+| thread.cpp:25:3:25:3 | s [post update] | thread.cpp:28:38:28:38 | s | |
+| thread.cpp:25:3:25:3 | s [post update] | thread.cpp:32:7:32:7 | s | |
+| thread.cpp:25:3:25:16 | ... = ... | thread.cpp:25:5:25:5 | x [post update] | |
+| thread.cpp:25:9:25:14 | call to source | thread.cpp:25:3:25:16 | ... = ... | |
+| thread.cpp:26:18:26:39 | call to thread | thread.cpp:33:1:33:1 | t1 | |
+| thread.cpp:26:38:26:38 | s | thread.cpp:26:37:26:38 | & ... | |
+| thread.cpp:27:18:27:38 | call to thread | thread.cpp:33:1:33:1 | t2 | |
+| thread.cpp:27:37:27:37 | ref arg s | thread.cpp:28:38:28:38 | s | |
+| thread.cpp:27:37:27:37 | ref arg s | thread.cpp:32:7:32:7 | s | |
+| thread.cpp:28:18:28:43 | call to thread | thread.cpp:33:1:33:1 | t3 | |
+| thread.cpp:28:38:28:38 | s | thread.cpp:28:37:28:38 | & ... | |
+| thread.cpp:30:18:32:8 | call to thread | thread.cpp:33:1:33:1 | t4 | |
+| thread.cpp:30:24:30:24 | p | thread.cpp:30:24:30:24 | p | |
+| thread.cpp:30:24:30:24 | p | thread.cpp:31:10:31:10 | p | |
+| thread.cpp:32:7:32:7 | s | thread.cpp:32:6:32:7 | & ... | |
| vector.cpp:16:43:16:49 | source1 | vector.cpp:17:26:17:32 | source1 | |
| vector.cpp:16:43:16:49 | source1 | vector.cpp:31:38:31:44 | source1 | |
| vector.cpp:17:21:17:33 | call to vector | vector.cpp:19:14:19:14 | v | |
diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h
index 01e5f3b929b..57be2e9769a 100644
--- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h
+++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h
@@ -681,4 +681,17 @@ namespace std {
// the model for `format`.
template
int same_signature_as_format_but_different_name(format_string, Args &&...args);
+}
+
+namespace std {
+ class thread {
+ public:
+ template
+ explicit thread(F&&, Args&&...);
+
+ ~thread();
+
+ void join();
+ void detach();
+ };
}
\ No newline at end of file
diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_mad-signatures.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_mad-signatures.expected
index 3d4dd65d112..239ed2ec607 100644
--- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_mad-signatures.expected
+++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_mad-signatures.expected
@@ -17670,6 +17670,446 @@ signatureMatches
| taint.cpp:822:6:822:19 | take_const_ptr | (unsigned long *,const char *) | | set_cert_ex | 1 |
| taint.cpp:822:6:822:19 | take_const_ptr | (unsigned long *,const char *) | | set_name_ex | 1 |
| taint.cpp:822:6:822:19 | take_const_ptr | (uv_pipe_t *,const char *) | | uv_pipe_bind | 1 |
+| thread.cpp:4:6:4:9 | sink | (int) | | ASN1_STRING_type_new | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | ASN1_tag2bit | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | ASN1_tag2str | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | EVP_PKEY_asn1_get0 | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | Jim_ReturnCode | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | Jim_SignalId | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | OBJ_nid2ln | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | OBJ_nid2obj | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | OBJ_nid2sn | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | OSSL_STORE_INFO_type_string | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | OSSL_trace_get_category_name | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | PKCS12_init | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | Symbol_Nth | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | X509_PURPOSE_get0 | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | X509_PURPOSE_get_by_id | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | X509_TRUST_get0 | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | X509_TRUST_get_by_id | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | X509_VERIFY_PARAM_get0 | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | __btowc | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | __current_locale_name | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | __fdopendir | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | __get_errlist | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | __get_errname | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | __math_invalid_i | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | __math_invalidf_i | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | __p_class | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | __p_rcode | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | __p_type | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | __pkey_get | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | __sigdescr_np | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | __strerrordesc_np | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | _tolower | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | _toupper | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | btowc | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | c_tolower | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | c_toupper | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | curlx_sitouz | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | evp_pkey_type2name | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | inet6_option_space | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | isalnum | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | isalpha | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | isblank | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | iscntrl | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | isdigit | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | isgraph | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | islower | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | isprint | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | ispunct | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | isspace | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | isupper | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | isxdigit | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | ossl_cmp_bodytype_to_string | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | ossl_tolower | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | ossl_toupper | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | sigabbrev_np | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | sqlite3_compileoption_get | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | sqlite3_errstr | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | strerrorname_np | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | support_report_failure | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | svcudp_create | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | tls13_alert_code | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | toascii | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | tolower | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | toupper | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | uabs | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | uv__accept | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | uv_err_name | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | uv_get_osfhandle | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | uv_strerror | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | uv_translate_sys_error | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | | zError | 0 |
+| thread.cpp:4:6:4:9 | sink | (int) | __pthread_cleanup_class | __setdoit | 0 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (ASN1_STRING *,int) | | ASN1_STRING_length_set | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (ASYNC_WAIT_CTX *,int) | | ASYNC_WAIT_CTX_set_status | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (BIGNUM *,int) | | BN_clear_bit | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (BIGNUM *,int) | | BN_mask_bits | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (BIGNUM *,int) | | BN_set_bit | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (BIGNUM *,int) | | BN_set_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (BIGNUM *,int) | | bn_expand2 | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (BIGNUM *,int) | | bn_wexpand | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (BIGNUM *,int) | | ossl_bn_mask_bits_fixed_top | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (BIO *,int) | | BIO_clear_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (BIO *,int) | | BIO_find_type | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (BIO *,int) | | BIO_set_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (BIO *,int) | | BIO_set_init | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (BIO *,int) | | BIO_set_retry_reason | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (BIO *,int) | | BIO_set_shutdown | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (BIO *,int) | | TXT_DB_read | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (CMS_SignerInfo *,int) | | CMS_signed_delete_attr | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (CMS_SignerInfo *,int) | | CMS_unsigned_delete_attr | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (CURL *,int) | | curl_easy_pause | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (Curl_easy *,int) | | Curl_conn_get_socket | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (DH *,int) | | DH_clear_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (DH *,int) | | DH_set_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (DH_METHOD *,int) | | DH_meth_set_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (DSA *,int) | | DSA_clear_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (DSA *,int) | | DSA_set_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (DSA_METHOD *,int) | | DSA_meth_set_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EC_GROUP *,int) | | EC_GROUP_set_asn1_flag | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EC_GROUP *,int) | | EC_GROUP_set_curve_name | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EC_KEY *,int) | | EC_KEY_clear_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EC_KEY *,int) | | EC_KEY_set_asn1_flag | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EC_KEY *,int) | | EC_KEY_set_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (ENGINE *,int) | | ENGINE_cmd_is_executable | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (ENGINE *,int) | | ENGINE_set_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_CIPHER *,int) | | EVP_CIPHER_meth_set_impl_ctx_size | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_CIPHER *,int) | | EVP_CIPHER_meth_set_iv_length | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_CIPHER_CTX *,int) | | EVP_CIPHER_CTX_clear_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_CIPHER_CTX *,int) | | EVP_CIPHER_CTX_set_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_CIPHER_CTX *,int) | | EVP_CIPHER_CTX_set_key_length | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_CIPHER_CTX *,int) | | EVP_CIPHER_CTX_set_num | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_KEYMGMT *,int) | | evp_keymgmt_util_query_operation_name | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_MD *,int) | | EVP_MD_meth_set_app_datasize | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_MD *,int) | | EVP_MD_meth_set_input_blocksize | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_MD *,int) | | EVP_MD_meth_set_result_size | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_MD_CTX *,int) | | EVP_MD_CTX_clear_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_MD_CTX *,int) | | EVP_MD_CTX_set_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_PKEY *,int) | | EVP_PKEY_delete_attr | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_PKEY *,int) | | EVP_PKEY_save_parameters | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_PKEY *,int) | | EVP_PKEY_set_type | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_PKEY_CTX *,int) | | EVP_PKEY_CTX_get_keygen_info | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_PKEY_CTX *,int) | | EVP_PKEY_CTX_set_dh_kdf_type | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_PKEY_CTX *,int) | | EVP_PKEY_CTX_set_dh_nid | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_PKEY_CTX *,int) | | EVP_PKEY_CTX_set_dh_paramgen_type | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_PKEY_CTX *,int) | | EVP_PKEY_CTX_set_dh_rfc5114 | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_PKEY_CTX *,int) | | EVP_PKEY_CTX_set_dhx_rfc5114 | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_PKEY_CTX *,int) | | EVP_PKEY_CTX_set_ec_param_enc | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_PKEY_CTX *,int) | | EVP_PKEY_CTX_set_ec_paramgen_curve_nid | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_PKEY_CTX *,int) | | EVP_PKEY_CTX_set_ecdh_kdf_type | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_PKEY_CTX *,int) | | EVP_PKEY_CTX_set_hkdf_mode | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_PKEY_CTX *,int) | | EVP_PKEY_CTX_set_rsa_padding | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (EVP_PKEY_CTX *,int) | | EVP_PKEY_CTX_set_rsa_pss_saltlen | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (FFC_PARAMS *,int) | | ossl_ffc_params_set_gindex | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (FFC_PARAMS *,int) | | ossl_ffc_params_set_h | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (FFC_PARAMS *,int) | | ossl_ffc_params_set_pcounter | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (FILE *,int) | | _IO_default_pbackfail | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (FILE *,int) | | _IO_fwide | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (FILE *,int) | | _IO_init | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (FILE *,int) | | _IO_init_internal | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (FILE *,int) | | _IO_new_file_attach | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (FILE *,int) | | _IO_new_file_overflow | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (FILE *,int) | | _IO_old_init | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (FILE *,int) | | _IO_sputbackc | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (FILE *,int) | | _IO_str_overflow | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (FILE *,int) | | _IO_str_pbackfail | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (FILE *,int) | | __printf_buffer_as_file_overflow | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (FILE *,int) | | __wprintf_buffer_as_file_overflow | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (FTS *,int) | | fts_children | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (LIBSSH2_CHANNEL *,int) | | _libssh2_channel_extended_data | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (LIBSSH2_CHANNEL *,int) | | _libssh2_channel_flush | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (LIBSSH2_CHANNEL *,int) | | libssh2_channel_flush_ex | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (LIBSSH2_CHANNEL *,int) | | libssh2_channel_handle_extended_data | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (LIBSSH2_CHANNEL *,int) | | libssh2_channel_handle_extended_data2 | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (LIBSSH2_CHANNEL *,int) | | libssh2_channel_set_blocking | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (LIBSSH2_SESSION *,int) | | _libssh2_session_set_blocking | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (LIBSSH2_SESSION *,int) | | libssh2_hostkey_hash | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (LIBSSH2_SESSION *,int) | | libssh2_session_methods | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (LIBSSH2_SESSION *,int) | | libssh2_session_set_blocking | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (LIBSSH2_SESSION *,int) | | libssh2_session_startup | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (LPCOLESTR,int) | CComBSTR | Append | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OCSP_BASICRESP *,int) | | OCSP_BASICRESP_delete_ext | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OCSP_BASICRESP *,int) | | OCSP_BASICRESP_get_ext | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OCSP_BASICRESP *,int) | | OCSP_resp_get0 | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OCSP_ONEREQ *,int) | | OCSP_ONEREQ_delete_ext | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OCSP_ONEREQ *,int) | | OCSP_ONEREQ_get_ext | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OCSP_REQUEST *,int) | | OCSP_REQUEST_delete_ext | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OCSP_REQUEST *,int) | | OCSP_REQUEST_get_ext | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OCSP_REQUEST *,int) | | OCSP_request_onereq_get0 | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OCSP_SINGLERESP *,int) | | OCSP_SINGLERESP_delete_ext | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OCSP_SINGLERESP *,int) | | OCSP_SINGLERESP_get_ext | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OPENSSL_STACK *,int) | | OPENSSL_sk_delete | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OPENSSL_STACK *,int) | | OPENSSL_sk_reserve | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OPENSSL_sk_compfunc,int) | | OPENSSL_sk_new_reserve | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_ACKM *,int) | | ossl_ackm_get_ack_deadline | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_ACKM *,int) | | ossl_ackm_get_ack_frame | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_ACKM *,int) | | ossl_ackm_get_largest_acked | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_ACKM *,int) | | ossl_ackm_on_pkt_space_discarded | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_CMP_CTX *,int) | | OSSL_CMP_CTX_set_serverPort | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_CMP_CTX *,int) | | ossl_cmp_ctx_set_failInfoCode | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_CMP_CTX *,int) | | ossl_cmp_ctx_set_status | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_CMP_CTX *,int) | | ossl_cmp_msg_create | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_CMP_CTX *,int) | | ossl_cmp_pollReq_new | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_CMP_MSG *,int) | | ossl_cmp_msg_set_bodytype | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_CMP_PKIHEADER *,int) | | ossl_cmp_hdr_set_pvno | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_CMP_REVREPCONTENT *,int) | | ossl_cmp_revrepcontent_get_CertId | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_CMP_REVREPCONTENT *,int) | | ossl_cmp_revrepcontent_get_pkisi | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_CMP_SRV_CTX *,int) | | OSSL_CMP_SRV_CTX_set_accept_raverified | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_CMP_SRV_CTX *,int) | | OSSL_CMP_SRV_CTX_set_accept_unprotected | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_CMP_SRV_CTX *,int) | | OSSL_CMP_SRV_CTX_set_grant_implicit_confirm | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_CMP_SRV_CTX *,int) | | OSSL_CMP_SRV_CTX_set_send_unprotected_errors | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_CRMF_PKIPUBLICATIONINFO *,int) | | OSSL_CRMF_MSG_set_PKIPublicationInfo_action | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_DECODER_CTX *,int) | | OSSL_DECODER_CTX_set_selection | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_ENCODER_CTX *,int) | | OSSL_ENCODER_CTX_set_selection | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_LIB_CTX *,int) | | OSSL_LIB_CTX_get_data | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_LIB_CTX *,int) | | OSSL_LIB_CTX_set_conf_diagnostics | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_LIB_CTX *,int) | | ossl_ctx_global_properties | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_LIB_CTX *,int) | | ossl_dh_new_by_nid_ex | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_LIB_CTX *,int) | | ossl_lib_ctx_get_data | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_LIB_CTX *,int) | | ossl_mac_key_new | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_PARAM *,int) | | OSSL_PARAM_set_int | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_QRX *,int) | | ossl_qrx_get_bytes_received | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_RECORD_LAYER *,int) | | tls_set_first_handshake | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_RECORD_LAYER *,int) | | tls_set_plain_alerts | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (OSSL_STORE_CTX *,int) | | OSSL_STORE_expect | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (PKCS7 *,int) | | PKCS7_set_type | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (QUIC_CHANNEL *,int) | | ossl_quic_channel_new_stream_local | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (QUIC_ENGINE *,int) | | ossl_quic_engine_set_inhibit_tick | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (QUIC_PORT *,int) | | ossl_quic_port_set_allow_incoming | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (QUIC_RCIDM *,int) | | ossl_quic_rcidm_get_preferred_tx_dcid_changed | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (QUIC_RSTREAM *,int) | | ossl_quic_rstream_set_cleanse | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (QUIC_RXFC *,int) | | ossl_quic_rxfc_get_error | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (QUIC_RXFC *,int) | | ossl_quic_rxfc_has_cwm_changed | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (QUIC_SSTREAM *,int) | | ossl_quic_sstream_set_cleanse | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (QUIC_STREAM_MAP *,int) | | ossl_quic_stream_map_get_accept_queue_len | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (QUIC_TXFC *,int) | | ossl_quic_txfc_has_become_blocked | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (RSA *,int) | | RSA_clear_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (RSA *,int) | | RSA_set_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (RSA_METHOD *,int) | | RSA_meth_set_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (RSA_PSS_PARAMS_30 *,int) | | ossl_rsa_pss_params_30_set_hashalg | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (RSA_PSS_PARAMS_30 *,int) | | ossl_rsa_pss_params_30_set_maskgenhashalg | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (RSA_PSS_PARAMS_30 *,int) | | ossl_rsa_pss_params_30_set_saltlen | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (RSA_PSS_PARAMS_30 *,int) | | ossl_rsa_pss_params_30_set_trailerfield | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (SSL *,int) | | SSL_key_update | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (SSL *,int) | | SSL_set_post_handshake_auth | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (SSL *,int) | | SSL_set_purpose | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (SSL *,int) | | SSL_set_quic_tls_early_data_enabled | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (SSL *,int) | | SSL_set_quiet_shutdown | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (SSL *,int) | | SSL_set_read_ahead | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (SSL *,int) | | SSL_set_security_level | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (SSL *,int) | | SSL_set_shutdown | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (SSL *,int) | | SSL_set_trust | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (SSL *,int) | | SSL_set_verify_depth | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (SSL_CONNECTION *,int) | | dtls1_read_failed | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (SSL_CONNECTION *,int) | | ossl_statem_send_fatal | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (SSL_CONNECTION *,int) | | ossl_statem_set_in_init | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (SSL_CONNECTION *,int) | | tls1_shared_group | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (SSL_CTX *,int) | | SSL_CTX_set_post_handshake_auth | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (SSL_CTX *,int) | | SSL_CTX_set_purpose | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (SSL_CTX *,int) | | SSL_CTX_set_quiet_shutdown | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (SSL_CTX *,int) | | SSL_CTX_set_security_level | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (SSL_CTX *,int) | | SSL_CTX_set_srp_strength | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (SSL_CTX *,int) | | SSL_CTX_set_trust | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (SSL_CTX *,int) | | SSL_CTX_set_verify_depth | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (SSL_CTX *,int) | | ssl_md | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (SSL_SESSION *,int) | | SSL_SESSION_set_protocol_version | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (TS_REQ *,int) | | TS_REQ_delete_ext | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (TS_REQ *,int) | | TS_REQ_get_ext | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (TS_RESP_CTX *,int) | | TS_RESP_CTX_add_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (TS_STATUS_INFO *,int) | | TS_STATUS_INFO_set_status | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (TS_TST_INFO *,int) | | TS_TST_INFO_delete_ext | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (TS_TST_INFO *,int) | | TS_TST_INFO_get_ext | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (TS_VERIFY_CTX *,int) | | TS_VERIFY_CTX_add_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (TS_VERIFY_CTX *,int) | | TS_VERIFY_CTX_set_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (WPACKET *,int) | | ossl_DER_w_begin_sequence | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (X509 *,int) | | X509_delete_ext | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (X509 *,int) | | X509_self_signed | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (X509_ACERT *,int) | | X509_ACERT_delete_attr | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (X509_ATTRIBUTE *,int) | | X509_ATTRIBUTE_get0_type | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (X509_CRL *,int) | | X509_CRL_delete_ext | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (X509_NAME *,int) | | X509_NAME_delete_entry | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (X509_REQ *,int) | | X509_REQ_delete_attr | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (X509_REVOKED *,int) | | X509_REVOKED_delete_ext | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (X509_STORE *,int) | | X509_STORE_set_depth | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (X509_STORE *,int) | | X509_STORE_set_purpose | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (X509_STORE *,int) | | X509_STORE_set_trust | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (X509_STORE_CTX *,int) | | X509_STORE_CTX_set_depth | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (X509_STORE_CTX *,int) | | X509_STORE_CTX_set_error | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (X509_STORE_CTX *,int) | | X509_STORE_CTX_set_error_depth | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (X509_STORE_CTX *,int) | | X509_STORE_CTX_set_purpose | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (X509_STORE_CTX *,int) | | X509_STORE_CTX_set_trust | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (X509_VERIFY_PARAM *,int) | | X509_VERIFY_PARAM_get0_host | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (X509_VERIFY_PARAM *,int) | | X509_VERIFY_PARAM_set_auth_level | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (X509_VERIFY_PARAM *,int) | | X509_VERIFY_PARAM_set_depth | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (X509_VERIFY_PARAM *,int) | | X509_VERIFY_PARAM_set_purpose | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (X509_VERIFY_PARAM *,int) | | X509_VERIFY_PARAM_set_trust | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (_Float128,int) | | __ldexpf128 | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (_Float128,int) | | __scalbnf128 | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (__sigset_t *,int) | | __sigaddset_compat | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (__sigset_t *,int) | | __sigdelset_compat | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (acttab *,int) | | acttab_insert | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (addrinfo *,int) | | support_format_addrinfo | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (aiocb_union *,int) | | __aio_enqueue_request | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (argp_fmtstream_t,int) | | __argp_fmtstream_putc | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (char **,int) | | addrsort | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (char *,int) | | Curl_str2addr | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (char *,int) | | PEM_proc_type | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (char,int) | CStringT | CStringT | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (connectdata *,int) | | Curl_conn_is_ssl | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const ASN1_BIT_STRING *,int) | | ASN1_BIT_STRING_get_bit | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const BIGNUM *,int) | | BN_get_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const BIGNUM *,int) | | BN_is_bit_set | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const BIO *,int) | | BIO_get_ex_data | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const BIO *,int) | | BIO_test_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const CMS_SignerInfo *,int) | | CMS_signed_get_attr | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const CMS_SignerInfo *,int) | | CMS_unsigned_get_attr | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const CRYPTO_EX_DATA *,int) | | CRYPTO_get_ex_data | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const DH *,int) | | DH_get_ex_data | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const DH *,int) | | DH_test_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const DH *,int) | | ossl_dh_dup | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const DSA *,int) | | DSA_get_ex_data | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const DSA *,int) | | DSA_test_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const DSA *,int) | | ossl_dsa_dup | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const ECX_KEY *,int) | | ossl_ecx_key_dup | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const EC_KEY *,int) | | EC_KEY_get_ex_data | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const EC_KEY *,int) | | ossl_ec_key_dup | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const ENGINE *,int) | | ENGINE_get_ex_data | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const EVP_CIPHER_CTX *,int) | | EVP_CIPHER_CTX_test_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const EVP_MD_CTX *,int) | | EVP_MD_CTX_test_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const EVP_PKEY *,int) | | EVP_PKEY_get_attr | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const EVP_PKEY *,int) | | EVP_PKEY_get_ex_data | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const ML_DSA_KEY *,int) | | ossl_ml_dsa_key_dup | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const ML_KEM_KEY *,int) | | ossl_ml_kem_key_dup | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const OPENSSL_STACK *,int) | | OPENSSL_sk_value | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const OSSL_CMP_CERTREPMESSAGE *,int) | | ossl_cmp_certrepmessage_get0_certresponse | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const OSSL_CMP_CTX *,int) | | OSSL_CMP_CTX_get0_newPkey | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const OSSL_CMP_CTX *,int) | | OSSL_CMP_CTX_get_option | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const OSSL_CMP_PKISI *,int) | | ossl_cmp_pkisi_check_pkifailureinfo | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const OSSL_CMP_POLLREPCONTENT *,int) | | ossl_cmp_pollrepcontent_get0_pollrep | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const QUIC_CHANNEL *,int) | | ossl_quic_channel_get_local_stream_count_avail | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const QUIC_CHANNEL *,int) | | ossl_quic_channel_get_remote_stream_count_avail | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const RSA *,int) | | RSA_get_ex_data | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const RSA *,int) | | RSA_test_flags | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const RSA *,int) | | ossl_rsa_dup | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const SLH_DSA_KEY *,int) | | ossl_slh_dsa_key_dup | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const SSL *,int) | | SSL_get_ex_data | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const SSL_CTX *,int) | | SSL_CTX_get_ex_data | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const SSL_SESSION *,int) | | SSL_SESSION_get_ex_data | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const SSL_SESSION *,int) | | ssl_session_dup | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const UI *,int) | | UI_get_ex_data | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const UI_METHOD *,int) | | UI_method_get_ex_data | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const X509 *,int) | | X509_get_ex_data | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const X509 *,int) | | X509_get_ext | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const X509_ACERT *,int) | | X509_ACERT_get_attr | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const X509_CRL *,int) | | X509_CRL_get_ext | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const X509_NAME *,int) | | X509_NAME_get_entry | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const X509_POLICY_LEVEL *,int) | | X509_policy_level_get0_node | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const X509_POLICY_TREE *,int) | | X509_policy_tree_get0_level | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const X509_REQ *,int) | | X509_REQ_get_attr | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const X509_REVOKED *,int) | | X509_REVOKED_get_ext | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const X509_STORE *,int) | | X509_STORE_get_ex_data | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const X509_STORE_CTX *,int) | | X509_STORE_CTX_get_ex_data | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const XCHAR *,int) | CStringT | CStringT | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const YCHAR *,int) | CStringT | CStringT | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const char *,int) | | DH_meth_new | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const char *,int) | | DSA_meth_new | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const char *,int) | | Jim_StrDupLen | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const char *,int) | | NETSCAPE_SPKI_b64_decode | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const char *,int) | | RSA_meth_new | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const char *,int) | | ftok | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const char *,int) | | gethostbyname2 | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const char *,int) | | parse_yesno | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const char *,int) | | res_gethostbyname2 | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const stack_st_X509_ATTRIBUTE *,int) | | X509at_get_attr | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const stack_st_X509_EXTENSION *,int) | | X509v3_get_ext | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const unsigned char *,int) | | Jim_GenHashFunction | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const unsigned char *,int) | | OPENSSL_uni2asc | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const unsigned char *,int) | | OPENSSL_uni2utf8 | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (const void *,int) | | inet6_rth_getaddr | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (double,int) | | __ldexp | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (double,int) | | __scalbn | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (double[],int) | | getloadavg | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (dynhds *,int) | | Curl_dynhds_set_opts | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (fexcept_t *,int) | | fegetexceptflag | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (float,int) | | __ldexpf | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (float,int) | | __scalbnf | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (gzFile,int) | | gzflush | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (gzFile,int) | | gzputc | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (int *,int) | | X509_PURPOSE_set | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (int *,int) | | X509_TRUST_set | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (int *,int) | | __lll_unlock_elision | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (int,int) | | BN_security_bits | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (int,int) | | EVP_MD_meth_new | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (int,int) | | EVP_PKEY_meth_new | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (int,int) | | __isctype | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (int,int) | | acttab_alloc | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (int,int) | | div | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (int,int) | | inet6_rth_space | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (long double,int) | | __ldexpl | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (netlink_handle *,int) | | __netlink_request | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (nghttp2_option *,int) | | nghttp2_option_set_no_auto_ping_ack | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (nghttp2_option *,int) | | nghttp2_option_set_no_auto_window_update | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (nghttp2_option *,int) | | nghttp2_option_set_no_closed_streams | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (nghttp2_option *,int) | | nghttp2_option_set_no_http_messaging | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (nghttp2_option *,int) | | nghttp2_option_set_no_recv_client_magic | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (nghttp2_option *,int) | | nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (nghttp2_option *,int) | | nghttp2_option_set_server_fallback_rfc7540_priorities | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (ns_msg,int) | | ns_msg_getflag | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (obstack *,int) | | _obstack_newchunk | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (posix_spawnattr_t *,int) | | posix_spawnattr_setcgroup_np | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (posix_spawnattr_t *,int) | | posix_spawnattr_setschedpolicy | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (pthread_attr_t *,int) | | __pthread_attr_setschedpolicy | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (pthread_barrierattr_t *,int) | | __pthread_barrierattr_setpshared | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (pthread_mutexattr_t *,int) | | ___pthread_mutexattr_settype | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (pthread_mutexattr_t *,int) | | __pthread_mutexattr_setprioceiling | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (pthread_mutexattr_t *,int) | | __pthread_mutexattr_setprotocol | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (pthread_rwlockattr_t *,int) | | __pthread_rwlockattr_setkind_np | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (pthread_rwlockattr_t *,int) | | __pthread_rwlockattr_setpshared | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (rule *,int) | | Configlist_add | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (rule *,int) | | Configlist_addbasis | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (sigset_t *,int) | | sigaddset | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (sigset_t *,int) | | sigdelset | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (sqlite3 *,int) | | sqlite3_busy_timeout | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (sqlite3 *,int) | | sqlite3_db_name | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (sqlite3 *,int) | | sqlite3_wal_autocheckpoint | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (sqlite3_backup *,int) | | sqlite3_backup_step | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (sqlite3_context *,int) | | sqlite3_aggregate_context | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (sqlite3_context *,int) | | sqlite3_result_error_code | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (sqlite3_index_info *,int) | | sqlite3_vtab_collation | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (sqlite3_stmt *,int) | | sqlite3_bind_parameter_name | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (sqlite3_stmt *,int) | | sqlite3_column_blob | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (sqlite3_stmt *,int) | | sqlite3_column_bytes | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (sqlite3_stmt *,int) | | sqlite3_column_bytes16 | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (sqlite3_stmt *,int) | | sqlite3_column_decltype | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (sqlite3_stmt *,int) | | sqlite3_column_decltype16 | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (sqlite3_stmt *,int) | | sqlite3_column_double | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (sqlite3_stmt *,int) | | sqlite3_column_int | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (sqlite3_stmt *,int) | | sqlite3_column_int64 | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (sqlite3_stmt *,int) | | sqlite3_column_name | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (sqlite3_stmt *,int) | | sqlite3_column_name16 | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (sqlite3_stmt *,int) | | sqlite3_column_text | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (sqlite3_stmt *,int) | | sqlite3_column_text16 | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (sqlite3_stmt *,int) | | sqlite3_column_type | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (sqlite3_stmt *,int) | | sqlite3_column_value | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (sqlite3_stmt *,int) | | sqlite3_stmt_explain | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (stack_st_PKCS7 *,int) | | PKCS12_add_safes | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (stack_st_SSL_COMP *,int) | | ssl3_comp_find | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (stack_st_X509_ATTRIBUTE *,int) | | X509at_delete_attr | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (stack_st_X509_EXTENSION *,int) | | X509v3_delete_ext | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (timespec *,int) | | __timespec_get | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (timespec *,int) | | __timespec_getres | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (uint16_t,int) | | tls1_group_id2nid | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (unsigned char *,int) | | RAND_bytes | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (unsigned char *,int) | | RAND_priv_bytes | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (unsigned char *,int) | | ossl_ipaddr_to_asc | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (unsigned short,int) | | dtls1_get_queue_priority | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (uv_env_item_t *,int) | | uv_os_free_environ | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (void *,int) | | DSO_dsobyaddr | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (void *,int) | | sqlite3_realloc | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (void *const *,int) | | __backtrace_symbols | 1 |
+| thread.cpp:18:6:18:22 | thread_function_3 | (wchar_t,int) | CStringT | CStringT | 1 |
| vector.cpp:13:6:13:9 | sink | (int) | | ASN1_STRING_type_new | 0 |
| vector.cpp:13:6:13:9 | sink | (int) | | ASN1_tag2bit | 0 |
| vector.cpp:13:6:13:9 | sink | (int) | | ASN1_tag2str | 0 |
@@ -46491,6 +46931,16 @@ getParameterTypeName
| stl.h:678:33:678:38 | format | 1 | func:0 && |
| stl.h:683:6:683:48 | same_signature_as_format_but_different_name | 0 | format_string |
| stl.h:683:6:683:48 | same_signature_as_format_but_different_name | 1 | func:0 && |
+| stl.h:687:8:687:8 | operator= | 0 | const thread & |
+| stl.h:687:8:687:8 | thread | 0 | const thread & |
+| stl.h:690:12:690:17 | thread | 0 | func:0 && |
+| stl.h:690:12:690:17 | thread | 0 | func:0 && |
+| stl.h:690:12:690:17 | thread | 0 | func:0 && |
+| stl.h:690:12:690:17 | thread | 0 | func:0 && |
+| stl.h:690:12:690:17 | thread | 1 | func:1 && |
+| stl.h:690:12:690:17 | thread | 1 | func:1 && |
+| stl.h:690:12:690:17 | thread | 1 | func:1 && |
+| stl.h:690:12:690:17 | thread | 1 | func:1 && |
| string.cpp:17:6:17:9 | sink | 0 | const char * |
| string.cpp:18:6:18:9 | sink | 0 | const string & |
| string.cpp:19:6:19:9 | sink | 0 | const char * |
@@ -46741,6 +47191,18 @@ getParameterTypeName
| taint.cpp:817:6:817:27 | write_to_const_ptr_ptr | 1 | const char ** |
| taint.cpp:822:6:822:19 | take_const_ptr | 0 | const char * |
| taint.cpp:822:6:822:19 | take_const_ptr | 1 | const char * |
+| thread.cpp:4:6:4:9 | sink | 0 | int |
+| thread.cpp:6:8:6:8 | operator= | 0 | S && |
+| thread.cpp:6:8:6:8 | operator= | 0 | const S & |
+| thread.cpp:10:6:10:22 | thread_function_1 | 0 | S * |
+| thread.cpp:14:6:14:22 | thread_function_2 | 0 | S |
+| thread.cpp:18:6:18:22 | thread_function_3 | 0 | S * |
+| thread.cpp:18:6:18:22 | thread_function_3 | 1 | int |
+| thread.cpp:30:18:30:18 | (unnamed constructor) | 0 | const lambda [] type at line 762, col. 18 & |
+| thread.cpp:30:18:30:18 | (unnamed constructor) | 0 | lambda [] type at line 762, col. 18 && |
+| thread.cpp:30:18:30:18 | operator= | 0 | const lambda [] type at line 762, col. 18 & |
+| thread.cpp:30:20:30:20 | _FUN | 0 | S * |
+| thread.cpp:30:20:30:20 | operator() | 0 | S * |
| vector.cpp:13:6:13:9 | sink | 0 | int |
| vector.cpp:14:27:14:30 | sink | 0 | vector> & |
| vector.cpp:14:27:14:30 | sink | 0 | vector> & |
diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/thread.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/thread.cpp
new file mode 100644
index 00000000000..5a39669d1c6
--- /dev/null
+++ b/cpp/ql/test/library-tests/dataflow/taint-tests/thread.cpp
@@ -0,0 +1,33 @@
+#include "stl.h"
+
+int source();
+void sink(int);
+
+struct S {
+ int x;
+};
+
+void thread_function_1(S* s) {
+ sink(s->x); // $ ir
+}
+
+void thread_function_2(S s) {
+ sink(s.x); // $ ir
+}
+
+void thread_function_3(S* s, int y) {
+ sink(s->x); // $ ir
+ sink(y); // clean
+}
+
+void test_thread() {
+ S s;
+ s.x = source();
+ std::thread t1(thread_function_1, &s);
+ std::thread t2(thread_function_2, s);
+ std::thread t3(thread_function_3, &s, 42);
+
+ std::thread t4([](S* p) {
+ sink(p->x); // $ ir
+ }, &s);
+}
\ No newline at end of file
diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected
index a530c429072..a3ee6b46bd5 100644
--- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected
+++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected
@@ -24436,6 +24436,107 @@ ir.cpp:
# 2742| Type = [IntType] int
# 2742| ValueCategory = prvalue
# 2743| getStmt(14): [ReturnStmt] return ...
+# 2747| [CopyAssignmentOperator] std::strong_ordering& std::strong_ordering::operator=(std::strong_ordering const&)
+# 2747| :
+#-----| getParameter(0): [Parameter] (unnamed parameter 0)
+#-----| Type = [LValueReferenceType] const strong_ordering &
+# 2747| [MoveAssignmentOperator] std::strong_ordering& std::strong_ordering::operator=(std::strong_ordering&&)
+# 2747| :
+#-----| getParameter(0): [Parameter] (unnamed parameter 0)
+#-----| Type = [RValueReferenceType] strong_ordering &&
+# 2747| [CopyConstructor] void std::strong_ordering::strong_ordering(std::strong_ordering const&)
+# 2747| :
+#-----| getParameter(0): [Parameter] (unnamed parameter 0)
+#-----| Type = [LValueReferenceType] const strong_ordering &
+# 2747| [MoveConstructor] void std::strong_ordering::strong_ordering(std::strong_ordering&&)
+# 2747| :
+#-----| getParameter(0): [Parameter] (unnamed parameter 0)
+#-----| Type = [RValueReferenceType] strong_ordering &&
+# 2747| :
+# 2747| getEntryPoint(): [BlockStmt] { ... }
+# 2747| getStmt(0): [ReturnStmt] return ...
+# 2748| [Constructor] void std::strong_ordering::strong_ordering(std::_Order)
+# 2748| :
+# 2748| getParameter(0): [Parameter] v
+# 2748| Type = [ScopedEnum] _Order
+# 2748| :
+# 2748| getEntryPoint(): [BlockStmt] { ... }
+# 2748| getStmt(0): [ReturnStmt] return ...
+# 2763| [CopyAssignmentOperator] ThreeWay& ThreeWay::operator=(ThreeWay const&)
+# 2763| :
+#-----| getParameter(0): [Parameter] (unnamed parameter 0)
+#-----| Type = [LValueReferenceType] const ThreeWay &
+# 2763| [MoveAssignmentOperator] ThreeWay& ThreeWay::operator=(ThreeWay&&)
+# 2763| :
+#-----| getParameter(0): [Parameter] (unnamed parameter 0)
+#-----| Type = [RValueReferenceType] ThreeWay &&
+# 2763| [Constructor] void ThreeWay::ThreeWay()
+# 2763| :
+# 2766| [MemberFunction] std::strong_ordering ThreeWay::operator<=>(ThreeWay&)
+# 2766| :
+# 2766| getParameter(0): [Parameter] y
+# 2766| Type = [LValueReferenceType] ThreeWay &
+# 2766| getEntryPoint(): [BlockStmt] { ... }
+# 2766| getStmt(0): [ReturnStmt] return ...
+# 2766| getExpr(): [SpaceshipExpr] ... <=> ...
+# 2766| Type = [Class] strong_ordering
+# 2766| ValueCategory = prvalue
+# 2766| getChild(0): [PointerFieldAccess] x
+# 2766| Type = [IntType] int
+# 2766| ValueCategory = prvalue(load)
+# 2766| getQualifier(): [ThisExpr] this
+# 2766| Type = [PointerType] ThreeWay *
+# 2766| ValueCategory = prvalue(load)
+# 2766| getChild(1): [ReferenceFieldAccess] x
+# 2766| Type = [IntType] int
+# 2766| ValueCategory = prvalue(load)
+# 2766| getQualifier(): [VariableAccess] y
+# 2766| Type = [LValueReferenceType] ThreeWay &
+# 2766| ValueCategory = prvalue(load)
+# 2766| getQualifier().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
+# 2766| Type = [Class] ThreeWay
+# 2766| ValueCategory = lvalue
+# 2769| [TopLevelFunction] void test_three_way(int, int, ThreeWay, ThreeWay)
+# 2769| :
+# 2769| getParameter(0): [Parameter] a
+# 2769| Type = [IntType] int
+# 2769| getParameter(1): [Parameter] b
+# 2769| Type = [IntType] int
+# 2769| getParameter(2): [Parameter] c
+# 2769| Type = [Class] ThreeWay
+# 2769| getParameter(3): [Parameter] d
+# 2769| Type = [Class] ThreeWay
+# 2769| getEntryPoint(): [BlockStmt] { ... }
+# 2770| getStmt(0): [DeclStmt] declaration
+# 2770| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
+# 2770| Type = [Class] strong_ordering
+# 2770| getVariable().getInitializer(): [Initializer] initializer for x
+# 2770| getExpr(): [SpaceshipExpr] ... <=> ...
+# 2770| Type = [Class] strong_ordering
+# 2770| ValueCategory = prvalue
+# 2770| getChild(0): [VariableAccess] a
+# 2770| Type = [IntType] int
+# 2770| ValueCategory = prvalue(load)
+# 2770| getChild(1): [VariableAccess] b
+# 2770| Type = [IntType] int
+# 2770| ValueCategory = prvalue(load)
+# 2771| getStmt(1): [DeclStmt] declaration
+# 2771| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y
+# 2771| Type = [Class] strong_ordering
+# 2771| getVariable().getInitializer(): [Initializer] initializer for y
+# 2771| getExpr(): [FunctionCall] call to operator<=>
+# 2771| Type = [Class] strong_ordering
+# 2771| ValueCategory = prvalue
+# 2771| getQualifier(): [VariableAccess] c
+# 2771| Type = [Class] ThreeWay
+# 2771| ValueCategory = lvalue
+# 2771| getArgument(0): [VariableAccess] d
+# 2771| Type = [Class] ThreeWay
+# 2771| ValueCategory = lvalue
+# 2771| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
+# 2771| Type = [LValueReferenceType] ThreeWay &
+# 2771| ValueCategory = prvalue
+# 2772| getStmt(2): [ReturnStmt] return ...
ir23.cpp:
# 1| [TopLevelFunction] bool consteval_1()
# 1| :
@@ -50174,3 +50275,42 @@ try_except.cpp:
# 52| Type = [IntType] int
# 52| ValueCategory = prvalue(load)
# 54| getStmt(2): [ReturnStmt] return ...
+type_info_test.cpp:
+# 3| [TopLevelFunction] void type_info_test(int)
+# 3| :
+# 3| getParameter(0): [Parameter] x
+# 3| Type = [IntType] int
+# 3| getEntryPoint(): [BlockStmt] { ... }
+# 4| getStmt(0): [DeclStmt] declaration
+# 4| getDeclarationEntry(0): [VariableDeclarationEntry] definition of t1
+# 4| Type = [LValueReferenceType] const type_info &
+# 4| getVariable().getInitializer(): [Initializer] initializer for t1
+# 4| getExpr(): [TypeidOperator] typeid ...
+# 4| Type = [SpecifiedType] const type_info
+# 4| ValueCategory = lvalue
+# 4| getExpr(): [VariableAccess] x
+# 4| Type = [IntType] int
+# 4| ValueCategory = lvalue
+# 4| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
+# 4| Type = [LValueReferenceType] const type_info &
+# 4| ValueCategory = prvalue
+# 5| getStmt(1): [DeclStmt] declaration
+# 5| getDeclarationEntry(0): [VariableDeclarationEntry] definition of t2
+# 5| Type = [LValueReferenceType] const type_info &
+# 5| getVariable().getInitializer(): [Initializer] initializer for t2
+# 5| getExpr(): [TypeidOperator] typeid ...
+# 5| Type = [SpecifiedType] const type_info
+# 5| ValueCategory = lvalue
+# 5| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
+# 5| Type = [LValueReferenceType] const type_info &
+# 5| ValueCategory = prvalue
+# 6| getStmt(2): [ReturnStmt] return ...
+typeinfo:
+# 4| [CopyAssignmentOperator] std::type_info& std::type_info::operator=(std::type_info const&)
+# 4| :
+#-----| getParameter(0): [Parameter] (unnamed parameter 0)
+#-----| Type = [LValueReferenceType] const type_info &
+# 4| [MoveAssignmentOperator] std::type_info& std::type_info::operator=(std::type_info&&)
+# 4| :
+#-----| getParameter(0): [Parameter] (unnamed parameter 0)
+#-----| Type = [RValueReferenceType] type_info &&
diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected
index 4f1d1abb4ec..6d58656b55f 100644
--- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected
+++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected
@@ -20273,6 +20273,119 @@ ir.cpp:
# 2728| v2728_14(void) = AliasedUse : ~m2728_9
# 2728| v2728_15(void) = ExitFunction :
+# 2747| void std::strong_ordering::strong_ordering(std::strong_ordering&&)
+# 2747| Block 0
+# 2747| v2747_1(void) = EnterFunction :
+# 2747| m2747_2(unknown) = AliasedDefinition :
+# 2747| m2747_3(unknown) = InitializeNonLocal :
+# 2747| m2747_4(unknown) = Chi : total:m2747_2, partial:m2747_3
+# 2747| r2747_5(glval) = VariableAddress[#this] :
+# 2747| m2747_6(glval) = InitializeParameter[#this] : &:r2747_5
+# 2747| r2747_7(glval) = Load[#this] : &:r2747_5, m2747_6
+# 2747| m2747_8(strong_ordering) = InitializeIndirection[#this] : &:r2747_7
+#-----| r0_1(glval) = VariableAddress[(unnamed parameter 0)] :
+#-----| m0_2(strong_ordering &&) = InitializeParameter[(unnamed parameter 0)] : &:r0_1
+#-----| r0_3(strong_ordering &&) = Load[(unnamed parameter 0)] : &:r0_1, m0_2
+#-----| m0_4(unknown) = InitializeIndirection[(unnamed parameter 0)] : &:r0_3
+# 2747| v2747_9(void) = NoOp :
+# 2747| v2747_10(void) = ReturnIndirection[#this] : &:r2747_7, m2747_8
+#-----| v0_5(void) = ReturnIndirection[(unnamed parameter 0)] : &:r0_3, m0_4
+# 2747| v2747_11(void) = ReturnVoid :
+# 2747| v2747_12(void) = AliasedUse : m2747_3
+# 2747| v2747_13(void) = ExitFunction :
+
+# 2748| void std::strong_ordering::strong_ordering(std::_Order)
+# 2748| Block 0
+# 2748| v2748_1(void) = EnterFunction :
+# 2748| m2748_2(unknown) = AliasedDefinition :
+# 2748| m2748_3(unknown) = InitializeNonLocal :
+# 2748| m2748_4(unknown) = Chi : total:m2748_2, partial:m2748_3
+# 2748| r2748_5(glval) = VariableAddress[#this] :
+# 2748| m2748_6(glval) = InitializeParameter[#this] : &:r2748_5
+# 2748| r2748_7(glval) = Load[#this] : &:r2748_5, m2748_6
+# 2748| m2748_8(strong_ordering) = InitializeIndirection[#this] : &:r2748_7
+# 2748| r2748_9(glval<_Order>) = VariableAddress[v] :
+# 2748| m2748_10(_Order) = InitializeParameter[v] : &:r2748_9
+# 2748| v2748_11(void) = NoOp :
+# 2748| v2748_12(void) = ReturnIndirection[#this] : &:r2748_7, m2748_8
+# 2748| v2748_13(void) = ReturnVoid :
+# 2748| v2748_14(void) = AliasedUse : m2748_3
+# 2748| v2748_15(void) = ExitFunction :
+
+# 2766| std::strong_ordering ThreeWay::operator<=>(ThreeWay&)
+# 2766| Block 0
+# 2766| v2766_1(void) = EnterFunction :
+# 2766| m2766_2(unknown) = AliasedDefinition :
+# 2766| m2766_3(unknown) = InitializeNonLocal :
+# 2766| m2766_4(unknown) = Chi : total:m2766_2, partial:m2766_3
+# 2766| r2766_5(glval) = VariableAddress[#this] :
+# 2766| m2766_6(glval) = InitializeParameter[#this] : &:r2766_5
+# 2766| r2766_7(glval) = Load[#this] : &:r2766_5, m2766_6
+# 2766| m2766_8(ThreeWay) = InitializeIndirection[#this] : &:r2766_7
+# 2766| r2766_9(glval) = VariableAddress[y] :
+# 2766| m2766_10(ThreeWay &) = InitializeParameter[y] : &:r2766_9
+# 2766| r2766_11(ThreeWay &) = Load[y] : &:r2766_9, m2766_10
+# 2766| m2766_12(unknown) = InitializeIndirection[y] : &:r2766_11
+# 2766| r2766_13(glval) = VariableAddress[#return] :
+# 2766| r2766_14(glval) = VariableAddress[#this] :
+# 2766| r2766_15(ThreeWay *) = Load[#this] : &:r2766_14, m2766_6
+# 2766| r2766_16(glval) = FieldAddress[x] : r2766_15
+# 2766| r2766_17(int) = Load[?] : &:r2766_16, ~m2766_8
+# 2766| r2766_18(glval) = VariableAddress[y] :
+# 2766| r2766_19(ThreeWay &) = Load[y] : &:r2766_18, m2766_10
+# 2766| r2766_20(glval) = CopyValue : r2766_19
+# 2766| r2766_21(glval) = FieldAddress[x] : r2766_20
+# 2766| r2766_22(int) = Load[?] : &:r2766_21, ~m2766_12
+# 2766| r2766_23(strong_ordering) = Spaceship : r2766_17, r2766_22
+# 2766| m2766_24(strong_ordering) = Store[#return] : &:r2766_13, r2766_23
+# 2766| v2766_25(void) = ReturnIndirection[#this] : &:r2766_7, m2766_8
+# 2766| v2766_26(void) = ReturnIndirection[y] : &:r2766_11, m2766_12
+# 2766| r2766_27(glval) = VariableAddress[#return] :
+# 2766| v2766_28(void) = ReturnValue : &:r2766_27, m2766_24
+# 2766| v2766_29(void) = AliasedUse : m2766_3
+# 2766| v2766_30(void) = ExitFunction :
+
+# 2769| void test_three_way(int, int, ThreeWay, ThreeWay)
+# 2769| Block 0
+# 2769| v2769_1(void) = EnterFunction :
+# 2769| m2769_2(unknown) = AliasedDefinition :
+# 2769| m2769_3(unknown) = InitializeNonLocal :
+# 2769| m2769_4(unknown) = Chi : total:m2769_2, partial:m2769_3
+# 2769| r2769_5(glval) = VariableAddress[a] :
+# 2769| m2769_6(int) = InitializeParameter[a] : &:r2769_5
+# 2769| r2769_7(glval) = VariableAddress[b] :
+# 2769| m2769_8(int) = InitializeParameter[b] : &:r2769_7
+# 2769| r2769_9(glval) = VariableAddress[c] :
+# 2769| m2769_10(ThreeWay) = InitializeParameter[c] : &:r2769_9
+# 2769| r2769_11(glval) = VariableAddress[d] :
+# 2769| m2769_12(ThreeWay) = InitializeParameter[d] : &:r2769_11
+# 2770| r2770_1(glval) = VariableAddress[x] :
+# 2770| r2770_2(glval) = VariableAddress[a] :
+# 2770| r2770_3(int) = Load[a] : &:r2770_2, m2769_6
+# 2770| r2770_4(glval) = VariableAddress[b] :
+# 2770| r2770_5(int) = Load[b] : &:r2770_4, m2769_8
+# 2770| r2770_6(strong_ordering) = Spaceship : r2770_3, r2770_5
+# 2770| m2770_7(strong_ordering) = Store[x] : &:r2770_1, r2770_6
+# 2771| r2771_1(glval) = VariableAddress[y] :
+# 2771| r2771_2(glval) = VariableAddress[c] :
+# 2771| r2771_3(glval) = FunctionAddress[operator<=>] :
+# 2771| r2771_4(glval) = VariableAddress[d] :
+# 2771| r2771_5(ThreeWay &) = CopyValue : r2771_4
+# 2771| r2771_6(strong_ordering) = Call[operator<=>] : func:r2771_3, this:r2771_2, 0:r2771_5
+# 2771| m2771_7(unknown) = ^CallSideEffect : ~m2769_4
+# 2771| m2771_8(unknown) = Chi : total:m2769_4, partial:m2771_7
+# 2771| v2771_9(void) = ^IndirectReadSideEffect[-1] : &:r2771_2, m2769_10
+# 2771| v2771_10(void) = ^BufferReadSideEffect[0] : &:r2771_5, ~m2769_12
+# 2771| m2771_11(ThreeWay) = ^IndirectMayWriteSideEffect[-1] : &:r2771_2
+# 2771| m2771_12(ThreeWay) = Chi : total:m2769_10, partial:m2771_11
+# 2771| m2771_13(unknown) = ^BufferMayWriteSideEffect[0] : &:r2771_5
+# 2771| m2771_14(ThreeWay) = Chi : total:m2769_12, partial:m2771_13
+# 2771| m2771_15(strong_ordering) = Store[y] : &:r2771_1, r2771_6
+# 2772| v2772_1(void) = NoOp :
+# 2769| v2769_13(void) = ReturnVoid :
+# 2769| v2769_14(void) = AliasedUse : ~m2771_8
+# 2769| v2769_15(void) = ExitFunction :
+
ir23.cpp:
# 1| bool consteval_1()
# 1| Block 0
@@ -39973,3 +40086,27 @@ try_except.cpp:
# 44| Block 7
# 44| v44_10(void) = Unreached :
+
+type_info_test.cpp:
+# 3| void type_info_test(int)
+# 3| Block 0
+# 3| v3_1(void) = EnterFunction :
+# 3| m3_2(unknown) = AliasedDefinition :
+# 3| m3_3(unknown) = InitializeNonLocal :
+# 3| m3_4(unknown) = Chi : total:m3_2, partial:m3_3
+# 3| r3_5(glval) = VariableAddress[x] :
+# 3| m3_6(int) = InitializeParameter[x] : &:r3_5
+# 3| m3_7(unknown) = Chi : total:m3_4, partial:m3_6
+# 4| r4_1(glval) = VariableAddress[t1] :
+# 4| r4_2(glval) = VariableAddress[x] :
+# 4| r4_3(glval) = TypeidExpr : r4_2
+# 4| r4_4(type_info &) = CopyValue : r4_3
+# 4| m4_5(type_info &) = Store[t1] : &:r4_1, r4_4
+# 5| r5_1(glval) = VariableAddress[t2] :
+# 5| r5_2(glval) = TypeidType :
+# 5| r5_3(type_info &) = CopyValue : r5_2
+# 5| m5_4(type_info &) = Store[t2] : &:r5_1, r5_3
+# 6| v6_1(void) = NoOp :
+# 3| v3_8(void) = ReturnVoid :
+# 3| v3_9(void) = AliasedUse : m3_3
+# 3| v3_10(void) = ExitFunction :
diff --git a/cpp/ql/test/library-tests/ir/ir/ir.cpp b/cpp/ql/test/library-tests/ir/ir/ir.cpp
index 92566968e6e..74c41c7e916 100644
--- a/cpp/ql/test/library-tests/ir/ir/ir.cpp
+++ b/cpp/ql/test/library-tests/ir/ir/ir.cpp
@@ -2742,4 +2742,33 @@ void test_postfix_crement(int *p, int q) {
int q2 = (int)(q++);
}
+namespace std {
+ enum class _Order : signed char { __less = -1, __equiv = 0, __greater = 1 };
+ class strong_ordering {
+ explicit constexpr strong_ordering(_Order v) {}
+
+ public:
+ static const strong_ordering less;
+ static const strong_ordering equal;
+ static const strong_ordering equivalent;
+ static const strong_ordering greater;
+ };
+
+ inline constexpr strong_ordering strong_ordering::less(_Order::__less);
+ inline constexpr strong_ordering strong_ordering::equal(_Order::__equiv);
+ inline constexpr strong_ordering strong_ordering::equivalent(_Order::__equiv);
+ inline constexpr strong_ordering strong_ordering::greater(_Order::__greater);
+}
+
+class ThreeWay {
+ int x;
+public:
+ std::strong_ordering operator<=>(ThreeWay &y) { return this->x <=> y.x; }
+};
+
+void test_three_way(int a, int b, ThreeWay c, ThreeWay d) {
+ auto x = a <=> b;
+ auto y = c <=> d;
+}
+
// semmle-extractor-options: -std=c++20 --clang
diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected
index 937695c13ae..8cdb5e8c351 100644
--- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected
+++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected
@@ -18432,6 +18432,112 @@ ir.cpp:
# 2728| v2728_12(void) = AliasedUse : ~m?
# 2728| v2728_13(void) = ExitFunction :
+# 2747| void std::strong_ordering::strong_ordering(std::strong_ordering&&)
+# 2747| Block 0
+# 2747| v2747_1(void) = EnterFunction :
+# 2747| mu2747_2(unknown) = AliasedDefinition :
+# 2747| mu2747_3(unknown) = InitializeNonLocal :
+# 2747| r2747_4(glval) = VariableAddress[#this] :
+# 2747| mu2747_5(glval) = InitializeParameter[#this] : &:r2747_4
+# 2747| r2747_6(glval) = Load[#this] : &:r2747_4, ~m?
+# 2747| mu2747_7(strong_ordering) = InitializeIndirection[#this] : &:r2747_6
+#-----| r0_1(glval) = VariableAddress[(unnamed parameter 0)] :
+#-----| mu0_2(strong_ordering &&) = InitializeParameter[(unnamed parameter 0)] : &:r0_1
+#-----| r0_3(strong_ordering &&) = Load[(unnamed parameter 0)] : &:r0_1, ~m?
+#-----| mu0_4(unknown) = InitializeIndirection[(unnamed parameter 0)] : &:r0_3
+# 2747| v2747_8(void) = NoOp :
+# 2747| v2747_9(void) = ReturnIndirection[#this] : &:r2747_6, ~m?
+#-----| v0_5(void) = ReturnIndirection[(unnamed parameter 0)] : &:r0_3, ~m?
+# 2747| v2747_10(void) = ReturnVoid :
+# 2747| v2747_11(void) = AliasedUse : ~m?
+# 2747| v2747_12(void) = ExitFunction :
+
+# 2748| void std::strong_ordering::strong_ordering(std::_Order)
+# 2748| Block 0
+# 2748| v2748_1(void) = EnterFunction :
+# 2748| mu2748_2(unknown) = AliasedDefinition :
+# 2748| mu2748_3(unknown) = InitializeNonLocal :
+# 2748| r2748_4(glval) = VariableAddress[#this] :
+# 2748| mu2748_5(glval) = InitializeParameter[#this] : &:r2748_4
+# 2748| r2748_6(glval) = Load[#this] : &:r2748_4, ~m?
+# 2748| mu2748_7(strong_ordering) = InitializeIndirection[#this] : &:r2748_6
+# 2748| r2748_8(glval<_Order>) = VariableAddress[v] :
+# 2748| mu2748_9(_Order) = InitializeParameter[v] : &:r2748_8
+# 2748| v2748_10(void) = NoOp :
+# 2748| v2748_11(void) = ReturnIndirection[#this] : &:r2748_6, ~m?
+# 2748| v2748_12(void) = ReturnVoid :
+# 2748| v2748_13(void) = AliasedUse : ~m?
+# 2748| v2748_14(void) = ExitFunction :
+
+# 2766| std::strong_ordering ThreeWay::operator<=>(ThreeWay&)
+# 2766| Block 0
+# 2766| v2766_1(void) = EnterFunction :
+# 2766| mu2766_2(unknown) = AliasedDefinition :
+# 2766| mu2766_3(unknown) = InitializeNonLocal :
+# 2766| r2766_4(glval) = VariableAddress[#this] :
+# 2766| mu2766_5(glval) = InitializeParameter[#this] : &:r2766_4
+# 2766| r2766_6(glval) = Load[#this] : &:r2766_4, ~m?
+# 2766| mu2766_7(ThreeWay) = InitializeIndirection[#this] : &:r2766_6
+# 2766| r2766_8(glval) = VariableAddress[y] :
+# 2766| mu2766_9(ThreeWay &) = InitializeParameter[y] : &:r2766_8
+# 2766| r2766_10(ThreeWay &) = Load[y] : &:r2766_8, ~m?
+# 2766| mu2766_11(unknown) = InitializeIndirection[y] : &:r2766_10
+# 2766| r2766_12(glval) = VariableAddress[#return] :
+# 2766| r2766_13(glval) = VariableAddress[#this] :
+# 2766| r2766_14(ThreeWay *) = Load[#this] : &:r2766_13, ~m?
+# 2766| r2766_15(glval) = FieldAddress[x] : r2766_14
+# 2766| r2766_16(int) = Load[?] : &:r2766_15, ~m?
+# 2766| r2766_17(glval) = VariableAddress[y] :
+# 2766| r2766_18(ThreeWay &) = Load[y] : &:r2766_17, ~m?
+# 2766| r2766_19(glval) = CopyValue : r2766_18
+# 2766| r2766_20(glval) = FieldAddress[x] : r2766_19
+# 2766| r2766_21(int) = Load[?] : &:r2766_20, ~m?
+# 2766| r2766_22(strong_ordering) = Spaceship : r2766_16, r2766_21
+# 2766| mu2766_23(strong_ordering) = Store[#return] : &:r2766_12, r2766_22
+# 2766| v2766_24(void) = ReturnIndirection[#this] : &:r2766_6, ~m?
+# 2766| v2766_25(void) = ReturnIndirection[y] : &:r2766_10, ~m?
+# 2766| r2766_26(glval) = VariableAddress[#return] :
+# 2766| v2766_27(void) = ReturnValue : &:r2766_26, ~m?
+# 2766| v2766_28(void) = AliasedUse : ~m?
+# 2766| v2766_29(void) = ExitFunction :
+
+# 2769| void test_three_way(int, int, ThreeWay, ThreeWay)
+# 2769| Block 0
+# 2769| v2769_1(void) = EnterFunction :
+# 2769| mu2769_2(unknown) = AliasedDefinition :
+# 2769| mu2769_3(unknown) = InitializeNonLocal :
+# 2769| r2769_4(glval) = VariableAddress[a] :
+# 2769| mu2769_5(int) = InitializeParameter[a] : &:r2769_4
+# 2769| r2769_6(glval) = VariableAddress[b] :
+# 2769| mu2769_7(int) = InitializeParameter[b] : &:r2769_6
+# 2769| r2769_8(glval) = VariableAddress[c] :
+# 2769| mu2769_9(ThreeWay) = InitializeParameter[c] : &:r2769_8
+# 2769| r2769_10(glval) = VariableAddress[d] :
+# 2769| mu2769_11(ThreeWay) = InitializeParameter[d] : &:r2769_10
+# 2770| r2770_1(glval) = VariableAddress[x] :
+# 2770| r2770_2(glval) = VariableAddress[a] :
+# 2770| r2770_3(int) = Load[a] : &:r2770_2, ~m?
+# 2770| r2770_4(glval) = VariableAddress[b] :
+# 2770| r2770_5(int) = Load[b] : &:r2770_4, ~m?
+# 2770| r2770_6(strong_ordering) = Spaceship : r2770_3, r2770_5
+# 2770| mu2770_7(strong_ordering) = Store[x] : &:r2770_1, r2770_6
+# 2771| r2771_1(glval) = VariableAddress[y] :
+# 2771| r2771_2(glval) = VariableAddress[c] :
+# 2771| r2771_3(glval) = FunctionAddress[operator<=>] :
+# 2771| r2771_4(glval) = VariableAddress[d] :
+# 2771| r2771_5(ThreeWay &) = CopyValue : r2771_4
+# 2771| r2771_6(strong_ordering) = Call[operator<=>] : func:r2771_3, this:r2771_2, 0:r2771_5
+# 2771| mu2771_7(unknown) = ^CallSideEffect : ~m?
+# 2771| v2771_8(void) = ^IndirectReadSideEffect[-1] : &:r2771_2, ~m?
+# 2771| v2771_9(void) = ^BufferReadSideEffect[0] : &:r2771_5, ~m?
+# 2771| mu2771_10(ThreeWay) = ^IndirectMayWriteSideEffect[-1] : &:r2771_2
+# 2771| mu2771_11(unknown) = ^BufferMayWriteSideEffect[0] : &:r2771_5
+# 2771| mu2771_12(strong_ordering) = Store[y] : &:r2771_1, r2771_6
+# 2772| v2772_1(void) = NoOp :
+# 2769| v2769_12(void) = ReturnVoid :
+# 2769| v2769_13(void) = AliasedUse : ~m?
+# 2769| v2769_14(void) = ExitFunction :
+
ir23.cpp:
# 1| bool consteval_1()
# 1| Block 0
@@ -38102,3 +38208,25 @@ try_except.cpp:
# 54| v54_1(void) = NoOp :
# 44| v44_9(void) = ReturnVoid :
#-----| Goto -> Block 1
+
+type_info_test.cpp:
+# 3| void type_info_test(int)
+# 3| Block 0
+# 3| v3_1(void) = EnterFunction :
+# 3| mu3_2(unknown) = AliasedDefinition :
+# 3| mu3_3(unknown) = InitializeNonLocal :
+# 3| r3_4(glval) = VariableAddress[x] :
+# 3| mu3_5(int) = InitializeParameter[x] : &:r3_4
+# 4| r4_1(glval) = VariableAddress[t1] :
+# 4| r4_2(glval) = VariableAddress[x] :
+# 4| r4_3(glval) = TypeidExpr : r4_2
+# 4| r4_4(type_info &) = CopyValue : r4_3
+# 4| mu4_5(type_info &) = Store[t1] : &:r4_1, r4_4
+# 5| r5_1(glval) = VariableAddress[t2] :
+# 5| r5_2(glval) = TypeidType :
+# 5| r5_3(type_info &) = CopyValue : r5_2
+# 5| mu5_4(type_info &) = Store[t2] : &:r5_1, r5_3
+# 6| v6_1(void) = NoOp :
+# 3| v3_6(void) = ReturnVoid :
+# 3| v3_7(void) = AliasedUse : ~m?
+# 3| v3_8(void) = ExitFunction :
diff --git a/cpp/ql/test/library-tests/ir/ir/type_info_test.cpp b/cpp/ql/test/library-tests/ir/ir/type_info_test.cpp
new file mode 100644
index 00000000000..b35870aa409
--- /dev/null
+++ b/cpp/ql/test/library-tests/ir/ir/type_info_test.cpp
@@ -0,0 +1,8 @@
+#include
+
+void type_info_test(int x) {
+ const std::type_info &t1 = typeid(x);
+ const std::type_info &t2 = typeid(int);
+}
+
+// semmle-extractor-options: -I.
diff --git a/cpp/ql/test/library-tests/ir/ir/typeinfo b/cpp/ql/test/library-tests/ir/ir/typeinfo
new file mode 100644
index 00000000000..5b14e219f47
--- /dev/null
+++ b/cpp/ql/test/library-tests/ir/ir/typeinfo
@@ -0,0 +1,5 @@
+#pragma once
+
+namespace std{
+ class type_info {};
+}
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/consts/NonConstantFormat.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/consts/NonConstantFormat.expected
index c2a952774ff..b5f6ad602fb 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/consts/NonConstantFormat.expected
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/consts/NonConstantFormat.expected
@@ -1,9 +1,6 @@
edges
-| consts.cpp:24:7:24:9 | **gv1 | consts.cpp:25:2:25:4 | *a | provenance | |
| consts.cpp:24:7:24:9 | **gv1 | consts.cpp:30:9:30:14 | *access to array | provenance | |
| consts.cpp:24:7:24:9 | **gv1 | consts.cpp:123:2:123:12 | *... = ... | provenance | |
-| consts.cpp:25:2:25:4 | *a | consts.cpp:26:2:26:4 | *{...} | provenance | |
-| consts.cpp:26:2:26:4 | *{...} | consts.cpp:24:7:24:9 | **gv1 | provenance | |
| consts.cpp:29:7:29:25 | **nonConstFuncToArray | consts.cpp:126:9:126:30 | *call to nonConstFuncToArray | provenance | |
| consts.cpp:30:9:30:14 | *access to array | consts.cpp:29:7:29:25 | **nonConstFuncToArray | provenance | |
| consts.cpp:85:7:85:8 | gets output argument | consts.cpp:86:9:86:10 | *v1 | provenance | |
@@ -38,8 +35,6 @@ edges
| consts.cpp:144:16:144:18 | readStringRef output argument | consts.cpp:145:9:145:11 | *v12 | provenance | |
nodes
| consts.cpp:24:7:24:9 | **gv1 | semmle.label | **gv1 |
-| consts.cpp:25:2:25:4 | *a | semmle.label | *a |
-| consts.cpp:26:2:26:4 | *{...} | semmle.label | *{...} |
| consts.cpp:29:7:29:25 | **nonConstFuncToArray | semmle.label | **nonConstFuncToArray |
| consts.cpp:30:9:30:14 | *access to array | semmle.label | *access to array |
| consts.cpp:85:7:85:8 | gets output argument | semmle.label | gets output argument |
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-704/WcharCharConversion.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-704/WcharCharConversion.cpp
index dc2b9f4a9c1..22e5ccd958d 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-704/WcharCharConversion.cpp
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-704/WcharCharConversion.cpp
@@ -18,13 +18,13 @@ void Test()
wchar_t *lpWchar = NULL;
LPCSTR lpcstr = "b";
- lpWchar = (LPWSTR)"a"; // BUG
- lpWchar = (LPWSTR)lpcstr; // BUG
+ lpWchar = (LPWSTR)"a"; // $ Alert
+ lpWchar = (LPWSTR)lpcstr; // $ Alert
- lpWchar = (wchar_t*)lpChar; // BUG
+ lpWchar = (wchar_t*)lpChar; // $ Alert
- fconstWChar((LPCWSTR)lpChar); // BUG
- fWChar((LPWSTR)lpChar); // BUG
+ fconstWChar((LPCWSTR)lpChar); // $ Alert
+ fWChar((LPWSTR)lpChar); // $ Alert
lpChar = (LPSTR)"a"; // Valid
lpWchar = (LPWSTR)L"a"; // Valid
@@ -79,33 +79,64 @@ void CheckedConversionFalsePositiveTest3(unsigned short flags, LPTSTR buffer)
if(flags & UNICODE)
lpWchar = (LPWSTR)buffer; // GOOD
else
- lpWchar = (LPWSTR)buffer; // BUG
+ lpWchar = (LPWSTR)buffer; // $ Alert
if((flags & UNICODE) == 0x8)
lpWchar = (LPWSTR)buffer; // GOOD
else
- lpWchar = (LPWSTR)buffer; // BUG
+ lpWchar = (LPWSTR)buffer; // $ Alert
if((flags & UNICODE) != 0x8)
- lpWchar = (LPWSTR)buffer; // BUG
+ lpWchar = (LPWSTR)buffer; // $ Alert
else
lpWchar = (LPWSTR)buffer; // GOOD
// Bad operator precedence
if(flags & UNICODE == 0x8)
- lpWchar = (LPWSTR)buffer; // BUG
+ lpWchar = (LPWSTR)buffer; // $ Alert
else
- lpWchar = (LPWSTR)buffer; // BUG
+ lpWchar = (LPWSTR)buffer; // $ Alert
if((flags & UNICODE) != 0)
lpWchar = (LPWSTR)buffer; // GOOD
else
- lpWchar = (LPWSTR)buffer; // BUG
+ lpWchar = (LPWSTR)buffer; // $ Alert
if((flags & UNICODE) == 0)
- lpWchar = (LPWSTR)buffer; // BUG
+ lpWchar = (LPWSTR)buffer; // $ Alert
else
lpWchar = (LPWSTR)buffer; // GOOD
- lpWchar = (LPWSTR)buffer; // BUG
+ lpWchar = (LPWSTR)buffer; // $ Alert
+}
+
+typedef unsigned long long size_t;
+
+size_t wcslen(const wchar_t *str);
+size_t strlen(const char* str);
+
+template
+size_t str_len(const C *str) {
+ if (sizeof(C) != 1) {
+ return wcslen((const wchar_t *)str); // GOOD -- unreachable code
+ }
+
+ return strlen((const char *)str);
+}
+
+template
+size_t wrong_str_len(const C *str) {
+ if (sizeof(C) == 1) {
+ return wcslen((const wchar_t *)str); // $ Alert
+ }
+
+ return strlen((const char *)str);
+}
+
+void test_str_len(const wchar_t *wstr, const char *str) {
+ size_t len =
+ str_len(wstr) +
+ str_len(str) +
+ wrong_str_len(wstr) +
+ wrong_str_len(str);
}
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-704/WcharCharConversion.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-704/WcharCharConversion.expected
index 9b34966aa87..bb56396c08c 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-704/WcharCharConversion.expected
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-704/WcharCharConversion.expected
@@ -11,3 +11,4 @@
| WcharCharConversion.cpp:103:21:103:26 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:106:21:106:26 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:110:20:110:25 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
+| WcharCharConversion.cpp:130:34:130:36 | str | Conversion from const char * to const wchar_t *. Use of invalid string can lead to undefined behavior. |
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-704/WcharCharConversion.qlref b/cpp/ql/test/query-tests/Security/CWE/CWE-704/WcharCharConversion.qlref
index 4e3b6775188..5aa0107d1f9 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-704/WcharCharConversion.qlref
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-704/WcharCharConversion.qlref
@@ -1 +1,2 @@
-Security/CWE/CWE-704/WcharCharConversion.ql
\ No newline at end of file
+query: Security/CWE/CWE-704/WcharCharConversion.ql
+postprocess: utils/test/InlineExpectationsTestQuery.ql
diff --git a/csharp/ql/lib/change-notes/2025-06-10-getasupertype.md b/csharp/ql/lib/change-notes/2025-06-10-getasupertype.md
new file mode 100644
index 00000000000..14b086a9409
--- /dev/null
+++ b/csharp/ql/lib/change-notes/2025-06-10-getasupertype.md
@@ -0,0 +1,4 @@
+---
+category: feature
+---
+* Added a new predicate, `getASuperType()`, to get a direct supertype of this type.
diff --git a/csharp/ql/lib/ext/System.IO.model.yml b/csharp/ql/lib/ext/System.IO.model.yml
index dcc9c70551b..0b8b52d9e8a 100644
--- a/csharp/ql/lib/ext/System.IO.model.yml
+++ b/csharp/ql/lib/ext/System.IO.model.yml
@@ -47,7 +47,7 @@ extensions:
- ["System.IO", "FileStream", False, "FileStream", "(System.String,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare,System.Int32)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
- ["System.IO", "FileStream", False, "FileStream", "(System.String,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare,System.Int32,System.Boolean)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
- ["System.IO", "FileStream", False, "FileStream", "(System.String,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare,System.Int32,System.IO.FileOptions)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
- - ["System.IO", "MemoryStream", False, "MemoryStream", "(System.Byte[])", "", "Argument[0]", "Argument[this]", "taint", "manual"]
+ - ["System.IO", "MemoryStream", False, "MemoryStream", "(System.Byte[])", "", "Argument[0].Element", "Argument[this]", "taint", "manual"]
- ["System.IO", "MemoryStream", False, "MemoryStream", "(System.Byte[],System.Boolean)", "", "Argument[0].Element", "Argument[this]", "taint", "manual"]
- ["System.IO", "MemoryStream", False, "MemoryStream", "(System.Byte[],System.Int32,System.Int32)", "", "Argument[0].Element", "Argument[this]", "taint", "manual"]
- ["System.IO", "MemoryStream", False, "MemoryStream", "(System.Byte[],System.Int32,System.Int32,System.Boolean)", "", "Argument[0].Element", "Argument[this]", "taint", "manual"]
diff --git a/csharp/ql/lib/ext/System.Runtime.Serialization.model.yml b/csharp/ql/lib/ext/System.Runtime.Serialization.model.yml
new file mode 100644
index 00000000000..628d06b33b8
--- /dev/null
+++ b/csharp/ql/lib/ext/System.Runtime.Serialization.model.yml
@@ -0,0 +1,13 @@
+extensions:
+ - addsTo:
+ pack: codeql/csharp-all
+ extensible: summaryModel
+ data:
+ - ["System.Runtime.Serialization", "SerializationInfo", False, "AddValue", "(System.String,System.Object)", "", "Argument[1]", "Argument[this]", "taint", "manual"]
+ - ["System.Runtime.Serialization", "SerializationInfo", False, "AddValue", "(System.String,System.Object,System.Type)", "", "Argument[1]", "Argument[this]", "taint", "manual"]
+ - ["System.Runtime.Serialization", "SerializationInfo", False, "GetEnumerator", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
+ - ["System.Runtime.Serialization", "SerializationInfo", False, "GetString", "(System.String)", "", "Argument[this]", "ReturnValue", "taint", "manual"]
+ - ["System.Runtime.Serialization", "SerializationInfo", False, "GetValue", "(System.String,System.Type)", "", "Argument[this]", "ReturnValue", "taint", "manual"]
+ # Note that SerializationEntry hasn't been modeled yet, so the model below for get_Current will not in itself provide more flow.
+ - ["System.Runtime.Serialization", "SerializationInfoEnumerator", False, "get_Current", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
+ - ["System.Runtime.Serialization", "SerializationInfoEnumerator", False, "get_Value", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
diff --git a/csharp/ql/lib/ext/System.Text.model.yml b/csharp/ql/lib/ext/System.Text.model.yml
index 4a94b61109f..0067b8b000c 100644
--- a/csharp/ql/lib/ext/System.Text.model.yml
+++ b/csharp/ql/lib/ext/System.Text.model.yml
@@ -3,18 +3,18 @@ extensions:
pack: codeql/csharp-all
extensible: summaryModel
data:
- - ["System.Text", "Encoding", True, "GetBytes", "(System.Char*,System.Int32,System.Byte*,System.Int32)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
+ - ["System.Text", "Encoding", True, "GetBytes", "(System.Char*,System.Int32,System.Byte*,System.Int32)", "", "Argument[0].Element", "Argument[2]", "taint", "manual"]
- ["System.Text", "Encoding", True, "GetBytes", "(System.Char[])", "", "Argument[0].Element", "ReturnValue", "taint", "manual"]
- ["System.Text", "Encoding", True, "GetBytes", "(System.Char[],System.Int32,System.Int32)", "", "Argument[0].Element", "ReturnValue", "taint", "manual"]
- - ["System.Text", "Encoding", True, "GetBytes", "(System.Char[],System.Int32,System.Int32,System.Byte[],System.Int32)", "", "Argument[0].Element", "ReturnValue", "taint", "manual"]
- - ["System.Text", "Encoding", True, "GetBytes", "(System.ReadOnlySpan,System.Span)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
+ - ["System.Text", "Encoding", True, "GetBytes", "(System.Char[],System.Int32,System.Int32,System.Byte[],System.Int32)", "", "Argument[0].Element", "Argument[3]", "taint", "manual"]
+ - ["System.Text", "Encoding", True, "GetBytes", "(System.ReadOnlySpan,System.Span)", "", "Argument[0].Element", "Argument[1]", "taint", "manual"]
- ["System.Text", "Encoding", True, "GetBytes", "(System.String)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- - ["System.Text", "Encoding", False, "GetBytes", "(System.String,System.Int32,System.Int32)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- - ["System.Text", "Encoding", True, "GetBytes", "(System.String,System.Int32,System.Int32,System.Byte[],System.Int32)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- - ["System.Text", "Encoding", True, "GetChars", "(System.Byte*,System.Int32,System.Char*,System.Int32)", "", "Argument[0].Element", "ReturnValue", "taint", "manual"]
+ - ["System.Text", "Encoding", True, "GetBytes", "(System.String,System.Int32,System.Int32)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
+ - ["System.Text", "Encoding", True, "GetBytes", "(System.String,System.Int32,System.Int32,System.Byte[],System.Int32)", "", "Argument[0]", "Argument[3]", "taint", "manual"]
+ - ["System.Text", "Encoding", True, "GetChars", "(System.Byte*,System.Int32,System.Char*,System.Int32)", "", "Argument[0].Element", "Argument[2]", "taint", "manual"]
- ["System.Text", "Encoding", True, "GetChars", "(System.Byte[])", "", "Argument[0].Element", "ReturnValue", "taint", "manual"]
- ["System.Text", "Encoding", True, "GetChars", "(System.Byte[],System.Int32,System.Int32)", "", "Argument[0].Element", "ReturnValue", "taint", "manual"]
- - ["System.Text", "Encoding", True, "GetChars", "(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32)", "", "Argument[0].Element", "ReturnValue", "taint", "manual"]
+ - ["System.Text", "Encoding", True, "GetChars", "(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32)", "", "Argument[0].Element", "Argument[3]", "taint", "manual"]
- ["System.Text", "Encoding", True, "GetChars", "(System.ReadOnlySpan,System.Span)", "", "Argument[0].Element", "ReturnValue", "taint", "manual"]
- ["System.Text", "Encoding", False, "GetString", "(System.Byte*,System.Int32)", "", "Argument[0].Element", "ReturnValue", "taint", "manual"]
- ["System.Text", "Encoding", True, "GetString", "(System.Byte[])", "", "Argument[0].Element", "ReturnValue", "taint", "manual"]
diff --git a/csharp/ql/lib/ext/System.Xml.model.yml b/csharp/ql/lib/ext/System.Xml.model.yml
index 55825304a14..efea34b40db 100644
--- a/csharp/ql/lib/ext/System.Xml.model.yml
+++ b/csharp/ql/lib/ext/System.Xml.model.yml
@@ -4,6 +4,25 @@ extensions:
extensible: summaryModel
data:
- ["System.Xml", "XmlAttributeCollection", False, "CopyTo", "(System.Xml.XmlAttribute[],System.Int32)", "", "Argument[this].Element", "Argument[0].Element", "value", "manual"]
+ - ["System.Xml", "XmlDictionaryReader", False, "CreateBinaryReader", "(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas)", "", "Argument[0].Element", "ReturnValue", "taint", "df-manual"]
+ - ["System.Xml", "XmlDictionaryReader", False, "CreateBinaryReader", "(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas)", "", "Argument[3]", "ReturnValue", "taint", "df-manual"]
+ - ["System.Xml", "XmlDictionaryReader", False, "CreateBinaryReader", "(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession)", "", "Argument[0].Element", "ReturnValue", "taint", "df-manual"]
+ - ["System.Xml", "XmlDictionaryReader", False, "CreateBinaryReader", "(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession)", "", "Argument[3]", "ReturnValue", "taint", "df-manual"]
+ - ["System.Xml", "XmlDictionaryReader", False, "CreateBinaryReader", "(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession)", "", "Argument[5]", "ReturnValue", "taint", "df-manual"]
+ - ["System.Xml", "XmlDictionaryReader", False, "CreateBinaryReader", "(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose)", "", "Argument[0].Element", "ReturnValue", "taint", "manual"]
+ - ["System.Xml", "XmlDictionaryReader", False, "CreateBinaryReader", "(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose)", "", "Argument[3]", "ReturnValue", "taint", "manual"]
+ - ["System.Xml", "XmlDictionaryReader", False, "CreateBinaryReader", "(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose)", "", "Argument[5]", "ReturnValue", "taint", "manual"]
+ - ["System.Xml", "XmlDictionaryReader", False, "CreateBinaryReader", "(System.Byte[],System.Int32,System.Int32,System.Xml.XmlDictionaryReaderQuotas)", "", "Argument[0].Element", "ReturnValue", "taint", "df-manual"]
+ - ["System.Xml", "XmlDictionaryReader", False, "CreateBinaryReader", "(System.Byte[],System.Xml.XmlDictionaryReaderQuotas)", "", "Argument[0].Element", "ReturnValue", "taint", "df-manual"]
+ - ["System.Xml", "XmlDictionaryReader", False, "CreateBinaryReader", "(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas)", "", "Argument[0]", "ReturnValue", "taint", "df-manual"]
+ - ["System.Xml", "XmlDictionaryReader", False, "CreateBinaryReader", "(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas)", "", "Argument[1]", "ReturnValue", "taint", "df-manual"]
+ - ["System.Xml", "XmlDictionaryReader", False, "CreateBinaryReader", "(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession)", "", "Argument[0]", "ReturnValue", "taint", "df-manual"]
+ - ["System.Xml", "XmlDictionaryReader", False, "CreateBinaryReader", "(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession)", "", "Argument[1]", "ReturnValue", "taint", "df-manual"]
+ - ["System.Xml", "XmlDictionaryReader", False, "CreateBinaryReader", "(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession)", "", "Argument[3]", "ReturnValue", "taint", "df-manual"]
+ - ["System.Xml", "XmlDictionaryReader", False, "CreateBinaryReader", "(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
+ - ["System.Xml", "XmlDictionaryReader", False, "CreateBinaryReader", "(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose)", "", "Argument[1]", "ReturnValue", "taint", "manual"]
+ - ["System.Xml", "XmlDictionaryReader", False, "CreateBinaryReader", "(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose)", "", "Argument[3]", "ReturnValue", "taint", "manual"]
+ - ["System.Xml", "XmlDictionaryReader", False, "CreateBinaryReader", "(System.IO.Stream,System.Xml.XmlDictionaryReaderQuotas)", "", "Argument[0]", "ReturnValue", "taint", "df-manual"]
- ["System.Xml", "XmlDocument", False, "Load", "(System.IO.Stream)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
- ["System.Xml", "XmlDocument", False, "Load", "(System.IO.TextReader)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
- ["System.Xml", "XmlDocument", False, "Load", "(System.String)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
diff --git a/csharp/ql/lib/semmle/code/asp/WebConfig.qll b/csharp/ql/lib/semmle/code/asp/WebConfig.qll
index f9106bcd1af..384c3a013c3 100644
--- a/csharp/ql/lib/semmle/code/asp/WebConfig.qll
+++ b/csharp/ql/lib/semmle/code/asp/WebConfig.qll
@@ -8,14 +8,14 @@ import csharp
* A `Web.config` file.
*/
class WebConfigXml extends XmlFile {
- WebConfigXml() { this.getName().matches("%Web.config") }
+ WebConfigXml() { this.getName().toLowerCase().matches("%web.config") }
}
/**
* A `Web.config` transformation file.
*/
class WebConfigReleaseTransformXml extends XmlFile {
- WebConfigReleaseTransformXml() { this.getName().matches("%Web.Release.config") }
+ WebConfigReleaseTransformXml() { this.getName().toLowerCase().matches("%web.release.config") }
}
/** A `` tag in an ASP.NET configuration file. */
diff --git a/csharp/ql/lib/semmle/code/csharp/Type.qll b/csharp/ql/lib/semmle/code/csharp/Type.qll
index 9283bb3002a..d11b5618e80 100644
--- a/csharp/ql/lib/semmle/code/csharp/Type.qll
+++ b/csharp/ql/lib/semmle/code/csharp/Type.qll
@@ -138,6 +138,9 @@ class ValueOrRefType extends Type, Attributable, @value_or_ref_type {
/** Gets an immediate subtype of this type, if any. */
ValueOrRefType getASubType() { result.getABaseType() = this }
+ /** Gets an immediate supertype of this type, if any. */
+ ValueOrRefType getASuperType() { this.getABaseType() = result }
+
/** Gets a member of this type, if any. */
Member getAMember() { result.getDeclaringType() = this }
diff --git a/csharp/ql/src/change-notes/2025-07-01-improve-summary-models.md b/csharp/ql/src/change-notes/2025-07-01-improve-summary-models.md
new file mode 100644
index 00000000000..f2c8fd82bae
--- /dev/null
+++ b/csharp/ql/src/change-notes/2025-07-01-improve-summary-models.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* Explicitly added summary models for all overloads of `System.Xml.XmlDictionaryReader.CreateBinaryReader`. Added models for some of the methods and properties in `System.Runtime.Serialization.SerializationInfo` and `System.Runtime.Serialization.SerializationInfoEnumerator`. Updated models for `System.Text.Encoding.GetBytes`, `System.Text.Encoding.GetChars` and the constructor for `System.IO.MemoryStream`. This generally improves the library modelling and thus reduces the number of false negatives.
diff --git a/csharp/ql/src/change-notes/2025-07-16-web-config.md b/csharp/ql/src/change-notes/2025-07-16-web-config.md
new file mode 100644
index 00000000000..238f6438663
--- /dev/null
+++ b/csharp/ql/src/change-notes/2025-07-16-web-config.md
@@ -0,0 +1,4 @@
+---
+category: fix
+---
+* `web.config` and `web.release.config` files are now recognised regardless of case. This means queries `cs/web/debug-binary` and `cs/web/missing-x-frame-options` may produce more results than before.
diff --git a/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected b/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected
index c3eb0402922..ff615d53115 100644
--- a/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected
+++ b/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected
@@ -12371,7 +12371,7 @@ summary
| System.IO;MemoryStream;CopyToAsync;(System.IO.Stream,System.Int32,System.Threading.CancellationToken);Argument[this];Argument[0];taint;manual |
| System.IO;MemoryStream;FlushAsync;(System.Threading.CancellationToken);Argument[this];ReturnValue.SyntheticField[System.Threading.Tasks.Task.m_stateObject];value;dfc-generated |
| System.IO;MemoryStream;GetBuffer;();Argument[this];ReturnValue;taint;df-generated |
-| System.IO;MemoryStream;MemoryStream;(System.Byte[]);Argument[0];Argument[this];taint;manual |
+| System.IO;MemoryStream;MemoryStream;(System.Byte[]);Argument[0].Element;Argument[this];taint;manual |
| System.IO;MemoryStream;MemoryStream;(System.Byte[],System.Boolean);Argument[0].Element;Argument[this];taint;manual |
| System.IO;MemoryStream;MemoryStream;(System.Byte[],System.Int32,System.Int32);Argument[0].Element;Argument[this];taint;manual |
| System.IO;MemoryStream;MemoryStream;(System.Byte[],System.Int32,System.Int32,System.Boolean);Argument[0].Element;Argument[this];taint;manual |
@@ -17277,30 +17277,20 @@ summary
| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.Int16);Argument[0];Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._names].Element;value;dfc-generated |
| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.Int32);Argument[0];Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._names].Element;value;dfc-generated |
| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.Int64);Argument[0];Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._names].Element;value;dfc-generated |
-| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.Object);Argument[0];Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._names].Element;value;dfc-generated |
-| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.Object);Argument[1];Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._values].Element;value;dfc-generated |
-| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.Object,System.Type);Argument[0];Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._names].Element;value;dfc-generated |
-| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.Object,System.Type);Argument[1];Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._values].Element;value;dfc-generated |
+| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.Object);Argument[1];Argument[this];taint;manual |
+| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.Object,System.Type);Argument[1];Argument[this];taint;manual |
| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.SByte);Argument[0];Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._names].Element;value;dfc-generated |
| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.Single);Argument[0];Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._names].Element;value;dfc-generated |
| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.UInt16);Argument[0];Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._names].Element;value;dfc-generated |
| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.UInt32);Argument[0];Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._names].Element;value;dfc-generated |
| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.UInt64);Argument[0];Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._names].Element;value;dfc-generated |
-| System.Runtime.Serialization;SerializationInfo;GetEnumerator;();Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._names];ReturnValue.SyntheticField[System.Runtime.Serialization.SerializationInfoEnumerator._members];value;dfc-generated |
-| System.Runtime.Serialization;SerializationInfo;GetEnumerator;();Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._values];ReturnValue.SyntheticField[System.Runtime.Serialization.SerializationInfoEnumerator._data];value;dfc-generated |
-| System.Runtime.Serialization;SerializationInfo;GetString;(System.String);Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._values].Element;ReturnValue;value;dfc-generated |
-| System.Runtime.Serialization;SerializationInfo;GetValue;(System.String,System.Type);Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._values].Element;ReturnValue;value;dfc-generated |
+| System.Runtime.Serialization;SerializationInfo;GetEnumerator;();Argument[this];ReturnValue;taint;manual |
+| System.Runtime.Serialization;SerializationInfo;GetString;(System.String);Argument[this];ReturnValue;taint;manual |
+| System.Runtime.Serialization;SerializationInfo;GetValue;(System.String,System.Type);Argument[this];ReturnValue;taint;manual |
| System.Runtime.Serialization;SerializationInfo;SerializationInfo;(System.Type,System.Runtime.Serialization.IFormatterConverter);Argument[1];Argument[this];taint;df-generated |
-| System.Runtime.Serialization;SerializationInfoEnumerator;get_Current;();Argument[this].Property[System.Runtime.Serialization.SerializationInfoEnumerator.Current];ReturnValue;value;df-generated |
-| System.Runtime.Serialization;SerializationInfoEnumerator;get_Current;();Argument[this].Property[System.Runtime.Serialization.SerializationInfoEnumerator.Current];ReturnValue;value;dfc-generated |
-| System.Runtime.Serialization;SerializationInfoEnumerator;get_Current;();Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfoEnumerator._data].Element;ReturnValue.SyntheticField[System.Runtime.Serialization.SerializationEntry._value];value;df-generated |
-| System.Runtime.Serialization;SerializationInfoEnumerator;get_Current;();Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfoEnumerator._data].Element;ReturnValue.SyntheticField[System.Runtime.Serialization.SerializationEntry._value];value;dfc-generated |
-| System.Runtime.Serialization;SerializationInfoEnumerator;get_Current;();Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfoEnumerator._members].Element;ReturnValue.SyntheticField[System.Runtime.Serialization.SerializationEntry._name];value;df-generated |
-| System.Runtime.Serialization;SerializationInfoEnumerator;get_Current;();Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfoEnumerator._members].Element;ReturnValue.SyntheticField[System.Runtime.Serialization.SerializationEntry._name];value;dfc-generated |
-| System.Runtime.Serialization;SerializationInfoEnumerator;get_Current;();Argument[this];ReturnValue;taint;df-generated |
-| System.Runtime.Serialization;SerializationInfoEnumerator;get_Current;();Argument[this];ReturnValue;taint;dfc-generated |
+| System.Runtime.Serialization;SerializationInfoEnumerator;get_Current;();Argument[this];ReturnValue;taint;manual |
| System.Runtime.Serialization;SerializationInfoEnumerator;get_Name;();Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfoEnumerator._members].Element;ReturnValue;value;dfc-generated |
-| System.Runtime.Serialization;SerializationInfoEnumerator;get_Value;();Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfoEnumerator._data].Element;ReturnValue;value;dfc-generated |
+| System.Runtime.Serialization;SerializationInfoEnumerator;get_Value;();Argument[this];ReturnValue;taint;manual |
| System.Runtime.Serialization;SerializationObjectManager;SerializationObjectManager;(System.Runtime.Serialization.StreamingContext);Argument[0];Argument[this];taint;df-generated |
| System.Runtime.Serialization;StreamingContext;StreamingContext;(System.Runtime.Serialization.StreamingContextStates,System.Object);Argument[1];Argument[this].SyntheticField[System.Runtime.Serialization.StreamingContext._additionalContext];value;dfc-generated |
| System.Runtime.Serialization;StreamingContext;get_Context;();Argument[this].SyntheticField[System.Runtime.Serialization.StreamingContext._additionalContext];ReturnValue;value;dfc-generated |
@@ -18467,12 +18457,12 @@ summary
| System.Text.Unicode;Utf8+TryWriteInterpolatedStringHandler;TryWriteInterpolatedStringHandler;(System.Int32,System.Int32,System.Span,System.Boolean);Argument[2];Argument[this];taint;df-generated |
| System.Text.Unicode;Utf8+TryWriteInterpolatedStringHandler;TryWriteInterpolatedStringHandler;(System.Int32,System.Int32,System.Span,System.IFormatProvider,System.Boolean);Argument[2];Argument[this];taint;df-generated |
| System.Text.Unicode;Utf8+TryWriteInterpolatedStringHandler;TryWriteInterpolatedStringHandler;(System.Int32,System.Int32,System.Span,System.IFormatProvider,System.Boolean);Argument[3];Argument[this];taint;df-generated |
-| System.Text;ASCIIEncoding;GetBytes;(System.Char*,System.Int32,System.Byte*,System.Int32);Argument[0];ReturnValue;taint;manual |
-| System.Text;ASCIIEncoding;GetBytes;(System.Char[],System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0].Element;ReturnValue;taint;manual |
-| System.Text;ASCIIEncoding;GetBytes;(System.ReadOnlySpan,System.Span);Argument[0];ReturnValue;taint;manual |
-| System.Text;ASCIIEncoding;GetBytes;(System.String,System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0];ReturnValue;taint;manual |
-| System.Text;ASCIIEncoding;GetChars;(System.Byte*,System.Int32,System.Char*,System.Int32);Argument[0].Element;ReturnValue;taint;manual |
-| System.Text;ASCIIEncoding;GetChars;(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32);Argument[0].Element;ReturnValue;taint;manual |
+| System.Text;ASCIIEncoding;GetBytes;(System.Char*,System.Int32,System.Byte*,System.Int32);Argument[0].Element;Argument[2];taint;manual |
+| System.Text;ASCIIEncoding;GetBytes;(System.Char[],System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0].Element;Argument[3];taint;manual |
+| System.Text;ASCIIEncoding;GetBytes;(System.ReadOnlySpan,System.Span);Argument[0].Element;Argument[1];taint;manual |
+| System.Text;ASCIIEncoding;GetBytes;(System.String,System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0];Argument[3];taint;manual |
+| System.Text;ASCIIEncoding;GetChars;(System.Byte*,System.Int32,System.Char*,System.Int32);Argument[0].Element;Argument[2];taint;manual |
+| System.Text;ASCIIEncoding;GetChars;(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32);Argument[0].Element;Argument[3];taint;manual |
| System.Text;ASCIIEncoding;GetChars;(System.ReadOnlySpan,System.Span);Argument[0].Element;ReturnValue;taint;manual |
| System.Text;ASCIIEncoding;GetDecoder;();Argument[this];ReturnValue;taint;df-generated |
| System.Text;ASCIIEncoding;GetEncoder;();Argument[this];ReturnValue;taint;df-generated |
@@ -18501,18 +18491,18 @@ summary
| System.Text;Encoding;CreateTranscodingStream;(System.IO.Stream,System.Text.Encoding,System.Text.Encoding,System.Boolean);Argument[2];ReturnValue;taint;df-generated |
| System.Text;Encoding;Encoding;(System.Int32,System.Text.EncoderFallback,System.Text.DecoderFallback);Argument[1];Argument[this];taint;df-generated |
| System.Text;Encoding;Encoding;(System.Int32,System.Text.EncoderFallback,System.Text.DecoderFallback);Argument[2];Argument[this];taint;df-generated |
-| System.Text;Encoding;GetBytes;(System.Char*,System.Int32,System.Byte*,System.Int32);Argument[0];ReturnValue;taint;manual |
+| System.Text;Encoding;GetBytes;(System.Char*,System.Int32,System.Byte*,System.Int32);Argument[0].Element;Argument[2];taint;manual |
| System.Text;Encoding;GetBytes;(System.Char[]);Argument[0].Element;ReturnValue;taint;manual |
| System.Text;Encoding;GetBytes;(System.Char[],System.Int32,System.Int32);Argument[0].Element;ReturnValue;taint;manual |
-| System.Text;Encoding;GetBytes;(System.Char[],System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0].Element;ReturnValue;taint;manual |
-| System.Text;Encoding;GetBytes;(System.ReadOnlySpan,System.Span);Argument[0];ReturnValue;taint;manual |
+| System.Text;Encoding;GetBytes;(System.Char[],System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0].Element;Argument[3];taint;manual |
+| System.Text;Encoding;GetBytes;(System.ReadOnlySpan,System.Span);Argument[0].Element;Argument[1];taint;manual |
| System.Text;Encoding;GetBytes;(System.String);Argument[0];ReturnValue;taint;manual |
| System.Text;Encoding;GetBytes;(System.String,System.Int32,System.Int32);Argument[0];ReturnValue;taint;manual |
-| System.Text;Encoding;GetBytes;(System.String,System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0];ReturnValue;taint;manual |
-| System.Text;Encoding;GetChars;(System.Byte*,System.Int32,System.Char*,System.Int32);Argument[0].Element;ReturnValue;taint;manual |
+| System.Text;Encoding;GetBytes;(System.String,System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0];Argument[3];taint;manual |
+| System.Text;Encoding;GetChars;(System.Byte*,System.Int32,System.Char*,System.Int32);Argument[0].Element;Argument[2];taint;manual |
| System.Text;Encoding;GetChars;(System.Byte[]);Argument[0].Element;ReturnValue;taint;manual |
| System.Text;Encoding;GetChars;(System.Byte[],System.Int32,System.Int32);Argument[0].Element;ReturnValue;taint;manual |
-| System.Text;Encoding;GetChars;(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32);Argument[0].Element;ReturnValue;taint;manual |
+| System.Text;Encoding;GetChars;(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32);Argument[0].Element;Argument[3];taint;manual |
| System.Text;Encoding;GetChars;(System.ReadOnlySpan,System.Span);Argument[0].Element;ReturnValue;taint;manual |
| System.Text;Encoding;GetDecoder;();Argument[this];ReturnValue;taint;df-generated |
| System.Text;Encoding;GetEncoder;();Argument[this];ReturnValue;taint;df-generated |
@@ -18703,37 +18693,37 @@ summary
| System.Text;StringRuneEnumerator;GetEnumerator;();Argument[this].Element;ReturnValue.Property[System.Collections.IEnumerator.Current];value;manual |
| System.Text;StringRuneEnumerator;GetEnumerator;();Argument[this];ReturnValue;value;dfc-generated |
| System.Text;StringRuneEnumerator;get_Current;();Argument[this];ReturnValue;taint;df-generated |
-| System.Text;UTF7Encoding;GetBytes;(System.Char*,System.Int32,System.Byte*,System.Int32);Argument[0];ReturnValue;taint;manual |
-| System.Text;UTF7Encoding;GetBytes;(System.Char[],System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0].Element;ReturnValue;taint;manual |
-| System.Text;UTF7Encoding;GetBytes;(System.String,System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0];ReturnValue;taint;manual |
-| System.Text;UTF7Encoding;GetChars;(System.Byte*,System.Int32,System.Char*,System.Int32);Argument[0].Element;ReturnValue;taint;manual |
-| System.Text;UTF7Encoding;GetChars;(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32);Argument[0].Element;ReturnValue;taint;manual |
+| System.Text;UTF7Encoding;GetBytes;(System.Char*,System.Int32,System.Byte*,System.Int32);Argument[0].Element;Argument[2];taint;manual |
+| System.Text;UTF7Encoding;GetBytes;(System.Char[],System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0].Element;Argument[3];taint;manual |
+| System.Text;UTF7Encoding;GetBytes;(System.String,System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0];Argument[3];taint;manual |
+| System.Text;UTF7Encoding;GetChars;(System.Byte*,System.Int32,System.Char*,System.Int32);Argument[0].Element;Argument[2];taint;manual |
+| System.Text;UTF7Encoding;GetChars;(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32);Argument[0].Element;Argument[3];taint;manual |
| System.Text;UTF7Encoding;GetDecoder;();Argument[this];ReturnValue;taint;df-generated |
| System.Text;UTF7Encoding;GetEncoder;();Argument[this];ReturnValue;taint;df-generated |
| System.Text;UTF7Encoding;GetString;(System.Byte[],System.Int32,System.Int32);Argument[0].Element;ReturnValue;taint;manual |
-| System.Text;UTF8Encoding;GetBytes;(System.Char*,System.Int32,System.Byte*,System.Int32);Argument[0];ReturnValue;taint;manual |
-| System.Text;UTF8Encoding;GetBytes;(System.Char[],System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0].Element;ReturnValue;taint;manual |
-| System.Text;UTF8Encoding;GetBytes;(System.ReadOnlySpan,System.Span);Argument[0];ReturnValue;taint;manual |
-| System.Text;UTF8Encoding;GetBytes;(System.String,System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0];ReturnValue;taint;manual |
-| System.Text;UTF8Encoding;GetChars;(System.Byte*,System.Int32,System.Char*,System.Int32);Argument[0].Element;ReturnValue;taint;manual |
-| System.Text;UTF8Encoding;GetChars;(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32);Argument[0].Element;ReturnValue;taint;manual |
+| System.Text;UTF8Encoding;GetBytes;(System.Char*,System.Int32,System.Byte*,System.Int32);Argument[0].Element;Argument[2];taint;manual |
+| System.Text;UTF8Encoding;GetBytes;(System.Char[],System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0].Element;Argument[3];taint;manual |
+| System.Text;UTF8Encoding;GetBytes;(System.ReadOnlySpan,System.Span);Argument[0].Element;Argument[1];taint;manual |
+| System.Text;UTF8Encoding;GetBytes;(System.String,System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0];Argument[3];taint;manual |
+| System.Text;UTF8Encoding;GetChars;(System.Byte*,System.Int32,System.Char*,System.Int32);Argument[0].Element;Argument[2];taint;manual |
+| System.Text;UTF8Encoding;GetChars;(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32);Argument[0].Element;Argument[3];taint;manual |
| System.Text;UTF8Encoding;GetChars;(System.ReadOnlySpan,System.Span);Argument[0].Element;ReturnValue;taint;manual |
| System.Text;UTF8Encoding;GetDecoder;();Argument[this];ReturnValue;taint;df-generated |
| System.Text;UTF8Encoding;GetEncoder;();Argument[this];ReturnValue;taint;df-generated |
| System.Text;UTF8Encoding;GetString;(System.Byte[],System.Int32,System.Int32);Argument[0].Element;ReturnValue;taint;manual |
-| System.Text;UTF32Encoding;GetBytes;(System.Char*,System.Int32,System.Byte*,System.Int32);Argument[0];ReturnValue;taint;manual |
-| System.Text;UTF32Encoding;GetBytes;(System.Char[],System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0].Element;ReturnValue;taint;manual |
-| System.Text;UTF32Encoding;GetBytes;(System.String,System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0];ReturnValue;taint;manual |
-| System.Text;UTF32Encoding;GetChars;(System.Byte*,System.Int32,System.Char*,System.Int32);Argument[0].Element;ReturnValue;taint;manual |
-| System.Text;UTF32Encoding;GetChars;(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32);Argument[0].Element;ReturnValue;taint;manual |
+| System.Text;UTF32Encoding;GetBytes;(System.Char*,System.Int32,System.Byte*,System.Int32);Argument[0].Element;Argument[2];taint;manual |
+| System.Text;UTF32Encoding;GetBytes;(System.Char[],System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0].Element;Argument[3];taint;manual |
+| System.Text;UTF32Encoding;GetBytes;(System.String,System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0];Argument[3];taint;manual |
+| System.Text;UTF32Encoding;GetChars;(System.Byte*,System.Int32,System.Char*,System.Int32);Argument[0].Element;Argument[2];taint;manual |
+| System.Text;UTF32Encoding;GetChars;(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32);Argument[0].Element;Argument[3];taint;manual |
| System.Text;UTF32Encoding;GetDecoder;();Argument[this];ReturnValue;taint;df-generated |
| System.Text;UTF32Encoding;GetEncoder;();Argument[this];ReturnValue;taint;df-generated |
| System.Text;UTF32Encoding;GetString;(System.Byte[],System.Int32,System.Int32);Argument[0].Element;ReturnValue;taint;manual |
-| System.Text;UnicodeEncoding;GetBytes;(System.Char*,System.Int32,System.Byte*,System.Int32);Argument[0];ReturnValue;taint;manual |
-| System.Text;UnicodeEncoding;GetBytes;(System.Char[],System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0].Element;ReturnValue;taint;manual |
-| System.Text;UnicodeEncoding;GetBytes;(System.String,System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0];ReturnValue;taint;manual |
-| System.Text;UnicodeEncoding;GetChars;(System.Byte*,System.Int32,System.Char*,System.Int32);Argument[0].Element;ReturnValue;taint;manual |
-| System.Text;UnicodeEncoding;GetChars;(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32);Argument[0].Element;ReturnValue;taint;manual |
+| System.Text;UnicodeEncoding;GetBytes;(System.Char*,System.Int32,System.Byte*,System.Int32);Argument[0].Element;Argument[2];taint;manual |
+| System.Text;UnicodeEncoding;GetBytes;(System.Char[],System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0].Element;Argument[3];taint;manual |
+| System.Text;UnicodeEncoding;GetBytes;(System.String,System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0];Argument[3];taint;manual |
+| System.Text;UnicodeEncoding;GetChars;(System.Byte*,System.Int32,System.Char*,System.Int32);Argument[0].Element;Argument[2];taint;manual |
+| System.Text;UnicodeEncoding;GetChars;(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32);Argument[0].Element;Argument[3];taint;manual |
| System.Text;UnicodeEncoding;GetDecoder;();Argument[this];ReturnValue;taint;df-generated |
| System.Text;UnicodeEncoding;GetEncoder;();Argument[this];ReturnValue;taint;df-generated |
| System.Text;UnicodeEncoding;GetString;(System.Byte[],System.Int32,System.Int32);Argument[0].Element;ReturnValue;taint;manual |
@@ -20868,21 +20858,27 @@ summary
| System.Xml;XmlDictionary;TryLookup;(System.Int32,System.Xml.XmlDictionaryString);Argument[this];Argument[1];taint;df-generated |
| System.Xml;XmlDictionary;TryLookup;(System.String,System.Xml.XmlDictionaryString);Argument[this];Argument[1];taint;df-generated |
| System.Xml;XmlDictionary;TryLookup;(System.Xml.XmlDictionaryString,System.Xml.XmlDictionaryString);Argument[0];Argument[1];value;dfc-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas);Argument[0].Element;ReturnValue;taint;df-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas);Argument[3];ReturnValue;taint;df-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession);Argument[0].Element;ReturnValue;taint;df-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession);Argument[3];ReturnValue;taint;df-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession);Argument[5];ReturnValue;taint;df-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose);Argument[6];Argument[6].Parameter[delegate-self];value;hq-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.XmlDictionaryReaderQuotas);Argument[0].Element;ReturnValue;taint;df-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Xml.XmlDictionaryReaderQuotas);Argument[0].Element;ReturnValue;taint;df-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas);Argument[0];ReturnValue;taint;df-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas);Argument[1];ReturnValue;taint;df-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession);Argument[0];ReturnValue;taint;df-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession);Argument[1];ReturnValue;taint;df-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession);Argument[3];ReturnValue;taint;df-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose);Argument[4];Argument[4].Parameter[delegate-self];value;hq-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.XmlDictionaryReaderQuotas);Argument[0];ReturnValue;taint;df-generated |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas);Argument[0].Element;ReturnValue;taint;df-manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas);Argument[3];ReturnValue;taint;df-manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession);Argument[0].Element;ReturnValue;taint;df-manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession);Argument[3];ReturnValue;taint;df-manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession);Argument[5];ReturnValue;taint;df-manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose);Argument[0].Element;ReturnValue;taint;manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose);Argument[3];ReturnValue;taint;manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose);Argument[5];ReturnValue;taint;manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose);Argument[6];Argument[6].Parameter[delegate-self];value;manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.XmlDictionaryReaderQuotas);Argument[0].Element;ReturnValue;taint;df-manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Xml.XmlDictionaryReaderQuotas);Argument[0].Element;ReturnValue;taint;df-manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas);Argument[0];ReturnValue;taint;df-manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas);Argument[1];ReturnValue;taint;df-manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession);Argument[0];ReturnValue;taint;df-manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession);Argument[1];ReturnValue;taint;df-manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession);Argument[3];ReturnValue;taint;df-manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose);Argument[0];ReturnValue;taint;manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose);Argument[1];ReturnValue;taint;manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose);Argument[3];ReturnValue;taint;manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose);Argument[4];Argument[4].Parameter[delegate-self];value;manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.XmlDictionaryReaderQuotas);Argument[0];ReturnValue;taint;df-manual |
| System.Xml;XmlDictionaryReader;CreateDictionaryReader;(System.Xml.XmlReader);Argument[0];ReturnValue;value;dfc-generated |
| System.Xml;XmlDictionaryReader;CreateMtomReader;(System.Byte[],System.Int32,System.Int32,System.Text.Encoding[],System.String,System.Xml.XmlDictionaryReaderQuotas,System.Int32,System.Xml.OnXmlDictionaryReaderClose);Argument[7];Argument[7].Parameter[delegate-self];value;hq-generated |
| System.Xml;XmlDictionaryReader;CreateMtomReader;(System.IO.Stream,System.Text.Encoding[],System.String,System.Xml.XmlDictionaryReaderQuotas,System.Int32,System.Xml.OnXmlDictionaryReaderClose);Argument[5];Argument[5].Parameter[delegate-self];value;hq-generated |
diff --git a/csharp/ql/test/library-tests/dataflow/library/FlowSummariesFiltered.expected b/csharp/ql/test/library-tests/dataflow/library/FlowSummariesFiltered.expected
index 8c0a26ee403..faf716f4d7b 100644
--- a/csharp/ql/test/library-tests/dataflow/library/FlowSummariesFiltered.expected
+++ b/csharp/ql/test/library-tests/dataflow/library/FlowSummariesFiltered.expected
@@ -9208,7 +9208,7 @@
| System.IO;FileSystemWatcher;remove_Error;(System.IO.ErrorEventHandler);Argument[0];Argument[0].Parameter[delegate-self];value;hq-generated |
| System.IO;FileSystemWatcher;remove_Renamed;(System.IO.RenamedEventHandler);Argument[0];Argument[0].Parameter[delegate-self];value;hq-generated |
| System.IO;MemoryStream;GetBuffer;();Argument[this];ReturnValue;taint;df-generated |
-| System.IO;MemoryStream;MemoryStream;(System.Byte[]);Argument[0];Argument[this];taint;manual |
+| System.IO;MemoryStream;MemoryStream;(System.Byte[]);Argument[0].Element;Argument[this];taint;manual |
| System.IO;MemoryStream;MemoryStream;(System.Byte[],System.Boolean);Argument[0].Element;Argument[this];taint;manual |
| System.IO;MemoryStream;MemoryStream;(System.Byte[],System.Int32,System.Int32);Argument[0].Element;Argument[this];taint;manual |
| System.IO;MemoryStream;MemoryStream;(System.Byte[],System.Int32,System.Int32,System.Boolean);Argument[0].Element;Argument[this];taint;manual |
@@ -13222,28 +13222,20 @@
| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.Int16);Argument[0];Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._names].Element;value;dfc-generated |
| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.Int32);Argument[0];Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._names].Element;value;dfc-generated |
| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.Int64);Argument[0];Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._names].Element;value;dfc-generated |
-| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.Object);Argument[0];Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._names].Element;value;dfc-generated |
-| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.Object);Argument[1];Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._values].Element;value;dfc-generated |
-| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.Object,System.Type);Argument[0];Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._names].Element;value;dfc-generated |
-| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.Object,System.Type);Argument[1];Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._values].Element;value;dfc-generated |
+| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.Object);Argument[1];Argument[this];taint;manual |
+| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.Object,System.Type);Argument[1];Argument[this];taint;manual |
| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.SByte);Argument[0];Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._names].Element;value;dfc-generated |
| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.Single);Argument[0];Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._names].Element;value;dfc-generated |
| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.UInt16);Argument[0];Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._names].Element;value;dfc-generated |
| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.UInt32);Argument[0];Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._names].Element;value;dfc-generated |
| System.Runtime.Serialization;SerializationInfo;AddValue;(System.String,System.UInt64);Argument[0];Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._names].Element;value;dfc-generated |
-| System.Runtime.Serialization;SerializationInfo;GetEnumerator;();Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._names];ReturnValue.SyntheticField[System.Runtime.Serialization.SerializationInfoEnumerator._members];value;dfc-generated |
-| System.Runtime.Serialization;SerializationInfo;GetEnumerator;();Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._values];ReturnValue.SyntheticField[System.Runtime.Serialization.SerializationInfoEnumerator._data];value;dfc-generated |
-| System.Runtime.Serialization;SerializationInfo;GetString;(System.String);Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._values].Element;ReturnValue;value;dfc-generated |
-| System.Runtime.Serialization;SerializationInfo;GetValue;(System.String,System.Type);Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfo._values].Element;ReturnValue;value;dfc-generated |
+| System.Runtime.Serialization;SerializationInfo;GetEnumerator;();Argument[this];ReturnValue;taint;manual |
+| System.Runtime.Serialization;SerializationInfo;GetString;(System.String);Argument[this];ReturnValue;taint;manual |
+| System.Runtime.Serialization;SerializationInfo;GetValue;(System.String,System.Type);Argument[this];ReturnValue;taint;manual |
| System.Runtime.Serialization;SerializationInfo;SerializationInfo;(System.Type,System.Runtime.Serialization.IFormatterConverter);Argument[1];Argument[this];taint;df-generated |
-| System.Runtime.Serialization;SerializationInfoEnumerator;get_Current;();Argument[this].Property[System.Runtime.Serialization.SerializationInfoEnumerator.Current];ReturnValue;value;df-generated |
-| System.Runtime.Serialization;SerializationInfoEnumerator;get_Current;();Argument[this].Property[System.Runtime.Serialization.SerializationInfoEnumerator.Current];ReturnValue;value;dfc-generated |
-| System.Runtime.Serialization;SerializationInfoEnumerator;get_Current;();Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfoEnumerator._data].Element;ReturnValue.SyntheticField[System.Runtime.Serialization.SerializationEntry._value];value;df-generated |
-| System.Runtime.Serialization;SerializationInfoEnumerator;get_Current;();Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfoEnumerator._data].Element;ReturnValue.SyntheticField[System.Runtime.Serialization.SerializationEntry._value];value;dfc-generated |
-| System.Runtime.Serialization;SerializationInfoEnumerator;get_Current;();Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfoEnumerator._members].Element;ReturnValue.SyntheticField[System.Runtime.Serialization.SerializationEntry._name];value;df-generated |
-| System.Runtime.Serialization;SerializationInfoEnumerator;get_Current;();Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfoEnumerator._members].Element;ReturnValue.SyntheticField[System.Runtime.Serialization.SerializationEntry._name];value;dfc-generated |
+| System.Runtime.Serialization;SerializationInfoEnumerator;get_Current;();Argument[this];ReturnValue;taint;manual |
| System.Runtime.Serialization;SerializationInfoEnumerator;get_Name;();Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfoEnumerator._members].Element;ReturnValue;value;dfc-generated |
-| System.Runtime.Serialization;SerializationInfoEnumerator;get_Value;();Argument[this].SyntheticField[System.Runtime.Serialization.SerializationInfoEnumerator._data].Element;ReturnValue;value;dfc-generated |
+| System.Runtime.Serialization;SerializationInfoEnumerator;get_Value;();Argument[this];ReturnValue;taint;manual |
| System.Runtime.Serialization;SerializationObjectManager;SerializationObjectManager;(System.Runtime.Serialization.StreamingContext);Argument[0];Argument[this];taint;df-generated |
| System.Runtime.Serialization;StreamingContext;StreamingContext;(System.Runtime.Serialization.StreamingContextStates,System.Object);Argument[1];Argument[this].SyntheticField[System.Runtime.Serialization.StreamingContext._additionalContext];value;dfc-generated |
| System.Runtime.Serialization;StreamingContext;get_Context;();Argument[this].SyntheticField[System.Runtime.Serialization.StreamingContext._additionalContext];ReturnValue;value;dfc-generated |
@@ -14074,18 +14066,18 @@
| System.Text;Encoding;CreateTranscodingStream;(System.IO.Stream,System.Text.Encoding,System.Text.Encoding,System.Boolean);Argument[2];ReturnValue;taint;df-generated |
| System.Text;Encoding;Encoding;(System.Int32,System.Text.EncoderFallback,System.Text.DecoderFallback);Argument[1];Argument[this];taint;df-generated |
| System.Text;Encoding;Encoding;(System.Int32,System.Text.EncoderFallback,System.Text.DecoderFallback);Argument[2];Argument[this];taint;df-generated |
-| System.Text;Encoding;GetBytes;(System.Char*,System.Int32,System.Byte*,System.Int32);Argument[0];ReturnValue;taint;manual |
+| System.Text;Encoding;GetBytes;(System.Char*,System.Int32,System.Byte*,System.Int32);Argument[0].Element;Argument[2];taint;manual |
| System.Text;Encoding;GetBytes;(System.Char[]);Argument[0].Element;ReturnValue;taint;manual |
| System.Text;Encoding;GetBytes;(System.Char[],System.Int32,System.Int32);Argument[0].Element;ReturnValue;taint;manual |
-| System.Text;Encoding;GetBytes;(System.Char[],System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0].Element;ReturnValue;taint;manual |
-| System.Text;Encoding;GetBytes;(System.ReadOnlySpan,System.Span);Argument[0];ReturnValue;taint;manual |
+| System.Text;Encoding;GetBytes;(System.Char[],System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0].Element;Argument[3];taint;manual |
+| System.Text;Encoding;GetBytes;(System.ReadOnlySpan,System.Span);Argument[0].Element;Argument[1];taint;manual |
| System.Text;Encoding;GetBytes;(System.String);Argument[0];ReturnValue;taint;manual |
| System.Text;Encoding;GetBytes;(System.String,System.Int32,System.Int32);Argument[0];ReturnValue;taint;manual |
-| System.Text;Encoding;GetBytes;(System.String,System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0];ReturnValue;taint;manual |
-| System.Text;Encoding;GetChars;(System.Byte*,System.Int32,System.Char*,System.Int32);Argument[0].Element;ReturnValue;taint;manual |
+| System.Text;Encoding;GetBytes;(System.String,System.Int32,System.Int32,System.Byte[],System.Int32);Argument[0];Argument[3];taint;manual |
+| System.Text;Encoding;GetChars;(System.Byte*,System.Int32,System.Char*,System.Int32);Argument[0].Element;Argument[2];taint;manual |
| System.Text;Encoding;GetChars;(System.Byte[]);Argument[0].Element;ReturnValue;taint;manual |
| System.Text;Encoding;GetChars;(System.Byte[],System.Int32,System.Int32);Argument[0].Element;ReturnValue;taint;manual |
-| System.Text;Encoding;GetChars;(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32);Argument[0].Element;ReturnValue;taint;manual |
+| System.Text;Encoding;GetChars;(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32);Argument[0].Element;Argument[3];taint;manual |
| System.Text;Encoding;GetChars;(System.ReadOnlySpan,System.Span);Argument[0].Element;ReturnValue;taint;manual |
| System.Text;Encoding;GetDecoder;();Argument[this];ReturnValue;taint;df-generated |
| System.Text;Encoding;GetEncoder;();Argument[this];ReturnValue;taint;df-generated |
@@ -16194,21 +16186,27 @@
| System.Xml;XmlDeclaration;XmlDeclaration;(System.String,System.String,System.String,System.Xml.XmlDocument);Argument[2];Argument[this];taint;df-generated |
| System.Xml;XmlDictionary;Add;(System.String);Argument[0];ReturnValue.SyntheticField[System.Xml.XmlDictionaryString._value];value;dfc-generated |
| System.Xml;XmlDictionary;Add;(System.String);Argument[this];ReturnValue.SyntheticField[System.Xml.XmlDictionaryString._dictionary];value;dfc-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas);Argument[0].Element;ReturnValue;taint;df-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas);Argument[3];ReturnValue;taint;df-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession);Argument[0].Element;ReturnValue;taint;df-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession);Argument[3];ReturnValue;taint;df-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession);Argument[5];ReturnValue;taint;df-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose);Argument[6];Argument[6].Parameter[delegate-self];value;hq-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.XmlDictionaryReaderQuotas);Argument[0].Element;ReturnValue;taint;df-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Xml.XmlDictionaryReaderQuotas);Argument[0].Element;ReturnValue;taint;df-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas);Argument[0];ReturnValue;taint;df-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas);Argument[1];ReturnValue;taint;df-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession);Argument[0];ReturnValue;taint;df-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession);Argument[1];ReturnValue;taint;df-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession);Argument[3];ReturnValue;taint;df-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose);Argument[4];Argument[4].Parameter[delegate-self];value;hq-generated |
-| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.XmlDictionaryReaderQuotas);Argument[0];ReturnValue;taint;df-generated |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas);Argument[0].Element;ReturnValue;taint;df-manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas);Argument[3];ReturnValue;taint;df-manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession);Argument[0].Element;ReturnValue;taint;df-manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession);Argument[3];ReturnValue;taint;df-manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession);Argument[5];ReturnValue;taint;df-manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose);Argument[0].Element;ReturnValue;taint;manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose);Argument[3];ReturnValue;taint;manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose);Argument[5];ReturnValue;taint;manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose);Argument[6];Argument[6].Parameter[delegate-self];value;manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Int32,System.Int32,System.Xml.XmlDictionaryReaderQuotas);Argument[0].Element;ReturnValue;taint;df-manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.Byte[],System.Xml.XmlDictionaryReaderQuotas);Argument[0].Element;ReturnValue;taint;df-manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas);Argument[0];ReturnValue;taint;df-manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas);Argument[1];ReturnValue;taint;df-manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession);Argument[0];ReturnValue;taint;df-manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession);Argument[1];ReturnValue;taint;df-manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession);Argument[3];ReturnValue;taint;df-manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose);Argument[0];ReturnValue;taint;manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose);Argument[1];ReturnValue;taint;manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose);Argument[3];ReturnValue;taint;manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.IXmlDictionary,System.Xml.XmlDictionaryReaderQuotas,System.Xml.XmlBinaryReaderSession,System.Xml.OnXmlDictionaryReaderClose);Argument[4];Argument[4].Parameter[delegate-self];value;manual |
+| System.Xml;XmlDictionaryReader;CreateBinaryReader;(System.IO.Stream,System.Xml.XmlDictionaryReaderQuotas);Argument[0];ReturnValue;taint;df-manual |
| System.Xml;XmlDictionaryReader;CreateDictionaryReader;(System.Xml.XmlReader);Argument[0];ReturnValue;value;dfc-generated |
| System.Xml;XmlDictionaryReader;CreateMtomReader;(System.Byte[],System.Int32,System.Int32,System.Text.Encoding[],System.String,System.Xml.XmlDictionaryReaderQuotas,System.Int32,System.Xml.OnXmlDictionaryReaderClose);Argument[7];Argument[7].Parameter[delegate-self];value;hq-generated |
| System.Xml;XmlDictionaryReader;CreateMtomReader;(System.IO.Stream,System.Text.Encoding[],System.String,System.Xml.XmlDictionaryReaderQuotas,System.Int32,System.Xml.OnXmlDictionaryReaderClose);Argument[5];Argument[5].Parameter[delegate-self];value;hq-generated |
diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/DeserializedDelegate/DeserializedDelegate.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/DeserializedDelegate/DeserializedDelegate.cs
index 93dede10b15..a2d0c24ff4c 100644
--- a/csharp/ql/test/query-tests/Security Features/CWE-502/DeserializedDelegate/DeserializedDelegate.cs
+++ b/csharp/ql/test/query-tests/Security Features/CWE-502/DeserializedDelegate/DeserializedDelegate.cs
@@ -11,11 +11,11 @@ class DeserializedDelegate
{
var formatter = new BinaryFormatter();
// BAD
- var a = (Func)formatter.Deserialize(fs);
+ var a = (Func)formatter.Deserialize(fs); // $ Alert[cs/deserialized-delegate]
// BAD
- var b = (Expression>)formatter.Deserialize(fs);
+ var b = (Expression>)formatter.Deserialize(fs); // $ Alert[cs/deserialized-delegate]
// BAD
- var c = (D)formatter.Deserialize(fs);
+ var c = (D)formatter.Deserialize(fs); // $ Alert[cs/deserialized-delegate]
// GOOD
var d = (int)formatter.Deserialize(fs);
}
diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/DeserializedDelegate/DeserializedDelegate.qlref b/csharp/ql/test/query-tests/Security Features/CWE-502/DeserializedDelegate/DeserializedDelegate.qlref
index 913c61338c4..dbfd493cef5 100644
--- a/csharp/ql/test/query-tests/Security Features/CWE-502/DeserializedDelegate/DeserializedDelegate.qlref
+++ b/csharp/ql/test/query-tests/Security Features/CWE-502/DeserializedDelegate/DeserializedDelegate.qlref
@@ -1 +1,4 @@
-Security Features/CWE-502/DeserializedDelegate.ql
\ No newline at end of file
+query: Security Features/CWE-502/DeserializedDelegate.ql
+postprocess:
+ - utils/test/PrettyPrintModels.ql
+ - utils/test/InlineExpectationsTestQuery.ql
diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/DeserializedDelegate/DeserializedDelegateBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/DeserializedDelegate/DeserializedDelegateBad.cs
index 12b2dc76987..48c2ed2b414 100644
--- a/csharp/ql/test/query-tests/Security Features/CWE-502/DeserializedDelegate/DeserializedDelegateBad.cs
+++ b/csharp/ql/test/query-tests/Security Features/CWE-502/DeserializedDelegate/DeserializedDelegateBad.cs
@@ -8,7 +8,7 @@ class Bad
{
var formatter = new BinaryFormatter();
// BAD
- var f = (Func)formatter.Deserialize(fs);
+ var f = (Func)formatter.Deserialize(fs); // $ Alert[cs/deserialized-delegate]
return f();
}
}
diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/BinaryFormatterBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/BinaryFormatterBad.cs
index 1170a37ad3b..7fbe5499dbb 100644
--- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/BinaryFormatterBad.cs
+++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/BinaryFormatterBad.cs
@@ -7,6 +7,6 @@ class BadBinaryFormatter
{
var ds = new BinaryFormatter();
// BAD
- return ds.Deserialize(s);
+ return ds.Deserialize(s); // $ Alert[cs/unsafe-deserialization]
}
}
diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/DataContractJsonSerializerBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/DataContractJsonSerializerBad.cs
index 1256428176c..2e2b80cc25a 100644
--- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/DataContractJsonSerializerBad.cs
+++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/DataContractJsonSerializerBad.cs
@@ -8,6 +8,6 @@ class BadDataContractJsonSerializer
{
var ds = new DataContractJsonSerializer(type);
// BAD
- return ds.ReadObject(s);
+ return ds.ReadObject(s); // $ Alert[cs/unsafe-deserialization]
}
}
diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/DataContractSerializerBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/DataContractSerializerBad.cs
index 35cff0b45f1..e98bd0c0aa0 100644
--- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/DataContractSerializerBad.cs
+++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/DataContractSerializerBad.cs
@@ -8,6 +8,6 @@ class BadDataContractSerializer
{
var ds = new DataContractSerializer(type);
// BAD
- return ds.ReadObject(s);
+ return ds.ReadObject(s); // $ Alert[cs/unsafe-deserialization]
}
}
diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/ResourceReaderBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/ResourceReaderBad.cs
index 2da5dc1aa6a..e39a8776990 100644
--- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/ResourceReaderBad.cs
+++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/ResourceReaderBad.cs
@@ -6,11 +6,11 @@ class BadResourceReader
{
public static void Deserialize(Stream s)
{
- var ds = new ResourceReader(s);
+ var ds = new ResourceReader(s); // $ Alert[cs/unsafe-deserialization]
// BAD
var dict = ds.GetEnumerator();
while (dict.MoveNext())
- Console.WriteLine(" {0}: '{1}' (Type {2})",
+ Console.WriteLine(" {0}: '{1}' (Type {2})",
dict.Key, dict.Value, dict.Value.GetType().Name);
ds.Close();
}
diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/UnsafeDeserialization.qlref b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/UnsafeDeserialization.qlref
index 78efa2399c0..25a133ff8a7 100644
--- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/UnsafeDeserialization.qlref
+++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/UnsafeDeserialization.qlref
@@ -1 +1,4 @@
-Security Features/CWE-502/UnsafeDeserialization.ql
\ No newline at end of file
+query: Security Features/CWE-502/UnsafeDeserialization.ql
+postprocess:
+ - utils/test/PrettyPrintModels.ql
+ - utils/test/InlineExpectationsTestQuery.ql
diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/UnsafeDeserializationBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/UnsafeDeserializationBad.cs
index 385e700a0bf..ce178961b9b 100644
--- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/UnsafeDeserializationBad.cs
+++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/UnsafeDeserializationBad.cs
@@ -6,6 +6,6 @@ class Bad
{
JavaScriptSerializer sr = new JavaScriptSerializer(new SimpleTypeResolver());
// BAD
- return sr.DeserializeObject(s);
+ return sr.DeserializeObject(s); // $ Alert[cs/unsafe-deserialization]
}
}
diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/XmlObjectSerializerBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/XmlObjectSerializerBad.cs
index 4096934da0b..a8e1bc42e2f 100644
--- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/XmlObjectSerializerBad.cs
+++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/XmlObjectSerializerBad.cs
@@ -8,6 +8,6 @@ class BadXmlObjectSerializer
{
XmlObjectSerializer ds = new DataContractSerializer(type);
// BAD
- return ds.ReadObject(s);
+ return ds.ReadObject(s); // $ Alert[cs/unsafe-deserialization]
}
}
diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/XmlSerializerBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/XmlSerializerBad.cs
index 4d32bae9c08..a5f3287cd55 100644
--- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/XmlSerializerBad.cs
+++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/XmlSerializerBad.cs
@@ -8,6 +8,6 @@ class BadXmlSerializer
{
var ds = new XmlSerializer(type);
// BAD
- return ds.Deserialize(s);
+ return ds.Deserialize(s); // $ Alert[cs/unsafe-deserialization]
}
}
diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/BinaryFormatterUntrustedInputBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/BinaryFormatterUntrustedInputBad.cs
index 73c6c35413b..8f19580b68a 100644
--- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/BinaryFormatterUntrustedInputBad.cs
+++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/BinaryFormatterUntrustedInputBad.cs
@@ -1,14 +1,25 @@
-using System.Web.UI.WebControls;
-using System.Runtime.Serialization.Formatters.Binary;
+using System;
using System.IO;
+using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
+using System.Web.UI.WebControls;
-class BadBinaryFormatter
+class BadBinaryFormatter1
{
public static object Deserialize(TextBox textBox)
{
var ds = new BinaryFormatter();
// BAD
- return ds.Deserialize(new MemoryStream(Encoding.UTF8.GetBytes(textBox.Text)));
+ return ds.Deserialize(new MemoryStream(Encoding.UTF8.GetBytes(textBox.Text))); // $ Alert[cs/unsafe-deserialization-untrusted-input]
+ }
+}
+
+class BadBinaryFormatter2
+{
+ public static object Deserialize(TextBox type, TextBox data)
+ {
+ var ds = new BinaryFormatter();
+ // BAD
+ return ds.Deserialize(new MemoryStream(Convert.FromBase64String(data.Text))); // $ Alert[cs/unsafe-deserialization-untrusted-input]
}
}
diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/DataContractJsonSerializerUntrustedInputBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/DataContractJsonSerializerUntrustedInputBad.cs
index 2d3efe3ae26..e1e389c0a67 100644
--- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/DataContractJsonSerializerUntrustedInputBad.cs
+++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/DataContractJsonSerializerUntrustedInputBad.cs
@@ -10,6 +10,6 @@ class BadDataContractJsonSerializer
{
var ds = new DataContractJsonSerializer(Type.GetType(type.Text));
// BAD
- return ds.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(data.Text)));
+ return ds.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(data.Text))); // $ Alert[cs/unsafe-deserialization-untrusted-input]
}
}
diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/DataContractSerializerUntrustedInputBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/DataContractSerializerUntrustedInputBad.cs
index f4f266ed3e0..2e979b2387d 100644
--- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/DataContractSerializerUntrustedInputBad.cs
+++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/DataContractSerializerUntrustedInputBad.cs
@@ -10,6 +10,6 @@ class BadDataContractSerializer
{
var ds = new DataContractSerializer(Type.GetType(type.Text));
// BAD
- return ds.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(data.Text)));
+ return ds.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(data.Text))); // $ Alert[cs/unsafe-deserialization-untrusted-input]
}
}
diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ResourceReaderUntrustedInputBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ResourceReaderUntrustedInputBad.cs
index cd5468afc2d..33ca758ac9c 100644
--- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ResourceReaderUntrustedInputBad.cs
+++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ResourceReaderUntrustedInputBad.cs
@@ -8,11 +8,11 @@ class BadResourceReader
{
public static void Deserialize(TextBox data)
{
- var ds = new ResourceReader(new MemoryStream(Encoding.UTF8.GetBytes(data.Text)));
+ var ds = new ResourceReader(new MemoryStream(Encoding.UTF8.GetBytes(data.Text))); // $ Alert[cs/unsafe-deserialization-untrusted-input]
// BAD
var dict = ds.GetEnumerator();
while (dict.MoveNext())
- Console.WriteLine(" {0}: '{1}' (Type {2})",
+ Console.WriteLine(" {0}: '{1}' (Type {2})",
dict.Key, dict.Value, dict.Value.GetType().Name);
ds.Close();
}
diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInput.expected b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInput.expected
index 37cba1c28bf..c3377fcb04f 100644
--- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInput.expected
+++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInput.expected
@@ -1,5 +1,6 @@
#select
-| BinaryFormatterUntrustedInputBad.cs:12:31:12:84 | object creation of type MemoryStream | BinaryFormatterUntrustedInputBad.cs:12:71:12:77 | access to parameter textBox : TextBox | BinaryFormatterUntrustedInputBad.cs:12:31:12:84 | object creation of type MemoryStream | $@ flows to unsafe deserializer. | BinaryFormatterUntrustedInputBad.cs:12:71:12:77 | access to parameter textBox : TextBox | User-provided data |
+| BinaryFormatterUntrustedInputBad.cs:13:31:13:84 | object creation of type MemoryStream | BinaryFormatterUntrustedInputBad.cs:13:71:13:77 | access to parameter textBox : TextBox | BinaryFormatterUntrustedInputBad.cs:13:31:13:84 | object creation of type MemoryStream | $@ flows to unsafe deserializer. | BinaryFormatterUntrustedInputBad.cs:13:71:13:77 | access to parameter textBox : TextBox | User-provided data |
+| BinaryFormatterUntrustedInputBad.cs:23:31:23:83 | object creation of type MemoryStream | BinaryFormatterUntrustedInputBad.cs:23:73:23:76 | access to parameter data : TextBox | BinaryFormatterUntrustedInputBad.cs:23:31:23:83 | object creation of type MemoryStream | $@ flows to unsafe deserializer. | BinaryFormatterUntrustedInputBad.cs:23:73:23:76 | access to parameter data : TextBox | User-provided data |
| DataContractJsonSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | DataContractJsonSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | $@ flows to unsafe deserializer. | DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | User-provided data |
| DataContractSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | DataContractSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | DataContractSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | $@ flows to unsafe deserializer. | DataContractSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | User-provided data |
| ResourceReaderUntrustedInputBad.cs:11:37:11:87 | object creation of type MemoryStream | ResourceReaderUntrustedInputBad.cs:11:77:11:80 | access to parameter data : TextBox | ResourceReaderUntrustedInputBad.cs:11:37:11:87 | object creation of type MemoryStream | $@ flows to unsafe deserializer. | ResourceReaderUntrustedInputBad.cs:11:77:11:80 | access to parameter data : TextBox | User-provided data |
@@ -7,9 +8,12 @@
| XmlObjectSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | XmlObjectSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | XmlObjectSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | $@ flows to unsafe deserializer. | XmlObjectSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | User-provided data |
| XmlSerializerUntrustedInputBad.cs:13:31:13:81 | object creation of type MemoryStream | XmlSerializerUntrustedInputBad.cs:13:71:13:74 | access to parameter data : TextBox | XmlSerializerUntrustedInputBad.cs:13:31:13:81 | object creation of type MemoryStream | $@ flows to unsafe deserializer. | XmlSerializerUntrustedInputBad.cs:13:71:13:74 | access to parameter data : TextBox | User-provided data |
edges
-| BinaryFormatterUntrustedInputBad.cs:12:48:12:83 | call to method GetBytes : Byte[] | BinaryFormatterUntrustedInputBad.cs:12:31:12:84 | object creation of type MemoryStream | provenance | MaD:1 |
-| BinaryFormatterUntrustedInputBad.cs:12:71:12:77 | access to parameter textBox : TextBox | BinaryFormatterUntrustedInputBad.cs:12:71:12:82 | access to property Text : String | provenance | MaD:3 |
-| BinaryFormatterUntrustedInputBad.cs:12:71:12:82 | access to property Text : String | BinaryFormatterUntrustedInputBad.cs:12:48:12:83 | call to method GetBytes : Byte[] | provenance | MaD:2 |
+| BinaryFormatterUntrustedInputBad.cs:13:48:13:83 | call to method GetBytes : Byte[] | BinaryFormatterUntrustedInputBad.cs:13:31:13:84 | object creation of type MemoryStream | provenance | MaD:1 |
+| BinaryFormatterUntrustedInputBad.cs:13:71:13:77 | access to parameter textBox : TextBox | BinaryFormatterUntrustedInputBad.cs:13:71:13:82 | access to property Text : String | provenance | MaD:3 |
+| BinaryFormatterUntrustedInputBad.cs:13:71:13:82 | access to property Text : String | BinaryFormatterUntrustedInputBad.cs:13:48:13:83 | call to method GetBytes : Byte[] | provenance | MaD:2 |
+| BinaryFormatterUntrustedInputBad.cs:23:48:23:82 | call to method FromBase64String : Byte[] [element] : Object | BinaryFormatterUntrustedInputBad.cs:23:31:23:83 | object creation of type MemoryStream | provenance | MaD:1 |
+| BinaryFormatterUntrustedInputBad.cs:23:73:23:76 | access to parameter data : TextBox | BinaryFormatterUntrustedInputBad.cs:23:73:23:81 | access to property Text : String | provenance | MaD:3 |
+| BinaryFormatterUntrustedInputBad.cs:23:73:23:81 | access to property Text : String | BinaryFormatterUntrustedInputBad.cs:23:48:23:82 | call to method FromBase64String : Byte[] [element] : Object | provenance | MaD:4 |
| DataContractJsonSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | DataContractJsonSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | provenance | MaD:1 |
| DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | provenance | MaD:3 |
| DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:78 | access to property Text : String | DataContractJsonSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | provenance | MaD:2 |
@@ -27,14 +31,19 @@ edges
| XmlSerializerUntrustedInputBad.cs:13:71:13:74 | access to parameter data : TextBox | XmlSerializerUntrustedInputBad.cs:13:71:13:79 | access to property Text : String | provenance | MaD:3 |
| XmlSerializerUntrustedInputBad.cs:13:71:13:79 | access to property Text : String | XmlSerializerUntrustedInputBad.cs:13:48:13:80 | call to method GetBytes : Byte[] | provenance | MaD:2 |
models
-| 1 | Summary: System.IO; MemoryStream; false; MemoryStream; (System.Byte[]); ; Argument[0]; Argument[this]; taint; manual |
+| 1 | Summary: System.IO; MemoryStream; false; MemoryStream; (System.Byte[]); ; Argument[0].Element; Argument[this]; taint; manual |
| 2 | Summary: System.Text; Encoding; true; GetBytes; (System.String); ; Argument[0]; ReturnValue; taint; manual |
| 3 | Summary: System.Web.UI.WebControls; TextBox; false; get_Text; (); ; Argument[this]; ReturnValue; taint; manual |
+| 4 | Summary: System; Convert; false; FromBase64String; (System.String); ; Argument[0]; ReturnValue.Element; taint; manual |
nodes
-| BinaryFormatterUntrustedInputBad.cs:12:31:12:84 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream |
-| BinaryFormatterUntrustedInputBad.cs:12:48:12:83 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] |
-| BinaryFormatterUntrustedInputBad.cs:12:71:12:77 | access to parameter textBox : TextBox | semmle.label | access to parameter textBox : TextBox |
-| BinaryFormatterUntrustedInputBad.cs:12:71:12:82 | access to property Text : String | semmle.label | access to property Text : String |
+| BinaryFormatterUntrustedInputBad.cs:13:31:13:84 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream |
+| BinaryFormatterUntrustedInputBad.cs:13:48:13:83 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] |
+| BinaryFormatterUntrustedInputBad.cs:13:71:13:77 | access to parameter textBox : TextBox | semmle.label | access to parameter textBox : TextBox |
+| BinaryFormatterUntrustedInputBad.cs:13:71:13:82 | access to property Text : String | semmle.label | access to property Text : String |
+| BinaryFormatterUntrustedInputBad.cs:23:31:23:83 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream |
+| BinaryFormatterUntrustedInputBad.cs:23:48:23:82 | call to method FromBase64String : Byte[] [element] : Object | semmle.label | call to method FromBase64String : Byte[] [element] : Object |
+| BinaryFormatterUntrustedInputBad.cs:23:73:23:76 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox |
+| BinaryFormatterUntrustedInputBad.cs:23:73:23:81 | access to property Text : String | semmle.label | access to property Text : String |
| DataContractJsonSerializerUntrustedInputBad.cs:13:30:13:80 | object creation of type MemoryStream | semmle.label | object creation of type MemoryStream |
| DataContractJsonSerializerUntrustedInputBad.cs:13:47:13:79 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] |
| DataContractJsonSerializerUntrustedInputBad.cs:13:70:13:73 | access to parameter data : TextBox | semmle.label | access to parameter data : TextBox |
diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInput.qlref b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInput.qlref
index a1ffb72bf10..195452ad567 100644
--- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInput.qlref
+++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInput.qlref
@@ -1,2 +1,4 @@
query: Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql
-postprocess: utils/test/PrettyPrintModels.ql
+postprocess:
+ - utils/test/PrettyPrintModels.ql
+ - utils/test/InlineExpectationsTestQuery.ql
diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInputBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInputBad.cs
index db2b25097ba..6af634af09c 100644
--- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInputBad.cs
+++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/UnsafeDeserializationUntrustedInputBad.cs
@@ -7,6 +7,6 @@ class Bad
{
JavaScriptSerializer sr = new JavaScriptSerializer(new SimpleTypeResolver());
// BAD
- return sr.DeserializeObject(textBox.Text);
+ return sr.DeserializeObject(textBox.Text); // $ Alert[cs/unsafe-deserialization-untrusted-input]
}
}
diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/XmlObjectSerializerUntrustedInputBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/XmlObjectSerializerUntrustedInputBad.cs
index b525dd28692..c7a0d94cb45 100644
--- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/XmlObjectSerializerUntrustedInputBad.cs
+++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/XmlObjectSerializerUntrustedInputBad.cs
@@ -10,6 +10,6 @@ class BadXmlObjectSerializer
{
XmlObjectSerializer ds = new DataContractSerializer(Type.GetType(type.Text));
// BAD
- return ds.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(data.Text)));
+ return ds.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(data.Text))); // $ Alert[cs/unsafe-deserialization-untrusted-input]
}
}
diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/XmlSerializerUntrustedInputBad.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/XmlSerializerUntrustedInputBad.cs
index f658f2a9e1a..b5299c01f3f 100644
--- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/XmlSerializerUntrustedInputBad.cs
+++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/XmlSerializerUntrustedInputBad.cs
@@ -10,6 +10,6 @@ class BadXmlSerializer
{
var ds = new XmlSerializer(Type.GetType(type.Text));
// BAD
- return ds.Deserialize(new MemoryStream(Encoding.UTF8.GetBytes(data.Text)));
+ return ds.Deserialize(new MemoryStream(Encoding.UTF8.GetBytes(data.Text))); // $ Alert[cs/unsafe-deserialization-untrusted-input]
}
}
diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInputNewtonsoftJson/Test.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInputNewtonsoftJson/Test.cs
index c8c5cbb0098..90bdeef8336 100644
--- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInputNewtonsoftJson/Test.cs
+++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInputNewtonsoftJson/Test.cs
@@ -14,9 +14,9 @@ class Test
public static object Deserialize2(TextBox data)
{
- return JsonConvert.DeserializeObject(data.Text, new JsonSerializerSettings
+ return JsonConvert.DeserializeObject(data.Text, new JsonSerializerSettings // $ Alert[cs/unsafe-deserialization-untrusted-input]
{
- TypeNameHandling = TypeNameHandling.Auto // BAD
+ TypeNameHandling = TypeNameHandling.Auto
});
}
diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInputNewtonsoftJson/UnsafeDeserializationUntrustedInput.qlref b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInputNewtonsoftJson/UnsafeDeserializationUntrustedInput.qlref
index a1ffb72bf10..195452ad567 100644
--- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInputNewtonsoftJson/UnsafeDeserializationUntrustedInput.qlref
+++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInputNewtonsoftJson/UnsafeDeserializationUntrustedInput.qlref
@@ -1,2 +1,4 @@
query: Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql
-postprocess: utils/test/PrettyPrintModels.ql
+postprocess:
+ - utils/test/PrettyPrintModels.ql
+ - utils/test/InlineExpectationsTestQuery.ql
diff --git a/docs/codeql/reusables/download-github-database.rst b/docs/codeql/reusables/download-github-database.rst
index e416d3cd8ec..e2b2303c2fa 100644
--- a/docs/codeql/reusables/download-github-database.rst
+++ b/docs/codeql/reusables/download-github-database.rst
@@ -3,12 +3,12 @@ GitHub stores CodeQL databases for over 200,000 repos on GitHub.com, which you c
You can check if a repository has any CodeQL databases available for download using the ``/repos///code-scanning/codeql/databases`` endpoint.
For example, to check for CodeQL databases using the `GitHub CLI `__ you would run::
- gh api /repos///code-scanning/codeql/databases
+ gh api repos///code-scanning/codeql/databases
This command returns information about any CodeQL databases that are available for a repository, including the language the database represents, and when the database was last updated. If no CodeQL databases are available, the response is empty.
When you have confirmed that a CodeQL database exists for the language you are interested in, you can download it using the following command::
- gh api /repos///code-scanning/codeql/databases/ -H 'Accept: application/zip' > path/to/local/database.zip
+ gh api repos///code-scanning/codeql/databases/ -H 'Accept: application/zip' > path/to/local/database.zip
For more information, see the documentation for the `Get CodeQL database `__ endpoint in the GitHub REST API documentation.
diff --git a/docs/query-metadata-style-guide.md b/docs/query-metadata-style-guide.md
index 18fa5d1880f..f6cc6f883fc 100644
--- a/docs/query-metadata-style-guide.md
+++ b/docs/query-metadata-style-guide.md
@@ -157,7 +157,7 @@ Each code quality related query should have **one** of these two "top-level" cat
* `@tags maintainability`–for queries that detect patterns that make it harder for developers to make changes to the code.
* `@tags reliability`–for queries that detect issues that affect whether the code will perform as expected during execution.
-In addition to the "top-level" categories, we will also add sub-categories to further group code quality related queries:
+In addition to the "top-level" categories, we may also add sub-categories to further group code quality related queries:
* `@tags maintainability`–for queries that detect patterns that make it harder for developers to make changes to the code.
* `@tags readability`–for queries that detect confusing patterns that make it harder for developers to read the code.
@@ -171,6 +171,7 @@ In addition to the "top-level" categories, we will also add sub-categories to fu
* `@tags concurrency`-for queries that detect concurrency related issues such as race conditions, deadlocks, thread safety, etc
* `@tags error-handling`-for queries that detect issues related to unsafe error handling such as uncaught exceptions, etc
+You may use sub-categories from both top-level categories on the same query. However, if you only use sub-categories from a single top-level category, then you must also tag the query with that top-level category.
There are also more specific `@tags` that can be added. See, the following pages for examples of the low-level tags:
diff --git a/go/extractor/go.mod b/go/extractor/go.mod
index 8dce8565a58..927cf8e0512 100644
--- a/go/extractor/go.mod
+++ b/go/extractor/go.mod
@@ -9,8 +9,8 @@ toolchain go1.24.0
// when adding or removing dependencies, run
// bazel mod tidy
require (
- golang.org/x/mod v0.25.0
- golang.org/x/tools v0.34.0
+ golang.org/x/mod v0.26.0
+ golang.org/x/tools v0.35.0
)
-require golang.org/x/sync v0.15.0 // indirect
+require golang.org/x/sync v0.16.0 // indirect
diff --git a/go/extractor/go.sum b/go/extractor/go.sum
index c6a97825c8a..58f0d0b933b 100644
--- a/go/extractor/go.sum
+++ b/go/extractor/go.sum
@@ -1,8 +1,8 @@
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
-golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
-golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
-golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
-golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
-golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
+golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
+golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
+golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
+golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
+golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
+golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
diff --git a/go/ql/lib/change-notes/2025-07-08-request-forgery-sinks.md b/go/ql/lib/change-notes/2025-07-08-request-forgery-sinks.md
new file mode 100644
index 00000000000..6204749d9d6
--- /dev/null
+++ b/go/ql/lib/change-notes/2025-07-08-request-forgery-sinks.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* Added models for the `Head` function and the `Client.Head` method, from the `net/http` package, to the `Http::ClientRequest` class. This means that they will be recognized as sinks for the query `go/request-forgery` and the experimental query `go/ssrf`.
diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplConsistency.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplConsistency.qll
index 58b84985841..aa9c9da1bd1 100644
--- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplConsistency.qll
+++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplConsistency.qll
@@ -4,11 +4,11 @@
*/
private import go
-private import DataFlowImplSpecific
+private import DataFlowImplSpecific as Impl
private import TaintTrackingImplSpecific
private import codeql.dataflow.internal.DataFlowImplConsistency
private import semmle.go.dataflow.internal.DataFlowNodes
-private module Input implements InputSig { }
+private module Input implements InputSig { }
-module Consistency = MakeConsistency;
+module Consistency = MakeConsistency;
diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/NetHttp.qll b/go/ql/lib/semmle/go/frameworks/stdlib/NetHttp.qll
index dded5092bcc..9a917f05ff5 100644
--- a/go/ql/lib/semmle/go/frameworks/stdlib/NetHttp.qll
+++ b/go/ql/lib/semmle/go/frameworks/stdlib/NetHttp.qll
@@ -179,12 +179,11 @@ module NetHttp {
private class RequestCall extends Http::ClientRequest::Range, DataFlow::CallNode {
RequestCall() {
exists(string functionName |
- (
- this.getTarget().hasQualifiedName("net/http", functionName)
- or
- this.getTarget().(Method).hasQualifiedName("net/http", "Client", functionName)
- ) and
- (functionName = "Get" or functionName = "Post" or functionName = "PostForm")
+ this.getTarget().hasQualifiedName("net/http", functionName)
+ or
+ this.getTarget().(Method).hasQualifiedName("net/http", "Client", functionName)
+ |
+ functionName = ["Get", "Head", "Post", "PostForm"]
)
}
diff --git a/go/ql/lib/semmle/go/security/TaintedPathCustomizations.qll b/go/ql/lib/semmle/go/security/TaintedPathCustomizations.qll
index df601ce1eb8..39db60de483 100644
--- a/go/ql/lib/semmle/go/security/TaintedPathCustomizations.qll
+++ b/go/ql/lib/semmle/go/security/TaintedPathCustomizations.qll
@@ -243,4 +243,20 @@ module TaintedPath {
override predicate checks(Expr e, boolean branch) { regexpFunctionChecksExpr(this, e, branch) }
}
+
+ /**
+ * A call of the form `filepath.IsLocal(path)` considered as a sanitizer guard for `path`.
+ */
+ class IsLocalCheck extends SanitizerGuard, DataFlow::CallNode {
+ IsLocalCheck() {
+ exists(Function f |
+ f.hasQualifiedName("path/filepath", "IsLocal") and
+ this = f.getACall()
+ )
+ }
+
+ override predicate checks(Expr e, boolean branch) {
+ e = this.getArgument(0).asExpr() and branch = true
+ }
+ }
}
diff --git a/go/ql/src/change-notes/2025-07-15-islocal-sanitizer.md b/go/ql/src/change-notes/2025-07-15-islocal-sanitizer.md
new file mode 100644
index 00000000000..35f04aacb58
--- /dev/null
+++ b/go/ql/src/change-notes/2025-07-15-islocal-sanitizer.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* `filepath.IsLocal` is now recognised as a sanitizer against path-traversal and related vulnerabilities.
diff --git a/go/ql/test/query-tests/Security/CWE-022/TaintedPath.go b/go/ql/test/query-tests/Security/CWE-022/TaintedPath.go
index e6a1c49f4c5..82c0592a516 100644
--- a/go/ql/test/query-tests/Security/CWE-022/TaintedPath.go
+++ b/go/ql/test/query-tests/Security/CWE-022/TaintedPath.go
@@ -93,4 +93,10 @@ func handler(w http.ResponseWriter, r *http.Request) {
}
data, _ = ioutil.ReadFile(part.FileName())
+
+ // GOOD: An attempt has been made to prevent path traversal
+ if filepath.IsLocal(tainted_path) {
+ data, _ = ioutil.ReadFile(tainted_path)
+ w.Write(data)
+ }
}
diff --git a/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected b/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected
index 76097b7a5c0..696d8dd700b 100644
--- a/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected
+++ b/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected
@@ -1,12 +1,18 @@
#select
| RequestForgery.go:11:15:11:66 | call to Get | RequestForgery.go:8:12:8:34 | call to FormValue | RequestForgery.go:11:24:11:65 | ...+... | The $@ of this request depends on a $@. | RequestForgery.go:11:24:11:65 | ...+... | URL | RequestForgery.go:8:12:8:34 | call to FormValue | user-provided value |
| tst.go:14:2:14:18 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:14:11:14:17 | tainted | The $@ of this request depends on a $@. | tst.go:14:11:14:17 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
+| tst.go:16:2:16:19 | call to Head | tst.go:10:13:10:35 | call to FormValue | tst.go:16:12:16:18 | tainted | The $@ of this request depends on a $@. | tst.go:16:12:16:18 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
| tst.go:18:2:18:38 | call to Post | tst.go:10:13:10:35 | call to FormValue | tst.go:18:12:18:18 | tainted | The $@ of this request depends on a $@. | tst.go:18:12:18:18 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
-| tst.go:22:2:22:14 | call to Do | tst.go:10:13:10:35 | call to FormValue | tst.go:21:34:21:40 | tainted | The $@ of this request depends on a $@. | tst.go:21:34:21:40 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
-| tst.go:25:2:25:14 | call to Do | tst.go:10:13:10:35 | call to FormValue | tst.go:24:66:24:72 | tainted | The $@ of this request depends on a $@. | tst.go:24:66:24:72 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
-| tst.go:27:2:27:30 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:27:11:27:29 | ...+... | The $@ of this request depends on a $@. | tst.go:27:11:27:29 | ...+... | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
-| tst.go:29:2:29:41 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:29:11:29:40 | ...+... | The $@ of this request depends on a $@. | tst.go:29:11:29:40 | ...+... | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
-| tst.go:37:2:37:21 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:37:11:37:20 | call to String | The $@ of this request depends on a $@. | tst.go:37:11:37:20 | call to String | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
+| tst.go:20:2:20:28 | call to PostForm | tst.go:10:13:10:35 | call to FormValue | tst.go:20:16:20:22 | tainted | The $@ of this request depends on a $@. | tst.go:20:16:20:22 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
+| tst.go:24:2:24:15 | call to Do | tst.go:10:13:10:35 | call to FormValue | tst.go:23:35:23:41 | tainted | The $@ of this request depends on a $@. | tst.go:23:35:23:41 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
+| tst.go:27:2:27:15 | call to Do | tst.go:10:13:10:35 | call to FormValue | tst.go:26:68:26:74 | tainted | The $@ of this request depends on a $@. | tst.go:26:68:26:74 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
+| tst.go:29:2:29:20 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:29:13:29:19 | tainted | The $@ of this request depends on a $@. | tst.go:29:13:29:19 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
+| tst.go:30:2:30:21 | call to Head | tst.go:10:13:10:35 | call to FormValue | tst.go:30:14:30:20 | tainted | The $@ of this request depends on a $@. | tst.go:30:14:30:20 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
+| tst.go:31:2:31:40 | call to Post | tst.go:10:13:10:35 | call to FormValue | tst.go:31:14:31:20 | tainted | The $@ of this request depends on a $@. | tst.go:31:14:31:20 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
+| tst.go:32:2:32:30 | call to PostForm | tst.go:10:13:10:35 | call to FormValue | tst.go:32:18:32:24 | tainted | The $@ of this request depends on a $@. | tst.go:32:18:32:24 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
+| tst.go:34:2:34:30 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:34:11:34:29 | ...+... | The $@ of this request depends on a $@. | tst.go:34:11:34:29 | ...+... | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
+| tst.go:36:2:36:41 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:36:11:36:40 | ...+... | The $@ of this request depends on a $@. | tst.go:36:11:36:40 | ...+... | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
+| tst.go:44:2:44:21 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:44:11:44:20 | call to String | The $@ of this request depends on a $@. | tst.go:44:11:44:20 | call to String | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value |
| websocket.go:65:12:65:53 | call to Dial | websocket.go:60:21:60:31 | call to Referer | websocket.go:65:27:65:40 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:65:27:65:40 | untrustedInput | WebSocket URL | websocket.go:60:21:60:31 | call to Referer | user-provided value |
| websocket.go:79:13:79:40 | call to DialConfig | websocket.go:74:21:74:31 | call to Referer | websocket.go:78:36:78:49 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:78:36:78:49 | untrustedInput | WebSocket URL | websocket.go:74:21:74:31 | call to Referer | user-provided value |
| websocket.go:91:3:91:50 | call to Dial | websocket.go:88:21:88:31 | call to Referer | websocket.go:91:31:91:44 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:91:31:91:44 | untrustedInput | WebSocket URL | websocket.go:88:21:88:31 | call to Referer | user-provided value |
@@ -14,27 +20,33 @@
| websocket.go:129:3:129:62 | call to DialContext | websocket.go:126:21:126:31 | call to Referer | websocket.go:129:38:129:51 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:129:38:129:51 | untrustedInput | WebSocket URL | websocket.go:126:21:126:31 | call to Referer | user-provided value |
| websocket.go:155:3:155:45 | call to Dial | websocket.go:154:21:154:31 | call to Referer | websocket.go:155:31:155:44 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:155:31:155:44 | untrustedInput | WebSocket URL | websocket.go:154:21:154:31 | call to Referer | user-provided value |
| websocket.go:162:3:162:45 | call to Dial | websocket.go:160:21:160:31 | call to Referer | websocket.go:162:31:162:44 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:162:31:162:44 | untrustedInput | WebSocket URL | websocket.go:160:21:160:31 | call to Referer | user-provided value |
-| websocket.go:197:3:197:32 | call to BuildProxy | websocket.go:195:21:195:31 | call to Referer | websocket.go:197:18:197:31 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:197:18:197:31 | untrustedInput | WebSocket URL | websocket.go:195:21:195:31 | call to Referer | user-provided value |
-| websocket.go:204:3:204:25 | call to New | websocket.go:202:21:202:31 | call to Referer | websocket.go:204:11:204:24 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:204:11:204:24 | untrustedInput | WebSocket URL | websocket.go:202:21:202:31 | call to Referer | user-provided value |
+| websocket.go:197:7:197:36 | call to BuildProxy | websocket.go:195:21:195:31 | call to Referer | websocket.go:197:22:197:35 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:197:22:197:35 | untrustedInput | WebSocket URL | websocket.go:195:21:195:31 | call to Referer | user-provided value |
+| websocket.go:204:7:204:29 | call to New | websocket.go:202:21:202:31 | call to Referer | websocket.go:204:15:204:28 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:204:15:204:28 | untrustedInput | WebSocket URL | websocket.go:202:21:202:31 | call to Referer | user-provided value |
edges
| RequestForgery.go:8:12:8:34 | call to FormValue | RequestForgery.go:11:24:11:65 | ...+... | provenance | Src:MaD:1 |
| tst.go:10:13:10:35 | call to FormValue | tst.go:14:11:14:17 | tainted | provenance | Src:MaD:1 |
+| tst.go:10:13:10:35 | call to FormValue | tst.go:16:12:16:18 | tainted | provenance | Src:MaD:1 |
| tst.go:10:13:10:35 | call to FormValue | tst.go:18:12:18:18 | tainted | provenance | Src:MaD:1 |
-| tst.go:10:13:10:35 | call to FormValue | tst.go:21:34:21:40 | tainted | provenance | Src:MaD:1 |
-| tst.go:10:13:10:35 | call to FormValue | tst.go:24:66:24:72 | tainted | provenance | Src:MaD:1 |
-| tst.go:10:13:10:35 | call to FormValue | tst.go:27:11:27:29 | ...+... | provenance | Src:MaD:1 |
-| tst.go:10:13:10:35 | call to FormValue | tst.go:29:11:29:40 | ...+... | provenance | Src:MaD:1 |
-| tst.go:10:13:10:35 | call to FormValue | tst.go:36:11:36:17 | tainted | provenance | Src:MaD:1 |
-| tst.go:35:2:35:2 | definition of u [pointer] | tst.go:36:2:36:2 | u [pointer] | provenance | |
-| tst.go:36:2:36:2 | implicit dereference | tst.go:35:2:35:2 | definition of u [pointer] | provenance | |
-| tst.go:36:2:36:2 | implicit dereference | tst.go:36:2:36:2 | u | provenance | |
-| tst.go:36:2:36:2 | implicit dereference | tst.go:37:11:37:11 | u | provenance | |
-| tst.go:36:2:36:2 | u | tst.go:36:2:36:2 | implicit dereference | provenance | |
-| tst.go:36:2:36:2 | u | tst.go:37:11:37:11 | u | provenance | |
-| tst.go:36:2:36:2 | u [pointer] | tst.go:36:2:36:2 | implicit dereference | provenance | |
-| tst.go:36:11:36:17 | tainted | tst.go:36:2:36:2 | u | provenance | Config |
-| tst.go:36:11:36:17 | tainted | tst.go:37:11:37:11 | u | provenance | Config |
-| tst.go:37:11:37:11 | u | tst.go:37:11:37:20 | call to String | provenance | MaD:3 |
+| tst.go:10:13:10:35 | call to FormValue | tst.go:20:16:20:22 | tainted | provenance | Src:MaD:1 |
+| tst.go:10:13:10:35 | call to FormValue | tst.go:23:35:23:41 | tainted | provenance | Src:MaD:1 |
+| tst.go:10:13:10:35 | call to FormValue | tst.go:26:68:26:74 | tainted | provenance | Src:MaD:1 |
+| tst.go:10:13:10:35 | call to FormValue | tst.go:29:13:29:19 | tainted | provenance | Src:MaD:1 |
+| tst.go:10:13:10:35 | call to FormValue | tst.go:30:14:30:20 | tainted | provenance | Src:MaD:1 |
+| tst.go:10:13:10:35 | call to FormValue | tst.go:31:14:31:20 | tainted | provenance | Src:MaD:1 |
+| tst.go:10:13:10:35 | call to FormValue | tst.go:32:18:32:24 | tainted | provenance | Src:MaD:1 |
+| tst.go:10:13:10:35 | call to FormValue | tst.go:34:11:34:29 | ...+... | provenance | Src:MaD:1 |
+| tst.go:10:13:10:35 | call to FormValue | tst.go:36:11:36:40 | ...+... | provenance | Src:MaD:1 |
+| tst.go:10:13:10:35 | call to FormValue | tst.go:43:11:43:17 | tainted | provenance | Src:MaD:1 |
+| tst.go:42:2:42:2 | definition of u [pointer] | tst.go:43:2:43:2 | u [pointer] | provenance | |
+| tst.go:43:2:43:2 | implicit dereference | tst.go:42:2:42:2 | definition of u [pointer] | provenance | |
+| tst.go:43:2:43:2 | implicit dereference | tst.go:43:2:43:2 | u | provenance | |
+| tst.go:43:2:43:2 | implicit dereference | tst.go:44:11:44:11 | u | provenance | |
+| tst.go:43:2:43:2 | u | tst.go:43:2:43:2 | implicit dereference | provenance | |
+| tst.go:43:2:43:2 | u | tst.go:44:11:44:11 | u | provenance | |
+| tst.go:43:2:43:2 | u [pointer] | tst.go:43:2:43:2 | implicit dereference | provenance | |
+| tst.go:43:11:43:17 | tainted | tst.go:43:2:43:2 | u | provenance | Config |
+| tst.go:43:11:43:17 | tainted | tst.go:44:11:44:11 | u | provenance | Config |
+| tst.go:44:11:44:11 | u | tst.go:44:11:44:20 | call to String | provenance | MaD:3 |
| websocket.go:60:21:60:31 | call to Referer | websocket.go:65:27:65:40 | untrustedInput | provenance | Src:MaD:2 |
| websocket.go:74:21:74:31 | call to Referer | websocket.go:78:36:78:49 | untrustedInput | provenance | Src:MaD:2 |
| websocket.go:88:21:88:31 | call to Referer | websocket.go:91:31:91:44 | untrustedInput | provenance | Src:MaD:2 |
@@ -42,8 +54,8 @@ edges
| websocket.go:126:21:126:31 | call to Referer | websocket.go:129:38:129:51 | untrustedInput | provenance | Src:MaD:2 |
| websocket.go:154:21:154:31 | call to Referer | websocket.go:155:31:155:44 | untrustedInput | provenance | Src:MaD:2 |
| websocket.go:160:21:160:31 | call to Referer | websocket.go:162:31:162:44 | untrustedInput | provenance | Src:MaD:2 |
-| websocket.go:195:21:195:31 | call to Referer | websocket.go:197:18:197:31 | untrustedInput | provenance | Src:MaD:2 |
-| websocket.go:202:21:202:31 | call to Referer | websocket.go:204:11:204:24 | untrustedInput | provenance | Src:MaD:2 |
+| websocket.go:195:21:195:31 | call to Referer | websocket.go:197:22:197:35 | untrustedInput | provenance | Src:MaD:2 |
+| websocket.go:202:21:202:31 | call to Referer | websocket.go:204:15:204:28 | untrustedInput | provenance | Src:MaD:2 |
models
| 1 | Source: net/http; Request; true; FormValue; ; ; ReturnValue; remote; manual |
| 2 | Source: net/http; Request; true; Referer; ; ; ReturnValue; remote; manual |
@@ -53,18 +65,24 @@ nodes
| RequestForgery.go:11:24:11:65 | ...+... | semmle.label | ...+... |
| tst.go:10:13:10:35 | call to FormValue | semmle.label | call to FormValue |
| tst.go:14:11:14:17 | tainted | semmle.label | tainted |
+| tst.go:16:12:16:18 | tainted | semmle.label | tainted |
| tst.go:18:12:18:18 | tainted | semmle.label | tainted |
-| tst.go:21:34:21:40 | tainted | semmle.label | tainted |
-| tst.go:24:66:24:72 | tainted | semmle.label | tainted |
-| tst.go:27:11:27:29 | ...+... | semmle.label | ...+... |
-| tst.go:29:11:29:40 | ...+... | semmle.label | ...+... |
-| tst.go:35:2:35:2 | definition of u [pointer] | semmle.label | definition of u [pointer] |
-| tst.go:36:2:36:2 | implicit dereference | semmle.label | implicit dereference |
-| tst.go:36:2:36:2 | u | semmle.label | u |
-| tst.go:36:2:36:2 | u [pointer] | semmle.label | u [pointer] |
-| tst.go:36:11:36:17 | tainted | semmle.label | tainted |
-| tst.go:37:11:37:11 | u | semmle.label | u |
-| tst.go:37:11:37:20 | call to String | semmle.label | call to String |
+| tst.go:20:16:20:22 | tainted | semmle.label | tainted |
+| tst.go:23:35:23:41 | tainted | semmle.label | tainted |
+| tst.go:26:68:26:74 | tainted | semmle.label | tainted |
+| tst.go:29:13:29:19 | tainted | semmle.label | tainted |
+| tst.go:30:14:30:20 | tainted | semmle.label | tainted |
+| tst.go:31:14:31:20 | tainted | semmle.label | tainted |
+| tst.go:32:18:32:24 | tainted | semmle.label | tainted |
+| tst.go:34:11:34:29 | ...+... | semmle.label | ...+... |
+| tst.go:36:11:36:40 | ...+... | semmle.label | ...+... |
+| tst.go:42:2:42:2 | definition of u [pointer] | semmle.label | definition of u [pointer] |
+| tst.go:43:2:43:2 | implicit dereference | semmle.label | implicit dereference |
+| tst.go:43:2:43:2 | u | semmle.label | u |
+| tst.go:43:2:43:2 | u [pointer] | semmle.label | u [pointer] |
+| tst.go:43:11:43:17 | tainted | semmle.label | tainted |
+| tst.go:44:11:44:11 | u | semmle.label | u |
+| tst.go:44:11:44:20 | call to String | semmle.label | call to String |
| websocket.go:60:21:60:31 | call to Referer | semmle.label | call to Referer |
| websocket.go:65:27:65:40 | untrustedInput | semmle.label | untrustedInput |
| websocket.go:74:21:74:31 | call to Referer | semmle.label | call to Referer |
@@ -80,7 +98,7 @@ nodes
| websocket.go:160:21:160:31 | call to Referer | semmle.label | call to Referer |
| websocket.go:162:31:162:44 | untrustedInput | semmle.label | untrustedInput |
| websocket.go:195:21:195:31 | call to Referer | semmle.label | call to Referer |
-| websocket.go:197:18:197:31 | untrustedInput | semmle.label | untrustedInput |
+| websocket.go:197:22:197:35 | untrustedInput | semmle.label | untrustedInput |
| websocket.go:202:21:202:31 | call to Referer | semmle.label | call to Referer |
-| websocket.go:204:11:204:24 | untrustedInput | semmle.label | untrustedInput |
+| websocket.go:204:15:204:28 | untrustedInput | semmle.label | untrustedInput |
subpaths
diff --git a/go/ql/test/query-tests/Security/CWE-918/RequestForgery.go b/go/ql/test/query-tests/Security/CWE-918/RequestForgery.go
index c88e9dc5f74..ab8f907c58b 100644
--- a/go/ql/test/query-tests/Security/CWE-918/RequestForgery.go
+++ b/go/ql/test/query-tests/Security/CWE-918/RequestForgery.go
@@ -5,10 +5,10 @@ import (
)
func handler(w http.ResponseWriter, req *http.Request) {
- target := req.FormValue("target")
+ target := req.FormValue("target") // $ Source
// BAD: `target` is controlled by the attacker
- resp, err := http.Get("https://" + target + ".example.com/data/")
+ resp, err := http.Get("https://" + target + ".example.com/data/") // $ Alert
if err != nil {
// error handling
}
diff --git a/go/ql/test/query-tests/Security/CWE-918/RequestForgery.qlref b/go/ql/test/query-tests/Security/CWE-918/RequestForgery.qlref
index 061679da228..760862973f1 100644
--- a/go/ql/test/query-tests/Security/CWE-918/RequestForgery.qlref
+++ b/go/ql/test/query-tests/Security/CWE-918/RequestForgery.qlref
@@ -1,2 +1,4 @@
query: Security/CWE-918/RequestForgery.ql
-postprocess: utils/test/PrettyPrintModels.ql
+postprocess:
+ - utils/test/PrettyPrintModels.ql
+ - utils/test/InlineExpectationsTestQuery.ql
diff --git a/go/ql/test/query-tests/Security/CWE-918/tst.go b/go/ql/test/query-tests/Security/CWE-918/tst.go
index 0e04429580c..44a172ddad0 100644
--- a/go/ql/test/query-tests/Security/CWE-918/tst.go
+++ b/go/ql/test/query-tests/Security/CWE-918/tst.go
@@ -7,26 +7,33 @@ import (
)
func handler2(w http.ResponseWriter, req *http.Request) {
- tainted := req.FormValue("target")
+ tainted := req.FormValue("target") // $ Source
http.Get("example.com") // OK
- http.Get(tainted) // Not OK
+ http.Get(tainted) // $ Alert
- http.Head(tainted) // OK
+ http.Head(tainted) // $ Alert
- http.Post(tainted, "text/basic", nil) // Not OK
+ http.Post(tainted, "text/basic", nil) // $ Alert
+
+ http.PostForm(tainted, nil) // $ Alert
client := &http.Client{}
- rq, _ := http.NewRequest("GET", tainted, nil)
- client.Do(rq) // Not OK
+ rq1, _ := http.NewRequest("GET", tainted, nil) // $ Sink
+ client.Do(rq1) // $ Alert
- rq, _ = http.NewRequestWithContext(context.Background(), "GET", tainted, nil)
- client.Do(rq) // Not OK
+ rq2, _ := http.NewRequestWithContext(context.Background(), "GET", tainted, nil) // $ Sink
+ client.Do(rq2) // $ Alert
- http.Get("http://" + tainted) // Not OK
+ client.Get(tainted) // $ Alert
+ client.Head(tainted) // $ Alert
+ client.Post(tainted, "text/basic", nil) // $ Alert
+ client.PostForm(tainted, nil) // $ Alert
- http.Get("http://example.com" + tainted) // Not OK
+ http.Get("http://" + tainted) // $ Alert
+
+ http.Get("http://example.com" + tainted) // $ Alert
http.Get("http://example.com/" + tainted) // OK
@@ -34,7 +41,7 @@ func handler2(w http.ResponseWriter, req *http.Request) {
u, _ := url.Parse("http://example.com/relative-path")
u.Host = tainted
- http.Get(u.String()) // Not OK
+ http.Get(u.String()) // $ Alert
}
func main() {
diff --git a/go/ql/test/query-tests/Security/CWE-918/websocket.go b/go/ql/test/query-tests/Security/CWE-918/websocket.go
index 328200770ae..15edef6b6cc 100644
--- a/go/ql/test/query-tests/Security/CWE-918/websocket.go
+++ b/go/ql/test/query-tests/Security/CWE-918/websocket.go
@@ -57,12 +57,12 @@ func test() {
// x net websocket dial bad
http.HandleFunc("/ex2", func(w http.ResponseWriter, r *http.Request) {
- untrustedInput := r.Referer()
+ untrustedInput := r.Referer() // $ Source
origin := "http://localhost/"
// bad as input is directly passed to dial function
- ws, _ := websocket.Dial(untrustedInput, "", origin)
+ ws, _ := websocket.Dial(untrustedInput, "", origin) // $ Alert
var msg = make([]byte, 512)
var n int
n, _ = ws.Read(msg)
@@ -71,12 +71,12 @@ func test() {
// x net websocket dialConfig bad
http.HandleFunc("/ex3", func(w http.ResponseWriter, r *http.Request) {
- untrustedInput := r.Referer()
+ untrustedInput := r.Referer() // $ Source
origin := "http://localhost/"
// bad as input is directly used
- config, _ := websocket.NewConfig(untrustedInput, origin) // good
- ws2, _ := websocket.DialConfig(config)
+ config, _ := websocket.NewConfig(untrustedInput, origin) // $ Sink
+ ws2, _ := websocket.DialConfig(config) // $ Alert
var msg = make([]byte, 512)
var n int
n, _ = ws2.Read(msg)
@@ -85,10 +85,10 @@ func test() {
// nhooyr websocket dial bad
http.HandleFunc("/ex4", func(w http.ResponseWriter, r *http.Request) {
- untrustedInput := r.Referer()
+ untrustedInput := r.Referer() // $ Source
// bad as input is used directly
- nhooyr.Dial(context.TODO(), untrustedInput, nil)
+ nhooyr.Dial(context.TODO(), untrustedInput, nil) // $ Alert
w.WriteHeader(500)
})
@@ -104,10 +104,10 @@ func test() {
// gorilla websocket Dialer.Dial bad
http.HandleFunc("/ex6", func(w http.ResponseWriter, r *http.Request) {
- untrustedInput := r.Referer()
+ untrustedInput := r.Referer() // $ Source
dialer := gorilla.Dialer{}
- dialer.Dial(untrustedInput, r.Header)
+ dialer.Dial(untrustedInput, r.Header) // $ Alert
})
// gorilla websocket Dialer.Dial good
@@ -123,10 +123,10 @@ func test() {
// gorilla websocket Dialer.DialContext bad
http.HandleFunc("/ex8", func(w http.ResponseWriter, r *http.Request) {
- untrustedInput := r.Referer()
+ untrustedInput := r.Referer() // $ Source
dialer := gorilla.Dialer{}
- dialer.DialContext(context.TODO(), untrustedInput, r.Header)
+ dialer.DialContext(context.TODO(), untrustedInput, r.Header) // $ Alert
})
// gorilla websocket Dialer.DialContext good
@@ -151,22 +151,22 @@ func test() {
// gobwas websocket Dial bad
http.HandleFunc("/ex11", func(w http.ResponseWriter, r *http.Request) {
- untrustedInput := r.Referer()
- gobwas.Dial(context.TODO(), untrustedInput)
+ untrustedInput := r.Referer() // $ Source
+ gobwas.Dial(context.TODO(), untrustedInput) // $ Alert
})
// gobwas websocket Dialer.Dial bad
http.HandleFunc("/ex12", func(w http.ResponseWriter, r *http.Request) {
- untrustedInput := r.Referer()
+ untrustedInput := r.Referer() // $ Source
dialer := gobwas.Dialer{}
- dialer.Dial(context.TODO(), untrustedInput)
+ dialer.Dial(context.TODO(), untrustedInput) // $ Alert
})
// gobwas websocket Dialer.Dial good
http.HandleFunc("/ex12", func(w http.ResponseWriter, r *http.Request) {
untrustedInput := r.Referer()
- if "localhost" == untrustedInput {
+ if untrustedInput == "localhost" {
dialer := gobwas.Dialer{}
dialer.Dial(context.TODO(), untrustedInput)
}
@@ -176,8 +176,8 @@ func test() {
http.HandleFunc("/ex13", func(w http.ResponseWriter, r *http.Request) {
untrustedInput := r.Referer()
- if "localhost" == untrustedInput {
- sac.New(untrustedInput)
+ if untrustedInput == "localhost" {
+ _ = sac.New(untrustedInput)
}
})
@@ -185,23 +185,23 @@ func test() {
http.HandleFunc("/ex14", func(w http.ResponseWriter, r *http.Request) {
untrustedInput := r.Referer()
- if "localhost" == untrustedInput {
- sac.BuildProxy(untrustedInput)
+ if untrustedInput == "localhost" {
+ _ = sac.BuildProxy(untrustedInput)
}
})
// sac007 websocket BuildProxy bad
http.HandleFunc("/ex15", func(w http.ResponseWriter, r *http.Request) {
- untrustedInput := r.Referer()
+ untrustedInput := r.Referer() // $ Source
- sac.BuildProxy(untrustedInput)
+ _ = sac.BuildProxy(untrustedInput) // $ Alert
})
// sac007 websocket New bad
http.HandleFunc("/ex16", func(w http.ResponseWriter, r *http.Request) {
- untrustedInput := r.Referer()
+ untrustedInput := r.Referer() // $ Source
- sac.New(untrustedInput)
+ _ = sac.New(untrustedInput) // $ Alert
})
log.Println(http.ListenAndServe(":80", nil))
diff --git a/java/kotlin-extractor/generate_dbscheme.py b/java/kotlin-extractor/generate_dbscheme.py
index be0c5622ed1..2f839158d9a 100755
--- a/java/kotlin-extractor/generate_dbscheme.py
+++ b/java/kotlin-extractor/generate_dbscheme.py
@@ -35,10 +35,10 @@ def parse_dbscheme(filename):
unions[name] = typs
# tables
- for relname, body in re.findall('\n([\w_]+)(\([^)]*\))',
+ for relname, body in re.findall(r'\n([\w_]+)(\([^)]*\))',
dbscheme,
flags=re.DOTALL):
- columns = list(re.findall('(\S+)\s*:\s*([^\s,]+)(?:\s+(ref)|)', body))
+ columns = list(re.findall(r'(\S+)\s*:\s*([^\s,]+)(?:\s+(ref)|)', body))
tables[relname] = columns
parse_dbscheme(dbscheme)
diff --git a/java/ql/integration-tests/java/query-suite/java-code-quality-extended.qls.expected b/java/ql/integration-tests/java/query-suite/java-code-quality-extended.qls.expected
index aed5d91d5a3..7a1a986b2aa 100644
--- a/java/ql/integration-tests/java/query-suite/java-code-quality-extended.qls.expected
+++ b/java/ql/integration-tests/java/query-suite/java-code-quality-extended.qls.expected
@@ -6,6 +6,7 @@ ql/java/ql/src/Compatibility/JDK9/UnderscoreIdentifier.ql
ql/java/ql/src/DeadCode/UselessParameter.ql
ql/java/ql/src/Language Abuse/EmptyMethod.ql
ql/java/ql/src/Language Abuse/IterableIterator.ql
+ql/java/ql/src/Language Abuse/LabelInSwitch.ql
ql/java/ql/src/Language Abuse/TypeVariableHidesType.ql
ql/java/ql/src/Language Abuse/UselessNullCheck.ql
ql/java/ql/src/Language Abuse/UselessTypeTest.ql
diff --git a/java/ql/integration-tests/java/query-suite/java-code-quality.qls.expected b/java/ql/integration-tests/java/query-suite/java-code-quality.qls.expected
index 1f2ebbfe7aa..17253dbe0f8 100644
--- a/java/ql/integration-tests/java/query-suite/java-code-quality.qls.expected
+++ b/java/ql/integration-tests/java/query-suite/java-code-quality.qls.expected
@@ -5,6 +5,7 @@ ql/java/ql/src/Compatibility/JDK9/JdkInternalAccess.ql
ql/java/ql/src/Compatibility/JDK9/UnderscoreIdentifier.ql
ql/java/ql/src/DeadCode/UselessParameter.ql
ql/java/ql/src/Language Abuse/IterableIterator.ql
+ql/java/ql/src/Language Abuse/LabelInSwitch.ql
ql/java/ql/src/Language Abuse/UselessNullCheck.ql
ql/java/ql/src/Language Abuse/UselessTypeTest.ql
ql/java/ql/src/Language Abuse/WrappedIterator.ql
diff --git a/java/ql/integration-tests/kotlin/linux/custom_plugin/plugin/BUILD.bazel b/java/ql/integration-tests/kotlin/linux/custom_plugin/plugin/BUILD.bazel
index 3e5195df88c..2ee3d63e3ec 100644
--- a/java/ql/integration-tests/kotlin/linux/custom_plugin/plugin/BUILD.bazel
+++ b/java/ql/integration-tests/kotlin/linux/custom_plugin/plugin/BUILD.bazel
@@ -17,7 +17,10 @@ kt_jvm_library(
srcs = ["Plugin.kt"],
kotlinc_opts = ":kotlinc-options",
module_name = "test",
- resource_strip_prefix = "%s/resources" % package_name(),
+ resource_strip_prefix = "../%s/%s/resources" % (
+ repo_name(),
+ package_name(),
+ ),
resources = glob(["resources/**"]),
deps = [
"@kotlin-compiler-%s" % _version,
diff --git a/java/ql/integration-tests/kotlin/linux/custom_plugin/test.py b/java/ql/integration-tests/kotlin/linux/custom_plugin/test.py
index 71b6514059f..f9da9268386 100644
--- a/java/ql/integration-tests/kotlin/linux/custom_plugin/test.py
+++ b/java/ql/integration-tests/kotlin/linux/custom_plugin/test.py
@@ -10,20 +10,15 @@ def test(codeql, java_full, cwd, semmle_code_dir, test_dir):
commands.run(
[
f"{semmle_code_dir}/tools/bazel",
- f"--output_user_root={build_dir}",
"--max_idle_secs=1",
"build",
- "//java/ql/integration-tests/kotlin/linux/custom_plugin/plugin",
- "--spawn_strategy=local",
- "--nouse_action_cache",
- "--noremote_accept_cached",
- "--noremote_upload_local_results",
- f'--symlink_prefix={cwd / "bazel-"}',
+ "@codeql//java/ql/integration-tests/kotlin/linux/custom_plugin/plugin",
],
- _cwd=test_dir,
+ _cwd=semmle_code_dir,
+ _env={"CODEQL_BAZEL_REMOTE_CACHE": "false"},
)
shutil.copy(
- "bazel-bin/java/ql/integration-tests/kotlin/linux/custom_plugin/plugin/plugin.jar",
+ f"{semmle_code_dir}/bazel-bin/external/ql+/java/ql/integration-tests/kotlin/linux/custom_plugin/plugin/plugin.jar",
"plugin.jar",
)
codeql.database.create(
diff --git a/java/ql/lib/change-notes/2025-07-11-unsafe-deserialization-extra-sink.md b/java/ql/lib/change-notes/2025-07-11-unsafe-deserialization-extra-sink.md
new file mode 100644
index 00000000000..26f745a2bb7
--- /dev/null
+++ b/java/ql/lib/change-notes/2025-07-11-unsafe-deserialization-extra-sink.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* The qualifiers of a calls to `readObject` on any classes that implement `java.io.ObjectInput` are now recognised as sinks for `java/unsafe-deserialization`. Previously this was only the case for classes which extend `java.io.ObjectInputStream`.
diff --git a/java/ql/lib/change-notes/2025-07-16-models-as-data-unsafe-deserialization-sinks.md b/java/ql/lib/change-notes/2025-07-16-models-as-data-unsafe-deserialization-sinks.md
new file mode 100644
index 00000000000..91485615962
--- /dev/null
+++ b/java/ql/lib/change-notes/2025-07-16-models-as-data-unsafe-deserialization-sinks.md
@@ -0,0 +1,4 @@
+---
+category: feature
+---
+* You can now add sinks for the query "Deserialization of user-controlled data" (`java/unsafe-deserialization`) using [data extensions](https://codeql.github.com/docs/codeql-language-guides/customizing-library-models-for-java-and-kotlin/#extensible-predicates-used-to-create-custom-models-in-java-and-kotlin) by extending `sinkModel` and using the kind "unsafe-deserialization". The existing sinks which do not require extra logic to determine if they are unsafe are now defined in this way.
diff --git a/java/ql/lib/change-notes/2025-07-16-unsafe-deserialization-sinks-deprecation.md b/java/ql/lib/change-notes/2025-07-16-unsafe-deserialization-sinks-deprecation.md
new file mode 100644
index 00000000000..7e7e607c18b
--- /dev/null
+++ b/java/ql/lib/change-notes/2025-07-16-unsafe-deserialization-sinks-deprecation.md
@@ -0,0 +1,8 @@
+---
+category: deprecated
+---
+* The module `semmle.code.java.frameworks.Castor` has been deprecated and will be removed in a future release.
+* The module `semmle.code.java.frameworks.JYaml` has been deprecated and will be removed in a future release.
+* The classes `UnsafeHessianInputReadObjectMethod` and `BurlapInputReadObjectMethod` in the module `semmle.code.java.frameworks.HessianBurlap` have been deprecated and will be removed in a future release.
+* The class `YamlBeansReaderReadMethod` in the module `semmle.code.java.frameworks.YamlBeans` has been deprecated and will be removed in a future release.
+* The class `MethodApacheSerializationUtilsDeserialize` in the module `semmle.code.java.frameworks.apache.Lang` has been deprecated and will be removed in a future release.
diff --git a/java/ql/lib/ext/com.alibaba.com.caucho.hessian.io.model.yml b/java/ql/lib/ext/com.alibaba.com.caucho.hessian.io.model.yml
new file mode 100644
index 00000000000..af8824aae0c
--- /dev/null
+++ b/java/ql/lib/ext/com.alibaba.com.caucho.hessian.io.model.yml
@@ -0,0 +1,7 @@
+extensions:
+ - addsTo:
+ pack: codeql/java-all
+ extensible: sinkModel
+ data:
+ - ["com.alibaba.com.caucho.hessian.io", "AbstractHessianInput", True, "readObject", "", "", "Argument[this]", "unsafe-deserialization", "manual"]
+ - ["com.alibaba.com.caucho.hessian.io", "Hessian2StreamingInput", True, "readObject", "", "", "Argument[this]", "unsafe-deserialization", "manual"]
diff --git a/java/ql/lib/ext/com.caucho.burlap.io.model.yml b/java/ql/lib/ext/com.caucho.burlap.io.model.yml
new file mode 100644
index 00000000000..862804438ca
--- /dev/null
+++ b/java/ql/lib/ext/com.caucho.burlap.io.model.yml
@@ -0,0 +1,6 @@
+extensions:
+ - addsTo:
+ pack: codeql/java-all
+ extensible: sinkModel
+ data:
+ - ["com.caucho.burlap.io", "BurlapInput", True, "readObject", "", "", "Argument[this]", "unsafe-deserialization", "manual"]
diff --git a/java/ql/lib/ext/com.caucho.hessian.io.model.yml b/java/ql/lib/ext/com.caucho.hessian.io.model.yml
new file mode 100644
index 00000000000..73c3ddebf45
--- /dev/null
+++ b/java/ql/lib/ext/com.caucho.hessian.io.model.yml
@@ -0,0 +1,7 @@
+extensions:
+ - addsTo:
+ pack: codeql/java-all
+ extensible: sinkModel
+ data:
+ - ["com.caucho.hessian.io", "AbstractHessianInput", True, "readObject", "", "", "Argument[this]", "unsafe-deserialization", "manual"]
+ - ["com.caucho.hessian.io", "Hessian2StreamingInput", True, "readObject", "", "", "Argument[this]", "unsafe-deserialization", "manual"]
diff --git a/java/ql/lib/ext/com.cedarsoftware.util.io.model.yml b/java/ql/lib/ext/com.cedarsoftware.util.io.model.yml
new file mode 100644
index 00000000000..926a8623811
--- /dev/null
+++ b/java/ql/lib/ext/com.cedarsoftware.util.io.model.yml
@@ -0,0 +1,7 @@
+extensions:
+ - addsTo:
+ pack: codeql/java-all
+ extensible: sinkModel
+ data:
+ - ["com.cedarsoftware.util.io", "JsonReader", False, "jsonToJava", "", "", "Argument[0]", "unsafe-deserialization", "manual"]
+ - ["com.cedarsoftware.util.io", "JsonReader", True, "readObject", "", "", "Argument[this]", "unsafe-deserialization", "manual"]
diff --git a/java/ql/lib/ext/com.esotericsoftware.yamlbeans.model.yml b/java/ql/lib/ext/com.esotericsoftware.yamlbeans.model.yml
new file mode 100644
index 00000000000..944222c420b
--- /dev/null
+++ b/java/ql/lib/ext/com.esotericsoftware.yamlbeans.model.yml
@@ -0,0 +1,6 @@
+extensions:
+ - addsTo:
+ pack: codeql/java-all
+ extensible: sinkModel
+ data:
+ - ["com.esotericsoftware.yamlbeans", "YamlReader", True, "read", "", "", "Argument[this]", "unsafe-deserialization", "manual"]
diff --git a/java/ql/lib/ext/java.beans.model.yml b/java/ql/lib/ext/java.beans.model.yml
index 30667ec6961..07291296612 100644
--- a/java/ql/lib/ext/java.beans.model.yml
+++ b/java/ql/lib/ext/java.beans.model.yml
@@ -13,3 +13,8 @@ extensions:
- ["java.beans", "PropertyEditor", "getValue", "()", "summary", "df-manual"] # needs to be modeled by regular CodeQL matching the get and set keys to reduce FPs
- ["java.beans", "PropertyEditor", "setAsText", "()", "summary", "df-manual"] # needs to be modeled by regular CodeQL matching the get and set keys to reduce FPs
- ["java.beans", "PropertyEditor", "setValue", "()", "summary", "df-manual"] # needs to be modeled by regular CodeQL matching the get and set keys to reduce FPs
+ - addsTo:
+ pack: codeql/java-all
+ extensible: sinkModel
+ data:
+ - ["java.beans", "XMLDecoder", True, "readObject", "()", "", "Argument[this]", "unsafe-deserialization", "manual"]
diff --git a/java/ql/lib/ext/org.apache.commons.lang.model.yml b/java/ql/lib/ext/org.apache.commons.lang.model.yml
index 8dd3fd003f9..0d38b845c9c 100644
--- a/java/ql/lib/ext/org.apache.commons.lang.model.yml
+++ b/java/ql/lib/ext/org.apache.commons.lang.model.yml
@@ -5,3 +5,8 @@ extensions:
data:
- ["org.apache.commons.lang", "StringEscapeUtils", true, "escapeHtml", "(String)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["org.apache.commons.lang", "StringEscapeUtils", true, "escapeHtml", "(Writer,String)", "", "Argument[1]", "Argument[0]", "taint", "manual"]
+ - addsTo:
+ pack: codeql/java-all
+ extensible: sinkModel
+ data:
+ - ["org.apache.commons.lang", "SerializationUtils", False, "deserialize", "", "", "Argument[0]", "unsafe-deserialization", "manual"]
diff --git a/java/ql/lib/ext/org.apache.commons.lang3.model.yml b/java/ql/lib/ext/org.apache.commons.lang3.model.yml
index 541db005f0b..7c455d780b1 100644
--- a/java/ql/lib/ext/org.apache.commons.lang3.model.yml
+++ b/java/ql/lib/ext/org.apache.commons.lang3.model.yml
@@ -3,6 +3,7 @@ extensions:
pack: codeql/java-all
extensible: sinkModel
data:
+ - ["org.apache.commons.lang3", "SerializationUtils", False, "deserialize", "", "", "Argument[0]", "unsafe-deserialization", "manual"]
# Note these sinks do not use the sink kind `regex-use[0]` because the regex injection query needs to select them separately from
# other `regex-use[0]` sinks in order to avoid FPs. As a result, these sinks are currently not used in the polynomial ReDoS query.
# TODO: refactor the `regex-use%` sink kind so that the polynomial ReDoS query can also use these sinks.
diff --git a/java/ql/lib/ext/org.exolab.castor.xml.model.yml b/java/ql/lib/ext/org.exolab.castor.xml.model.yml
new file mode 100644
index 00000000000..7113a9ab94a
--- /dev/null
+++ b/java/ql/lib/ext/org.exolab.castor.xml.model.yml
@@ -0,0 +1,6 @@
+extensions:
+ - addsTo:
+ pack: codeql/java-all
+ extensible: sinkModel
+ data:
+ - ["org.exolab.castor.xml", "Unmarshaller", True, "unmarshal", "", "", "Argument[0..1]", "unsafe-deserialization", "manual"]
diff --git a/java/ql/lib/ext/org.ho.yaml.model.yml b/java/ql/lib/ext/org.ho.yaml.model.yml
new file mode 100644
index 00000000000..fd6e0e36356
--- /dev/null
+++ b/java/ql/lib/ext/org.ho.yaml.model.yml
@@ -0,0 +1,13 @@
+extensions:
+ - addsTo:
+ pack: codeql/java-all
+ extensible: sinkModel
+ data:
+ - ["org.ho.yaml", "Yaml", False, "load", "", "", "Argument[0]", "unsafe-deserialization", "manual"]
+ - ["org.ho.yaml", "Yaml", False, "loadStream", "", "", "Argument[0]", "unsafe-deserialization", "manual"]
+ - ["org.ho.yaml", "Yaml", False, "loadStreamOfType", "", "", "Argument[0]", "unsafe-deserialization", "manual"]
+ - ["org.ho.yaml", "Yaml", False, "loadType", "", "", "Argument[0]", "unsafe-deserialization", "manual"]
+ - ["org.ho.yaml", "YamlConfig", False, "load", "", "", "Argument[0]", "unsafe-deserialization", "manual"]
+ - ["org.ho.yaml", "YamlConfig", False, "loadStream", "", "", "Argument[0]", "unsafe-deserialization", "manual"]
+ - ["org.ho.yaml", "YamlConfig", False, "loadStreamOfType", "", "", "Argument[0]", "unsafe-deserialization", "manual"]
+ - ["org.ho.yaml", "YamlConfig", False, "loadType", "", "", "Argument[0]", "unsafe-deserialization", "manual"]
diff --git a/java/ql/lib/ext/org.jabsorb.model.yml b/java/ql/lib/ext/org.jabsorb.model.yml
new file mode 100644
index 00000000000..5c50178e993
--- /dev/null
+++ b/java/ql/lib/ext/org.jabsorb.model.yml
@@ -0,0 +1,6 @@
+extensions:
+ - addsTo:
+ pack: codeql/java-all
+ extensible: sinkModel
+ data:
+ - ["org.jabsorb", "JSONSerializer", True, "fromJSON", "", "", "Argument[0]", "unsafe-deserialization", "manual"]
diff --git a/java/ql/lib/qlpack.yml b/java/ql/lib/qlpack.yml
index c7a6a045451..c27a06994b2 100644
--- a/java/ql/lib/qlpack.yml
+++ b/java/ql/lib/qlpack.yml
@@ -23,3 +23,4 @@ dataExtensions:
- ext/generated/*.model.yml
- ext/experimental/*.model.yml
warnOnImplicitThis: true
+compileForOverlayEval: true
diff --git a/java/ql/lib/semmle/code/Location.qll b/java/ql/lib/semmle/code/Location.qll
index 7265164e8e1..fced632a6dd 100644
--- a/java/ql/lib/semmle/code/Location.qll
+++ b/java/ql/lib/semmle/code/Location.qll
@@ -233,5 +233,5 @@ private predicate discardableLocation(string file, @location l) {
/** Discard base locations in files fully extracted in the overlay. */
overlay[discard_entity]
private predicate discardLocation(@location l) {
- exists(string file | discardableLocation(file, l) and extractedInOverlay(file))
+ exists(string file | discardableLocation(file, l) and overlayChangedFiles(file))
}
diff --git a/java/ql/lib/semmle/code/java/ControlFlowGraph.qll b/java/ql/lib/semmle/code/java/ControlFlowGraph.qll
index 33b7a6c0a9f..7188e1e6e21 100644
--- a/java/ql/lib/semmle/code/java/ControlFlowGraph.qll
+++ b/java/ql/lib/semmle/code/java/ControlFlowGraph.qll
@@ -82,6 +82,7 @@ module;
*/
import java
+private import codeql.util.Boolean
private import Completion
private import controlflow.internal.Preconditions
private import controlflow.internal.SwitchCases
@@ -102,6 +103,7 @@ module ControlFlow {
private newtype TNode =
TExprNode(Expr e) { hasControlFlow(e) } or
TStmtNode(Stmt s) or
+ TAnnotatedExitNode(Callable c, Boolean normal) { exists(c.getBody()) } or
TExitNode(Callable c) { exists(c.getBody()) } or
TAssertThrowNode(AssertStmt s)
@@ -191,6 +193,38 @@ module ControlFlow {
override Location getLocation() { result = s.getLocation() }
}
+ /** A control flow node indicating the normal or exceptional termination of a callable. */
+ class AnnotatedExitNode extends Node, TAnnotatedExitNode {
+ Callable c;
+ boolean normal;
+
+ AnnotatedExitNode() { this = TAnnotatedExitNode(c, normal) }
+
+ override Callable getEnclosingCallable() { result = c }
+
+ override ExprParent getAstNode() { result = c }
+
+ /** Gets a textual representation of this element. */
+ override string toString() {
+ normal = true and result = "Normal Exit"
+ or
+ normal = false and result = "Exceptional Exit"
+ }
+
+ /** Gets the source location for this element. */
+ override Location getLocation() { result = c.getLocation() }
+ }
+
+ /** A control flow node indicating normal termination of a callable. */
+ class NormalExitNode extends AnnotatedExitNode {
+ NormalExitNode() { this = TAnnotatedExitNode(_, true) }
+ }
+
+ /** A control flow node indicating exceptional termination of a callable. */
+ class ExceptionalExitNode extends AnnotatedExitNode {
+ ExceptionalExitNode() { this = TAnnotatedExitNode(_, false) }
+ }
+
/** A control flow node indicating the termination of a callable. */
class ExitNode extends Node, TExitNode {
Callable c;
@@ -1266,11 +1300,17 @@ private module ControlFlowGraphImpl {
*/
cached
Node succ(Node n, Completion completion) {
- // After executing the callable body, the final node is the exit node.
+ // After executing the callable body, the final nodes are first the
+ // annotated exit node and then the final exit node.
exists(Callable c | last(c.getBody(), n, completion) |
- result.(ExitNode).getEnclosingCallable() = c
+ if completion instanceof ThrowCompletion
+ then result.(ExceptionalExitNode).getEnclosingCallable() = c
+ else result.(NormalExitNode).getEnclosingCallable() = c
)
or
+ completion = NormalCompletion() and
+ n.(AnnotatedExitNode).getEnclosingCallable() = result.(ExitNode).getEnclosingCallable()
+ or
// Logic expressions and conditional expressions execute in AST pre-order.
completion = NormalCompletion() and
(
diff --git a/java/ql/lib/semmle/code/java/JDK.qll b/java/ql/lib/semmle/code/java/JDK.qll
index 897e857ba10..bdc2fb92fa0 100644
--- a/java/ql/lib/semmle/code/java/JDK.qll
+++ b/java/ql/lib/semmle/code/java/JDK.qll
@@ -211,6 +211,11 @@ class TypeObjectOutputStream extends RefType {
TypeObjectOutputStream() { this.hasQualifiedName("java.io", "ObjectOutputStream") }
}
+/** The type `java.io.ObjectInput`. */
+class TypeObjectInput extends RefType {
+ TypeObjectInput() { this.hasQualifiedName("java.io", "ObjectInput") }
+}
+
/** The type `java.io.ObjectInputStream`. */
class TypeObjectInputStream extends RefType {
TypeObjectInputStream() { this.hasQualifiedName("java.io", "ObjectInputStream") }
diff --git a/java/ql/lib/semmle/code/java/Overlay.qll b/java/ql/lib/semmle/code/java/Overlay.qll
index f1cfc5c434f..1d1a3896ba7 100644
--- a/java/ql/lib/semmle/code/java/Overlay.qll
+++ b/java/ql/lib/semmle/code/java/Overlay.qll
@@ -30,15 +30,6 @@ string getRawFileForLoc(@location l) {
exists(@file f | locations_default(l, f, _, _, _, _) and files(f, result))
}
-/** Holds for files fully extracted in the overlay. */
-overlay[local]
-predicate extractedInOverlay(string file) {
- isOverlay() and
- // numlines is used to restrict attention to fully extracted files and
- // ignore skeleton extracted files in the overlay
- exists(@locatable l | numlines(l, _, _, _) and file = getRawFile(l))
-}
-
/**
* A `@locatable` that should be discarded in the base variant if its file is
* extracted in the overlay variant.
@@ -54,7 +45,7 @@ abstract class DiscardableLocatable extends @locatable {
overlay[discard_entity]
private predicate discardLocatable(@locatable el) {
- extractedInOverlay(el.(DiscardableLocatable).getRawFileInBase())
+ overlayChangedFiles(el.(DiscardableLocatable).getRawFileInBase())
}
/**
@@ -77,7 +68,45 @@ abstract class DiscardableReferableLocatable extends @locatable {
overlay[discard_entity]
private predicate discardReferableLocatable(@locatable el) {
exists(DiscardableReferableLocatable drl | drl = el |
- extractedInOverlay(drl.getRawFileInBase()) and
+ overlayChangedFiles(drl.getRawFileInBase()) and
not drl.existsInOverlay()
)
}
+
+overlay[local]
+private predicate baseConfigLocatable(@configLocatable l) { not isOverlay() and exists(l) }
+
+overlay[local]
+private predicate overlayHasConfigLocatables() {
+ isOverlay() and
+ exists(@configLocatable el)
+}
+
+overlay[discard_entity]
+private predicate discardBaseConfigLocatable(@configLocatable el) {
+ // The properties extractor is currently not incremental, so if
+ // the overlay contains any config locatables, the overlay should
+ // contain a full extraction and all config locatables from base
+ // should be discarded.
+ baseConfigLocatable(el) and overlayHasConfigLocatables()
+}
+
+overlay[local]
+private predicate baseXmlLocatable(@xmllocatable l) {
+ not isOverlay() and not files(l, _) and not xmlNs(l, _, _, _)
+}
+
+overlay[local]
+private predicate overlayHasXmlLocatable() {
+ isOverlay() and
+ exists(@xmllocatable l | not files(l, _) and not xmlNs(l, _, _, _))
+}
+
+overlay[discard_entity]
+private predicate discardBaseXmlLocatable(@xmllocatable el) {
+ // The XML extractor is currently not incremental, so if
+ // the overlay contains any XML locatables, the overlay should
+ // contain a full extraction and all XML locatables from base
+ // should be discarded.
+ baseXmlLocatable(el) and overlayHasXmlLocatable()
+}
diff --git a/java/ql/lib/semmle/code/java/controlflow/Paths.qll b/java/ql/lib/semmle/code/java/controlflow/Paths.qll
index fb14c226484..abc56e32b5c 100644
--- a/java/ql/lib/semmle/code/java/controlflow/Paths.qll
+++ b/java/ql/lib/semmle/code/java/controlflow/Paths.qll
@@ -66,6 +66,10 @@ private class JoinBlock extends BasicBlock {
JoinBlock() { 2 <= strictcount(this.getAPredecessor()) }
}
+private class ReachableBlock extends BasicBlock {
+ ReachableBlock() { hasDominanceInformation(this) }
+}
+
/**
* Holds if `bb` is a block that is collectively dominated by a set of one or
* more actions that individually does not dominate the exit.
@@ -74,7 +78,7 @@ private predicate postActionBlock(BasicBlock bb, ActionConfiguration conf) {
bb = nonDominatingActionBlock(conf)
or
if bb instanceof JoinBlock
- then forall(BasicBlock pred | pred = bb.getAPredecessor() | postActionBlock(pred, conf))
+ then forall(ReachableBlock pred | pred = bb.getAPredecessor() | postActionBlock(pred, conf))
else postActionBlock(bb.getAPredecessor(), conf)
}
diff --git a/java/ql/lib/semmle/code/java/frameworks/Castor.qll b/java/ql/lib/semmle/code/java/frameworks/Castor.qll
index 2becb2fbf17..5be64575bc2 100644
--- a/java/ql/lib/semmle/code/java/frameworks/Castor.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/Castor.qll
@@ -1,8 +1,10 @@
/**
+ * DEPRECATED: Now modeled using data extensions instead.
+ *
* Provides classes and predicates for working with the Castor framework.
*/
overlay[local?]
-module;
+deprecated module;
import java
@@ -13,7 +15,9 @@ class CastorUnmarshaller extends RefType {
CastorUnmarshaller() { this.hasQualifiedName("org.exolab.castor.xml", "Unmarshaller") }
}
-/** A method with the name `unmarshal` declared in `org.exolab.castor.xml.Unmarshaller`. */
+/**
+ * A method with the name `unmarshal` declared in `org.exolab.castor.xml.Unmarshaller`.
+ */
class CastorUnmarshalMethod extends Method {
CastorUnmarshalMethod() {
this.getDeclaringType() instanceof CastorUnmarshaller and
diff --git a/java/ql/lib/semmle/code/java/frameworks/HessianBurlap.qll b/java/ql/lib/semmle/code/java/frameworks/HessianBurlap.qll
index 3a10b75a2a6..25449b351ab 100644
--- a/java/ql/lib/semmle/code/java/frameworks/HessianBurlap.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/HessianBurlap.qll
@@ -17,10 +17,12 @@ class UnsafeHessianInput extends RefType {
}
/**
+ * DEPRECATED: Now modeled using data extensions instead.
+ *
* A AbstractHessianInput or Hessian2StreamingInput subclass readObject method.
* This is either `AbstractHessianInput.readObject` or `Hessian2StreamingInput.readObject`.
*/
-class UnsafeHessianInputReadObjectMethod extends Method {
+deprecated class UnsafeHessianInputReadObjectMethod extends Method {
UnsafeHessianInputReadObjectMethod() {
this.getDeclaringType().getAnAncestor() instanceof UnsafeHessianInput and
this.getName() = "readObject"
@@ -34,8 +36,12 @@ class BurlapInput extends RefType {
BurlapInput() { this.hasQualifiedName("com.caucho.burlap.io", "BurlapInput") }
}
-/** A method with the name `readObject` declared in `com.caucho.burlap.io.BurlapInput`. */
-class BurlapInputReadObjectMethod extends Method {
+/**
+ * DEPRECATED: Now modeled using data extensions instead.
+ *
+ * A method with the name `readObject` declared in `com.caucho.burlap.io.BurlapInput`.
+ */
+deprecated class BurlapInputReadObjectMethod extends Method {
BurlapInputReadObjectMethod() {
this.getDeclaringType() instanceof BurlapInput and
this.getName() = "readObject"
diff --git a/java/ql/lib/semmle/code/java/frameworks/JYaml.qll b/java/ql/lib/semmle/code/java/frameworks/JYaml.qll
index cd9414521c4..4f39c8cd23f 100644
--- a/java/ql/lib/semmle/code/java/frameworks/JYaml.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/JYaml.qll
@@ -1,8 +1,10 @@
/**
+ * DEPRECATED: Now modeled using data extensions instead.
+ *
* Provides classes and predicates for working with the JYaml framework.
*/
overlay[local?]
-module;
+deprecated module;
import java
diff --git a/java/ql/lib/semmle/code/java/frameworks/Jabsorb.qll b/java/ql/lib/semmle/code/java/frameworks/Jabsorb.qll
index e8bb82f156f..1997fd74f64 100644
--- a/java/ql/lib/semmle/code/java/frameworks/Jabsorb.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/Jabsorb.qll
@@ -19,8 +19,12 @@ class JabsorbUnmarshallMethod extends Method {
}
}
-/** The deserialization method `fromJSON`. */
-class JabsorbFromJsonMethod extends Method {
+/**
+ * DEPRECATED: Now modeled using data extensions instead.
+ *
+ * The deserialization method `fromJSON`.
+ */
+deprecated class JabsorbFromJsonMethod extends Method {
JabsorbFromJsonMethod() {
this.getDeclaringType().getAnAncestor() instanceof JabsorbSerializer and
this.getName() = "fromJSON"
diff --git a/java/ql/lib/semmle/code/java/frameworks/YamlBeans.qll b/java/ql/lib/semmle/code/java/frameworks/YamlBeans.qll
index 040ae60fc71..55ff862d341 100644
--- a/java/ql/lib/semmle/code/java/frameworks/YamlBeans.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/YamlBeans.qll
@@ -13,8 +13,12 @@ class YamlBeansReader extends RefType {
YamlBeansReader() { this.hasQualifiedName("com.esotericsoftware.yamlbeans", "YamlReader") }
}
-/** A method with the name `read` declared in `com.esotericsoftware.yamlbeans.YamlReader`. */
-class YamlBeansReaderReadMethod extends Method {
+/**
+ * DEPRECATED: Now modeled using data extensions instead.
+ *
+ * A method with the name `read` declared in `com.esotericsoftware.yamlbeans.YamlReader`.
+ */
+deprecated class YamlBeansReaderReadMethod extends Method {
YamlBeansReaderReadMethod() {
this.getDeclaringType() instanceof YamlBeansReader and
this.getName() = "read"
diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/Lang.qll b/java/ql/lib/semmle/code/java/frameworks/apache/Lang.qll
index 27c7f9530ad..a58500eb20d 100644
--- a/java/ql/lib/semmle/code/java/frameworks/apache/Lang.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/apache/Lang.qll
@@ -16,10 +16,12 @@ class TypeApacheRandomStringUtils extends Class {
}
/**
+ * DEPRECATED: Now modeled using data extensions instead.
+ *
* The method `deserialize` in either `org.apache.commons.lang.SerializationUtils`
* or `org.apache.commons.lang3.SerializationUtils`.
*/
-class MethodApacheSerializationUtilsDeserialize extends Method {
+deprecated class MethodApacheSerializationUtilsDeserialize extends Method {
MethodApacheSerializationUtilsDeserialize() {
this.getDeclaringType()
.hasQualifiedName(["org.apache.commons.lang", "org.apache.commons.lang3"],
diff --git a/java/ql/lib/semmle/code/java/security/PathSanitizer.qll b/java/ql/lib/semmle/code/java/security/PathSanitizer.qll
index ed0761f6869..e789d3c4778 100644
--- a/java/ql/lib/semmle/code/java/security/PathSanitizer.qll
+++ b/java/ql/lib/semmle/code/java/security/PathSanitizer.qll
@@ -31,20 +31,10 @@ private module ValidationMethod {
* Holds if `m` validates its `arg`th parameter by using `validationGuard`.
*/
private predicate validationMethod(Method m, int arg) {
- exists(
- Guard g, SsaImplicitInit var, ControlFlow::ExitNode exit, ControlFlowNode normexit,
- boolean branch
- |
+ exists(Guard g, SsaImplicitInit var, ControlFlow::NormalExitNode normexit, boolean branch |
validationGuard(g, var.getAUse(), branch) and
var.isParameterDefinition(m.getParameter(arg)) and
- exit.getEnclosingCallable() = m and
- normexit.getANormalSuccessor() = exit and
- 1 = strictcount(ControlFlowNode n | n.getANormalSuccessor() = exit)
- |
- exists(ConditionNode conditionNode |
- g = conditionNode.getCondition() and conditionNode.getABranchSuccessor(branch) = exit
- )
- or
+ normexit.getEnclosingCallable() = m and
g.controls(normexit.getBasicBlock(), branch)
)
}
diff --git a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll
index e10c6cebaf6..ce0f649eff3 100644
--- a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll
+++ b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll
@@ -3,17 +3,16 @@
*/
import semmle.code.java.dataflow.FlowSources
+private import semmle.code.java.dataflow.ExternalFlow
private import semmle.code.java.dataflow.FlowSinks
private import semmle.code.java.dispatch.VirtualDispatch
private import semmle.code.java.frameworks.Kryo
private import semmle.code.java.frameworks.XStream
private import semmle.code.java.frameworks.SnakeYaml
private import semmle.code.java.frameworks.FastJson
-private import semmle.code.java.frameworks.JYaml
private import semmle.code.java.frameworks.JsonIo
private import semmle.code.java.frameworks.YamlBeans
private import semmle.code.java.frameworks.HessianBurlap
-private import semmle.code.java.frameworks.Castor
private import semmle.code.java.frameworks.Jackson
private import semmle.code.java.frameworks.Jabsorb
private import semmle.code.java.frameworks.Jms
@@ -23,10 +22,17 @@ private import semmle.code.java.frameworks.google.Gson
private import semmle.code.java.frameworks.apache.Lang
private import semmle.code.java.Reflection
-private class ObjectInputStreamReadObjectMethod extends Method {
- ObjectInputStreamReadObjectMethod() {
+private class ObjectInputReadObjectMethod extends Method {
+ ObjectInputReadObjectMethod() {
+ this.getDeclaringType().getASourceSupertype*() instanceof TypeObjectInput and
+ this.hasName("readObject")
+ }
+}
+
+private class ObjectInputStreamReadUnsharedMethod extends Method {
+ ObjectInputStreamReadUnsharedMethod() {
this.getDeclaringType().getASourceSupertype*() instanceof TypeObjectInputStream and
- (this.hasName("readObject") or this.hasName("readUnshared"))
+ this.hasName("readUnshared")
}
}
@@ -44,13 +50,6 @@ private class SafeObjectInputStreamType extends RefType {
}
}
-private class XmlDecoderReadObjectMethod extends Method {
- XmlDecoderReadObjectMethod() {
- this.getDeclaringType().hasQualifiedName("java.beans", "XMLDecoder") and
- this.hasName("readObject")
- }
-}
-
private module SafeXStreamConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) {
any(XStreamEnableWhiteListing ma).getQualifier().(VarAccess).getVariable().getAnAccess() =
@@ -142,20 +141,25 @@ private module SafeKryoConfig implements DataFlow::ConfigSig {
private module SafeKryoFlow = DataFlow::Global;
+private class DefaultUnsafeDeserializationSink extends DataFlow::Node {
+ DefaultUnsafeDeserializationSink() { sinkNode(this, "unsafe-deserialization") }
+}
+
/**
* Holds if `ma` is a call that deserializes data from `sink`.
+ *
+ * Note that this does not include deserialization methods that have been
+ * specified using models-as-data.
*/
predicate unsafeDeserialization(MethodCall ma, Expr sink) {
exists(Method m | m = ma.getMethod() |
- m instanceof ObjectInputStreamReadObjectMethod and
+ m instanceof ObjectInputReadObjectMethod and
sink = ma.getQualifier() and
- not exists(DataFlow::ExprNode node |
- node.getExpr() = sink and
- node.getTypeBound() instanceof SafeObjectInputStreamType
- )
+ not DataFlow::exprNode(sink).getTypeBound() instanceof SafeObjectInputStreamType
or
- m instanceof XmlDecoderReadObjectMethod and
- sink = ma.getQualifier()
+ m instanceof ObjectInputStreamReadUnsharedMethod and
+ sink = ma.getQualifier() and
+ not DataFlow::exprNode(sink).getTypeBound() instanceof SafeObjectInputStreamType
or
m instanceof XStreamReadObjectMethod and
sink = ma.getAnArgument() and
@@ -165,9 +169,6 @@ predicate unsafeDeserialization(MethodCall ma, Expr sink) {
sink = ma.getAnArgument() and
not SafeKryoFlow::flowToExpr(ma.getQualifier())
or
- m instanceof MethodApacheSerializationUtilsDeserialize and
- sink = ma.getArgument(0)
- or
ma instanceof UnsafeSnakeYamlParse and
sink = ma.getArgument(0)
or
@@ -175,23 +176,6 @@ predicate unsafeDeserialization(MethodCall ma, Expr sink) {
not fastJsonLooksSafe() and
sink = ma.getArgument(0)
or
- ma.getMethod() instanceof JYamlLoaderUnsafeLoadMethod and
- sink = ma.getArgument(0)
- or
- ma.getMethod() instanceof JsonIoJsonToJavaMethod and
- sink = ma.getArgument(0)
- or
- ma.getMethod() instanceof JsonIoReadObjectMethod and
- sink = ma.getQualifier()
- or
- ma.getMethod() instanceof YamlBeansReaderReadMethod and sink = ma.getQualifier()
- or
- ma.getMethod() instanceof UnsafeHessianInputReadObjectMethod and sink = ma.getQualifier()
- or
- ma.getMethod() instanceof CastorUnmarshalMethod and sink = ma.getAnArgument()
- or
- ma.getMethod() instanceof BurlapInputReadObjectMethod and sink = ma.getQualifier()
- or
ma.getMethod() instanceof ObjectMapperReadMethod and
sink = ma.getArgument(0) and
(
@@ -207,9 +191,6 @@ predicate unsafeDeserialization(MethodCall ma, Expr sink) {
sink = ma.getArgument(2) and
UnsafeTypeFlow::flowToExpr(ma.getArgument(1))
or
- m instanceof JabsorbFromJsonMethod and
- sink = ma.getArgument(0)
- or
m instanceof JoddJsonParseMethod and
sink = ma.getArgument(0) and
(
@@ -236,10 +217,17 @@ predicate unsafeDeserialization(MethodCall ma, Expr sink) {
/** A sink for unsafe deserialization. */
class UnsafeDeserializationSink extends ApiSinkNode, DataFlow::ExprNode {
- UnsafeDeserializationSink() { unsafeDeserialization(_, this.getExpr()) }
+ MethodCall mc;
+
+ UnsafeDeserializationSink() {
+ unsafeDeserialization(mc, this.getExpr())
+ or
+ this instanceof DefaultUnsafeDeserializationSink and
+ this.getExpr() = [mc.getQualifier(), mc.getAnArgument()]
+ }
/** Gets a call that triggers unsafe deserialization. */
- MethodCall getMethodCall() { unsafeDeserialization(result, this.getExpr()) }
+ MethodCall getMethodCall() { result = mc }
}
/** Holds if `node` is a sanitizer for unsafe deserialization */
diff --git a/java/ql/lib/semmle/code/java/security/regexp/PolynomialReDoSQuery.qll b/java/ql/lib/semmle/code/java/security/regexp/PolynomialReDoSQuery.qll
index ba65e13dd61..767ebc97437 100644
--- a/java/ql/lib/semmle/code/java/security/regexp/PolynomialReDoSQuery.qll
+++ b/java/ql/lib/semmle/code/java/security/regexp/PolynomialReDoSQuery.qll
@@ -47,6 +47,18 @@ module PolynomialRedosConfig implements DataFlow::ConfigSig {
node instanceof SimpleTypeSanitizer or
node.asExpr().(MethodCall).getMethod() instanceof LengthRestrictedMethod
}
+
+ predicate observeDiffInformedIncrementalMode() { any() }
+
+ Location getASelectedSinkLocation(DataFlow::Node sink) {
+ exists(SuperlinearBackTracking::PolynomialBackTrackingTerm regexp |
+ regexp.getRootTerm() = sink.(PolynomialRedosSink).getRegExp()
+ |
+ result = sink.getLocation()
+ or
+ result = regexp.getLocation()
+ )
+ }
}
module PolynomialRedosFlow = TaintTracking::Global;
diff --git a/java/ql/src/Language Abuse/LabelInSwitch.md b/java/ql/src/Language Abuse/LabelInSwitch.md
new file mode 100644
index 00000000000..e871e68abeb
--- /dev/null
+++ b/java/ql/src/Language Abuse/LabelInSwitch.md
@@ -0,0 +1,33 @@
+## Overview
+
+Java allows to freely mix `case` labels and ordinary statement labels in the body of
+a `switch` statement. However, this is confusing to read and may be the result of a typo.
+
+## Recommendation
+
+Examine the non-`case` labels to see whether they were meant to be `case` labels. If not, consider placing the non-`case` label headed code into a function, and use a function call inline in the `switch` body instead.
+
+## Example
+
+```java
+public class Test {
+ void test_noncase_label_in_switch(int p) {
+ switch (p) {
+ case 1: // Compliant
+ case2: // Non-compliant, likely a typo
+ break;
+ case 3:
+ notcaselabel: // Non-compliant, confusing to read
+ for (;;) {
+ break notcaselabel;
+ }
+ }
+ }
+}
+```
+
+In the example, `case2` is most likely a typo and should be fixed. For the intentional `notcaselabel`, placing the labelled code into a function and then calling that function is more readable.
+
+## References
+
+CodeQL query help for JavaScript and TypeScript - [Non-case label in switch statement](https://codeql.github.com/codeql-query-help/javascript/js-label-in-switch/).
diff --git a/java/ql/src/Language Abuse/LabelInSwitch.ql b/java/ql/src/Language Abuse/LabelInSwitch.ql
new file mode 100644
index 00000000000..56245df8033
--- /dev/null
+++ b/java/ql/src/Language Abuse/LabelInSwitch.ql
@@ -0,0 +1,25 @@
+/**
+ * @id java/label-in-switch
+ * @name Non-case label in switch statement
+ * @description A non-case label appearing in a switch statement
+ * is confusing to read or may even indicate a bug.
+ * @previous-id java/label-in-case
+ * @kind problem
+ * @precision very-high
+ * @problem.severity recommendation
+ * @tags quality
+ * maintainability
+ * readability
+ */
+
+import java
+
+from LabeledStmt l, SwitchStmt s, string alert
+where
+ l = s.getAStmt+() and
+ if exists(JumpStmt jump | jump.getTargetLabel() = l)
+ then alert = "Confusing non-case label in switch statement."
+ else
+ alert =
+ "Possibly erroneous non-case label in switch statement. The case keyword might be missing."
+select l, alert
diff --git a/java/ql/src/Language Abuse/TypeVariableHidesType.ql b/java/ql/src/Language Abuse/TypeVariableHidesType.ql
index 81da0e9703e..42d0a7bea2b 100644
--- a/java/ql/src/Language Abuse/TypeVariableHidesType.ql
+++ b/java/ql/src/Language Abuse/TypeVariableHidesType.ql
@@ -6,10 +6,10 @@
* @problem.severity warning
* @precision medium
* @id java/type-variable-hides-type
- * @tags reliability
+ * @tags quality
+ * maintainability
* readability
* types
- * quality
*/
import java
diff --git a/java/ql/src/Metrics/RefTypes/TInheritanceDepth.qhelp b/java/ql/src/Metrics/RefTypes/TInheritanceDepth.qhelp
index 7d78490985b..970b1c4e19e 100644
--- a/java/ql/src/Metrics/RefTypes/TInheritanceDepth.qhelp
+++ b/java/ql/src/Metrics/RefTypes/TInheritanceDepth.qhelp
@@ -29,14 +29,13 @@ that something is amiss, but further investigation will be needed to clarify
the cause of the problem. Here are two possibilities:
-
-
--
-A class and its superclass represent fundamentally the same abstraction.
+
+1. A class and its superclass represent fundamentally the same abstraction.
In this case, they should generally be merged together (see the 'Collapse
Hierarchy' refactoring on pp.279-80 of [Fowler]). For example, suppose
that in the following class hierarchy both A and C represent fundamentally
the same thing, then they should be merged together as shown:
+
@@ -48,11 +47,9 @@ the same thing, then they should be merged together as shown:
| After |
-
--
-The class hierarchy is trying to represent variation in more than one
+2. The class hierarchy is trying to represent variation in more than one
dimension using single inheritance. This can lead to an unnecessarily
deep class hierarchy with lots of code duplication. For example, consider
the following:
@@ -81,9 +78,6 @@ amount of code duplication that will be necessary.
For readers who are interested in this sort of approach, a good reference is
[West].
-
-
-
diff --git a/java/ql/src/Metrics/RefTypes/TNumberOfCallables.qhelp b/java/ql/src/Metrics/RefTypes/TNumberOfCallables.qhelp
index 49827592849..4f9452789a8 100644
--- a/java/ql/src/Metrics/RefTypes/TNumberOfCallables.qhelp
+++ b/java/ql/src/Metrics/RefTypes/TNumberOfCallables.qhelp
@@ -49,21 +49,17 @@ need to be part of the class. (A classic example of this is the
std::string class in the C++ Standard Library.) As [Sutter]
observes, there are at least two key problems with this approach:
-
--
-It may be possible to generalize some of the utility methods beyond the
+
+1. It may be possible to generalize some of the utility methods beyond the
narrow context of the class in question -- by bundling them with the class,
the class author reduces the scope for functionality reuse.
-
--
-It's usually impossible for the class author to know every possible
+2. It's usually impossible for the class author to know every possible
operation that the user might want to perform on the class, so the public
interface will inherently be incomplete. New utility methods will end up
having a different syntax to the privileged public methods in the class,
negatively impacting on code consistency.
-
-
+
To refactor a class like this, simply move its utility methods elsewhere,
paring its public interface down to the bare minimum.
diff --git a/java/ql/src/Metrics/RefTypes/TNumberOfFields.qhelp b/java/ql/src/Metrics/RefTypes/TNumberOfFields.qhelp
index befc6409449..2934ba958b5 100644
--- a/java/ql/src/Metrics/RefTypes/TNumberOfFields.qhelp
+++ b/java/ql/src/Metrics/RefTypes/TNumberOfFields.qhelp
@@ -25,11 +25,9 @@ If the class is too big, you should split it into multiple smaller classes.
-
If several of the fields are part of the same abstraction, you should
group them into a separate class, using the 'Extract Class' refactoring described
in [Fowler].
-
diff --git a/java/ql/src/Metrics/RefTypes/TSizeOfAPI.qhelp b/java/ql/src/Metrics/RefTypes/TSizeOfAPI.qhelp
index 3095d82049a..eda183a287c 100644
--- a/java/ql/src/Metrics/RefTypes/TSizeOfAPI.qhelp
+++ b/java/ql/src/Metrics/RefTypes/TSizeOfAPI.qhelp
@@ -46,21 +46,17 @@ need to be part of the class. (A classic example of this is the
std::string class in the C++ Standard Library.) As [Sutter]
observes, there are at least two key problems with this approach:
-
--
-It may be possible to generalize some of the utility methods beyond the
+
+1. It may be possible to generalize some of the utility methods beyond the
narrow context of the class in question -- by bundling them with the class,
the class author reduces the scope for functionality reuse.
-
--
-It's usually impossible for the class author to know every possible
+2. It's usually impossible for the class author to know every possible
operation that the user might want to perform on the class, so the public
interface will inherently be incomplete. New utility methods will end up
having a different syntax to the privileged public methods in the class,
negatively impacting on code consistency.
-
-
+
To refactor a class like this, simply move its utility methods elsewhere,
paring its public interface down to the bare minimum.
diff --git a/java/ql/src/Violations of Best Practice/SpecialCharactersInLiterals/NonExplicitControlAndWhitespaceCharsInLiterals.ql b/java/ql/src/Violations of Best Practice/SpecialCharactersInLiterals/NonExplicitControlAndWhitespaceCharsInLiterals.ql
index 0ff14bc8f2d..81485f9cd94 100644
--- a/java/ql/src/Violations of Best Practice/SpecialCharactersInLiterals/NonExplicitControlAndWhitespaceCharsInLiterals.ql
+++ b/java/ql/src/Violations of Best Practice/SpecialCharactersInLiterals/NonExplicitControlAndWhitespaceCharsInLiterals.ql
@@ -23,6 +23,7 @@ class ReservedUnicodeInLiteral extends Literal {
ReservedUnicodeInLiteral() {
not this instanceof CharacterLiteral and
+ this.getCompilationUnit().fromSource() and
exists(int codePoint |
this.getLiteral().codePointAt(indexStart) = codePoint and
(
@@ -45,6 +46,9 @@ where
literal.getIndexStart() = charIndex and
literal.getLiteral().codePointAt(charIndex) = codePoint and
not literal.getEnclosingCallable() instanceof LikelyTestMethod and
+ // Kotlin extraction doesn't preserve the literal value so we can't distinguish
+ // between control characters and their escaped versions, so we exclude Kotlin
+ // to avoid false positives.
not literal.getFile().isKotlinSourceFile()
select literal,
"Literal value contains control or non-printable whitespace character(s) starting with Unicode code point "
diff --git a/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStmts.expected b/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStmts.expected
index 8fe0abd91c0..116bde45f98 100644
--- a/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStmts.expected
+++ b/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStmts.expected
@@ -1,8 +1,12 @@
+| Test.kt:3:8:80:1 | Exceptional Exit | 0 | Test.kt:3:8:80:1 | Exceptional Exit |
+| Test.kt:3:8:80:1 | Exit | 0 | Test.kt:3:8:80:1 | Exit |
| Test.kt:3:8:80:1 | { ... } | 0 | Test.kt:3:8:80:1 | { ... } |
| Test.kt:3:8:80:1 | { ... } | 1 | Test.kt:3:1:80:1 | super(...) |
| Test.kt:3:8:80:1 | { ... } | 2 | Test.kt:3:8:80:1 | { ... } |
-| Test.kt:3:8:80:1 | { ... } | 3 | Test.kt:3:8:80:1 | Exit |
+| Test.kt:3:8:80:1 | { ... } | 3 | Test.kt:3:8:80:1 | Normal Exit |
+| Test.kt:4:2:79:2 | Exceptional Exit | 0 | Test.kt:4:2:79:2 | Exceptional Exit |
| Test.kt:4:2:79:2 | Exit | 0 | Test.kt:4:2:79:2 | Exit |
+| Test.kt:4:2:79:2 | Normal Exit | 0 | Test.kt:4:2:79:2 | Normal Exit |
| Test.kt:4:13:79:2 | { ... } | 0 | Test.kt:4:13:79:2 | { ... } |
| Test.kt:4:13:79:2 | { ... } | 1 | Test.kt:5:7:5:7 | var ...; |
| Test.kt:4:13:79:2 | { ... } | 2 | Test.kt:5:16:5:16 | 0 |
@@ -102,7 +106,9 @@
| Test.kt:43:3:43:3 | ; | 8 | Test.kt:77:3:77:8 | ...=... |
| Test.kt:43:3:43:3 | ; | 9 | Test.kt:78:3:78:8 | INSTANCE |
| Test.kt:43:3:43:3 | ; | 10 | Test.kt:78:3:78:8 | return ... |
+| Test.kt:82:1:89:1 | Exceptional Exit | 0 | Test.kt:82:1:89:1 | Exceptional Exit |
| Test.kt:82:1:89:1 | Exit | 0 | Test.kt:82:1:89:1 | Exit |
+| Test.kt:82:1:89:1 | Normal Exit | 0 | Test.kt:82:1:89:1 | Normal Exit |
| Test.kt:82:21:89:1 | { ... } | 0 | Test.kt:82:21:89:1 | { ... } |
| Test.kt:82:21:89:1 | { ... } | 1 | Test.kt:83:2:88:2 | try ... |
| Test.kt:82:21:89:1 | { ... } | 2 | Test.kt:83:6:86:2 | { ... } |
@@ -117,7 +123,9 @@
| Test.kt:86:4:88:2 | catch (...) | 2 | Test.kt:86:34:88:2 | { ... } |
| Test.kt:86:4:88:2 | catch (...) | 3 | Test.kt:87:10:87:10 | 2 |
| Test.kt:86:4:88:2 | catch (...) | 4 | Test.kt:87:3:87:10 | return ... |
+| Test.kt:91:1:98:1 | Exceptional Exit | 0 | Test.kt:91:1:98:1 | Exceptional Exit |
| Test.kt:91:1:98:1 | Exit | 0 | Test.kt:91:1:98:1 | Exit |
+| Test.kt:91:1:98:1 | Normal Exit | 0 | Test.kt:91:1:98:1 | Normal Exit |
| Test.kt:91:22:98:1 | { ... } | 0 | Test.kt:91:22:98:1 | { ... } |
| Test.kt:91:22:98:1 | { ... } | 1 | Test.kt:92:2:97:2 | try ... |
| Test.kt:91:22:98:1 | { ... } | 2 | Test.kt:92:6:95:2 | { ... } |
@@ -133,6 +141,7 @@
| Test.kt:95:4:97:2 | catch (...) | 3 | Test.kt:96:10:96:10 | 2 |
| Test.kt:95:4:97:2 | catch (...) | 4 | Test.kt:96:3:96:10 | return ... |
| Test.kt:100:1:110:1 | Exit | 0 | Test.kt:100:1:110:1 | Exit |
+| Test.kt:100:1:110:1 | Normal Exit | 0 | Test.kt:100:1:110:1 | Normal Exit |
| Test.kt:100:25:110:1 | { ... } | 0 | Test.kt:100:25:110:1 | { ... } |
| Test.kt:100:25:110:1 | { ... } | 1 | Test.kt:101:5:103:5 | ; |
| Test.kt:100:25:110:1 | { ... } | 2 | Test.kt:101:5:103:5 | when ... |
@@ -147,6 +156,7 @@
| Test.kt:101:33:103:5 | { ... } | 0 | Test.kt:101:33:103:5 | { ... } |
| Test.kt:101:33:103:5 | { ... } | 1 | Test.kt:102:15:102:25 | new Exception(...) |
| Test.kt:101:33:103:5 | { ... } | 2 | Test.kt:102:9:102:25 | throw ... |
+| Test.kt:101:33:103:5 | { ... } | 3 | Test.kt:100:1:110:1 | Exceptional Exit |
| Test.kt:105:5:109:5 | ; | 0 | Test.kt:105:5:109:5 | ; |
| Test.kt:105:5:109:5 | ; | 1 | Test.kt:105:5:109:5 | when ... |
| Test.kt:105:5:109:5 | ; | 2 | Test.kt:105:9:107:5 | ... -> ... |
@@ -165,7 +175,9 @@
| Test.kt:107:27:109:5 | { ... } | 1 | Test.kt:108:9:108:29 | ; |
| Test.kt:107:27:109:5 | { ... } | 2 | Test.kt:108:17:108:28 | "y not null" |
| Test.kt:107:27:109:5 | { ... } | 3 | Test.kt:108:9:108:29 | println(...) |
+| Test.kt:112:1:116:1 | Exceptional Exit | 0 | Test.kt:112:1:116:1 | Exceptional Exit |
| Test.kt:112:1:116:1 | Exit | 0 | Test.kt:112:1:116:1 | Exit |
+| Test.kt:112:1:116:1 | Normal Exit | 0 | Test.kt:112:1:116:1 | Normal Exit |
| Test.kt:112:32:116:1 | { ... } | 0 | Test.kt:112:32:116:1 | { ... } |
| Test.kt:112:32:116:1 | { ... } | 1 | Test.kt:113:5:115:5 | ; |
| Test.kt:112:32:116:1 | { ... } | 2 | Test.kt:113:5:115:5 | when ... |
@@ -174,7 +186,9 @@
| Test.kt:112:32:116:1 | { ... } | 5 | Test.kt:113:9:113:9 | x |
| Test.kt:113:14:113:14 | y | 0 | Test.kt:113:14:113:14 | y |
| Test.kt:113:17:115:5 | { ... } | 0 | Test.kt:113:17:115:5 | { ... } |
+| Test.kt:118:1:124:1 | Exceptional Exit | 0 | Test.kt:118:1:124:1 | Exceptional Exit |
| Test.kt:118:1:124:1 | Exit | 0 | Test.kt:118:1:124:1 | Exit |
+| Test.kt:118:1:124:1 | Normal Exit | 0 | Test.kt:118:1:124:1 | Normal Exit |
| Test.kt:118:37:124:1 | { ... } | 0 | Test.kt:118:37:124:1 | { ... } |
| Test.kt:118:37:124:1 | { ... } | 1 | Test.kt:119:2:123:12 | ; |
| Test.kt:118:37:124:1 | { ... } | 2 | Test.kt:119:2:123:12 | when ... |
diff --git a/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStrictDominance.expected b/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStrictDominance.expected
index fa358b39a35..6d0cb2bab71 100644
--- a/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStrictDominance.expected
+++ b/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStrictDominance.expected
@@ -1,4 +1,7 @@
+| Test.kt:3:8:80:1 | { ... } | Test.kt:3:8:80:1 | Exit |
+| Test.kt:4:2:79:2 | Normal Exit | Test.kt:4:2:79:2 | Exit |
| Test.kt:4:13:79:2 | { ... } | Test.kt:4:2:79:2 | Exit |
+| Test.kt:4:13:79:2 | { ... } | Test.kt:4:2:79:2 | Normal Exit |
| Test.kt:4:13:79:2 | { ... } | Test.kt:11:3:16:3 | ... -> ... |
| Test.kt:4:13:79:2 | { ... } | Test.kt:11:14:14:3 | { ... } |
| Test.kt:4:13:79:2 | { ... } | Test.kt:18:3:18:3 | ; |
@@ -10,6 +13,7 @@
| Test.kt:4:13:79:2 | { ... } | Test.kt:38:16:41:3 | { ... } |
| Test.kt:4:13:79:2 | { ... } | Test.kt:43:3:43:3 | ; |
| Test.kt:18:3:18:3 | ; | Test.kt:4:2:79:2 | Exit |
+| Test.kt:18:3:18:3 | ; | Test.kt:4:2:79:2 | Normal Exit |
| Test.kt:18:3:18:3 | ; | Test.kt:21:3:24:9 | ... -> ... |
| Test.kt:18:3:18:3 | ; | Test.kt:22:4:22:4 | ; |
| Test.kt:18:3:18:3 | ; | Test.kt:30:15:33:3 | { ... } |
@@ -27,13 +31,18 @@
| Test.kt:35:3:35:3 | ; | Test.kt:43:3:43:3 | ; |
| Test.kt:38:9:38:9 | x | Test.kt:38:16:41:3 | { ... } |
| Test.kt:38:9:38:9 | x | Test.kt:43:3:43:3 | ; |
+| Test.kt:82:1:89:1 | Normal Exit | Test.kt:82:1:89:1 | Exit |
| Test.kt:82:21:89:1 | { ... } | Test.kt:82:1:89:1 | Exit |
+| Test.kt:82:21:89:1 | { ... } | Test.kt:82:1:89:1 | Normal Exit |
| Test.kt:82:21:89:1 | { ... } | Test.kt:84:7:84:7 | x |
| Test.kt:82:21:89:1 | { ... } | Test.kt:86:4:88:2 | catch (...) |
+| Test.kt:91:1:98:1 | Normal Exit | Test.kt:91:1:98:1 | Exit |
| Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Exit |
+| Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Normal Exit |
| Test.kt:91:22:98:1 | { ... } | Test.kt:93:7:93:7 | x |
| Test.kt:91:22:98:1 | { ... } | Test.kt:95:4:97:2 | catch (...) |
| Test.kt:100:25:110:1 | { ... } | Test.kt:100:1:110:1 | Exit |
+| Test.kt:100:25:110:1 | { ... } | Test.kt:100:1:110:1 | Normal Exit |
| Test.kt:100:25:110:1 | { ... } | Test.kt:101:22:101:22 | y |
| Test.kt:100:25:110:1 | { ... } | Test.kt:101:33:103:5 | { ... } |
| Test.kt:100:25:110:1 | { ... } | Test.kt:105:5:109:5 | ; |
@@ -41,15 +50,20 @@
| Test.kt:100:25:110:1 | { ... } | Test.kt:107:16:109:5 | ... -> ... |
| Test.kt:100:25:110:1 | { ... } | Test.kt:107:27:109:5 | { ... } |
| Test.kt:101:22:101:22 | y | Test.kt:101:33:103:5 | { ... } |
+| Test.kt:105:5:109:5 | ; | Test.kt:100:1:110:1 | Normal Exit |
| Test.kt:105:5:109:5 | ; | Test.kt:105:20:107:5 | { ... } |
| Test.kt:105:5:109:5 | ; | Test.kt:107:16:109:5 | ... -> ... |
| Test.kt:105:5:109:5 | ; | Test.kt:107:27:109:5 | { ... } |
| Test.kt:107:16:109:5 | ... -> ... | Test.kt:107:27:109:5 | { ... } |
+| Test.kt:112:1:116:1 | Normal Exit | Test.kt:112:1:116:1 | Exit |
| Test.kt:112:32:116:1 | { ... } | Test.kt:112:1:116:1 | Exit |
+| Test.kt:112:32:116:1 | { ... } | Test.kt:112:1:116:1 | Normal Exit |
| Test.kt:112:32:116:1 | { ... } | Test.kt:113:14:113:14 | y |
| Test.kt:112:32:116:1 | { ... } | Test.kt:113:17:115:5 | { ... } |
| Test.kt:113:14:113:14 | y | Test.kt:113:17:115:5 | { ... } |
+| Test.kt:118:1:124:1 | Normal Exit | Test.kt:118:1:124:1 | Exit |
| Test.kt:118:37:124:1 | { ... } | Test.kt:118:1:124:1 | Exit |
+| Test.kt:118:37:124:1 | { ... } | Test.kt:118:1:124:1 | Normal Exit |
| Test.kt:118:37:124:1 | { ... } | Test.kt:121:9:121:9 | ; |
| Test.kt:118:37:124:1 | { ... } | Test.kt:122:12:122:16 | ... -> ... |
| Test.kt:118:37:124:1 | { ... } | Test.kt:123:8:123:10 | { ... } |
diff --git a/java/ql/test-kotlin1/library-tests/controlflow/basic/bbSuccessor.expected b/java/ql/test-kotlin1/library-tests/controlflow/basic/bbSuccessor.expected
index 3768db75d7e..cf5da7c83b7 100644
--- a/java/ql/test-kotlin1/library-tests/controlflow/basic/bbSuccessor.expected
+++ b/java/ql/test-kotlin1/library-tests/controlflow/basic/bbSuccessor.expected
@@ -1,10 +1,14 @@
+| Test.kt:3:8:80:1 | Exceptional Exit | Test.kt:3:8:80:1 | Exit |
+| Test.kt:3:8:80:1 | { ... } | Test.kt:3:8:80:1 | Exit |
+| Test.kt:4:2:79:2 | Exceptional Exit | Test.kt:4:2:79:2 | Exit |
+| Test.kt:4:2:79:2 | Normal Exit | Test.kt:4:2:79:2 | Exit |
| Test.kt:4:13:79:2 | { ... } | Test.kt:11:3:16:3 | ... -> ... |
| Test.kt:4:13:79:2 | { ... } | Test.kt:11:14:14:3 | { ... } |
| Test.kt:11:3:16:3 | ... -> ... | Test.kt:18:3:18:3 | ; |
| Test.kt:11:14:14:3 | { ... } | Test.kt:18:3:18:3 | ; |
| Test.kt:18:3:18:3 | ; | Test.kt:21:3:24:9 | ... -> ... |
| Test.kt:18:3:18:3 | ; | Test.kt:22:4:22:4 | ; |
-| Test.kt:21:3:24:9 | ... -> ... | Test.kt:4:2:79:2 | Exit |
+| Test.kt:21:3:24:9 | ... -> ... | Test.kt:4:2:79:2 | Normal Exit |
| Test.kt:22:4:22:4 | ; | Test.kt:30:15:33:3 | { ... } |
| Test.kt:22:4:22:4 | ; | Test.kt:35:3:35:3 | ; |
| Test.kt:30:15:33:3 | { ... } | Test.kt:35:3:35:3 | ; |
@@ -12,15 +16,20 @@
| Test.kt:38:9:38:9 | x | Test.kt:38:16:41:3 | { ... } |
| Test.kt:38:9:38:9 | x | Test.kt:43:3:43:3 | ; |
| Test.kt:38:16:41:3 | { ... } | Test.kt:38:9:38:9 | x |
-| Test.kt:43:3:43:3 | ; | Test.kt:4:2:79:2 | Exit |
+| Test.kt:43:3:43:3 | ; | Test.kt:4:2:79:2 | Normal Exit |
+| Test.kt:82:1:89:1 | Exceptional Exit | Test.kt:82:1:89:1 | Exit |
+| Test.kt:82:1:89:1 | Normal Exit | Test.kt:82:1:89:1 | Exit |
| Test.kt:82:21:89:1 | { ... } | Test.kt:84:7:84:7 | x |
| Test.kt:82:21:89:1 | { ... } | Test.kt:86:4:88:2 | catch (...) |
-| Test.kt:84:7:84:7 | x | Test.kt:82:1:89:1 | Exit |
-| Test.kt:86:4:88:2 | catch (...) | Test.kt:82:1:89:1 | Exit |
+| Test.kt:84:7:84:7 | x | Test.kt:82:1:89:1 | Normal Exit |
+| Test.kt:86:4:88:2 | catch (...) | Test.kt:82:1:89:1 | Normal Exit |
+| Test.kt:91:1:98:1 | Exceptional Exit | Test.kt:91:1:98:1 | Exit |
+| Test.kt:91:1:98:1 | Normal Exit | Test.kt:91:1:98:1 | Exit |
| Test.kt:91:22:98:1 | { ... } | Test.kt:93:7:93:7 | x |
| Test.kt:91:22:98:1 | { ... } | Test.kt:95:4:97:2 | catch (...) |
-| Test.kt:93:7:93:7 | x | Test.kt:91:1:98:1 | Exit |
-| Test.kt:95:4:97:2 | catch (...) | Test.kt:91:1:98:1 | Exit |
+| Test.kt:93:7:93:7 | x | Test.kt:91:1:98:1 | Normal Exit |
+| Test.kt:95:4:97:2 | catch (...) | Test.kt:91:1:98:1 | Normal Exit |
+| Test.kt:100:1:110:1 | Normal Exit | Test.kt:100:1:110:1 | Exit |
| Test.kt:100:25:110:1 | { ... } | Test.kt:101:22:101:22 | y |
| Test.kt:100:25:110:1 | { ... } | Test.kt:105:5:109:5 | ; |
| Test.kt:101:22:101:22 | y | Test.kt:101:33:103:5 | { ... } |
@@ -28,18 +37,22 @@
| Test.kt:101:33:103:5 | { ... } | Test.kt:100:1:110:1 | Exit |
| Test.kt:105:5:109:5 | ; | Test.kt:105:20:107:5 | { ... } |
| Test.kt:105:5:109:5 | ; | Test.kt:107:16:109:5 | ... -> ... |
-| Test.kt:105:20:107:5 | { ... } | Test.kt:100:1:110:1 | Exit |
-| Test.kt:107:16:109:5 | ... -> ... | Test.kt:100:1:110:1 | Exit |
+| Test.kt:105:20:107:5 | { ... } | Test.kt:100:1:110:1 | Normal Exit |
+| Test.kt:107:16:109:5 | ... -> ... | Test.kt:100:1:110:1 | Normal Exit |
| Test.kt:107:16:109:5 | ... -> ... | Test.kt:107:27:109:5 | { ... } |
-| Test.kt:107:27:109:5 | { ... } | Test.kt:100:1:110:1 | Exit |
-| Test.kt:112:32:116:1 | { ... } | Test.kt:112:1:116:1 | Exit |
+| Test.kt:107:27:109:5 | { ... } | Test.kt:100:1:110:1 | Normal Exit |
+| Test.kt:112:1:116:1 | Exceptional Exit | Test.kt:112:1:116:1 | Exit |
+| Test.kt:112:1:116:1 | Normal Exit | Test.kt:112:1:116:1 | Exit |
+| Test.kt:112:32:116:1 | { ... } | Test.kt:112:1:116:1 | Normal Exit |
| Test.kt:112:32:116:1 | { ... } | Test.kt:113:14:113:14 | y |
-| Test.kt:113:14:113:14 | y | Test.kt:112:1:116:1 | Exit |
+| Test.kt:113:14:113:14 | y | Test.kt:112:1:116:1 | Normal Exit |
| Test.kt:113:14:113:14 | y | Test.kt:113:17:115:5 | { ... } |
-| Test.kt:113:17:115:5 | { ... } | Test.kt:112:1:116:1 | Exit |
+| Test.kt:113:17:115:5 | { ... } | Test.kt:112:1:116:1 | Normal Exit |
+| Test.kt:118:1:124:1 | Exceptional Exit | Test.kt:118:1:124:1 | Exit |
+| Test.kt:118:1:124:1 | Normal Exit | Test.kt:118:1:124:1 | Exit |
| Test.kt:118:37:124:1 | { ... } | Test.kt:121:9:121:9 | ; |
| Test.kt:118:37:124:1 | { ... } | Test.kt:122:12:122:16 | ... -> ... |
-| Test.kt:121:9:121:9 | ; | Test.kt:118:1:124:1 | Exit |
+| Test.kt:121:9:121:9 | ; | Test.kt:118:1:124:1 | Normal Exit |
| Test.kt:121:9:121:9 | ; | Test.kt:123:8:123:10 | { ... } |
-| Test.kt:122:12:122:16 | ... -> ... | Test.kt:118:1:124:1 | Exit |
-| Test.kt:123:8:123:10 | { ... } | Test.kt:118:1:124:1 | Exit |
+| Test.kt:122:12:122:16 | ... -> ... | Test.kt:118:1:124:1 | Normal Exit |
+| Test.kt:123:8:123:10 | { ... } | Test.kt:118:1:124:1 | Normal Exit |
diff --git a/java/ql/test-kotlin1/library-tests/controlflow/basic/getASuccessor.expected b/java/ql/test-kotlin1/library-tests/controlflow/basic/getASuccessor.expected
index 81142abc1df..1d07b13c9d7 100644
--- a/java/ql/test-kotlin1/library-tests/controlflow/basic/getASuccessor.expected
+++ b/java/ql/test-kotlin1/library-tests/controlflow/basic/getASuccessor.expected
@@ -1,9 +1,13 @@
#select
| Test.kt:3:1:80:1 | super(...) | SuperConstructorInvocationStmt | Test.kt:3:8:80:1 | { ... } | BlockStmt |
+| Test.kt:3:8:80:1 | Exceptional Exit | Constructor | Test.kt:3:8:80:1 | Exit | Constructor |
| Test.kt:3:8:80:1 | Exit | Constructor | file://:0:0:0:0 | | |
+| Test.kt:3:8:80:1 | Normal Exit | Constructor | Test.kt:3:8:80:1 | Exit | Constructor |
| Test.kt:3:8:80:1 | { ... } | BlockStmt | Test.kt:3:1:80:1 | super(...) | SuperConstructorInvocationStmt |
-| Test.kt:3:8:80:1 | { ... } | BlockStmt | Test.kt:3:8:80:1 | Exit | Constructor |
+| Test.kt:3:8:80:1 | { ... } | BlockStmt | Test.kt:3:8:80:1 | Normal Exit | Constructor |
+| Test.kt:4:2:79:2 | Exceptional Exit | Method | Test.kt:4:2:79:2 | Exit | Method |
| Test.kt:4:2:79:2 | Exit | Method | file://:0:0:0:0 | | |
+| Test.kt:4:2:79:2 | Normal Exit | Method | Test.kt:4:2:79:2 | Exit | Method |
| Test.kt:4:13:79:2 | { ... } | BlockStmt | Test.kt:5:7:5:7 | var ...; | LocalVariableDeclStmt |
| Test.kt:5:7:5:7 | var ...; | LocalVariableDeclStmt | Test.kt:5:16:5:16 | 0 | IntegerLiteral |
| Test.kt:5:7:5:7 | x | LocalVariableDeclExpr | Test.kt:6:7:6:7 | var ...; | LocalVariableDeclStmt |
@@ -53,7 +57,7 @@
| Test.kt:22:4:22:9 | ...=... | AssignExpr | Test.kt:27:3:27:3 | ; | ExprStmt |
| Test.kt:22:8:22:9 | 40 | LongLiteral | Test.kt:22:4:22:9 | ...=... | AssignExpr |
| Test.kt:24:4:24:9 | INSTANCE | VarAccess | Test.kt:24:4:24:9 | return ... | ReturnStmt |
-| Test.kt:24:4:24:9 | return ... | ReturnStmt | Test.kt:4:2:79:2 | Exit | Method |
+| Test.kt:24:4:24:9 | return ... | ReturnStmt | Test.kt:4:2:79:2 | Normal Exit | Method |
| Test.kt:27:3:27:3 | ; | ExprStmt | Test.kt:27:7:27:8 | 10 | IntegerLiteral |
| Test.kt:27:3:27:8 | ...=... | AssignExpr | Test.kt:30:3:33:3 | ; | ExprStmt |
| Test.kt:27:7:27:8 | 10 | IntegerLiteral | Test.kt:27:3:27:8 | ...=... | AssignExpr |
@@ -106,8 +110,10 @@
| Test.kt:77:3:77:8 | ...=... | AssignExpr | Test.kt:78:3:78:8 | INSTANCE | VarAccess |
| Test.kt:77:7:77:8 | 40 | IntegerLiteral | Test.kt:77:3:77:8 | ...=... | AssignExpr |
| Test.kt:78:3:78:8 | INSTANCE | VarAccess | Test.kt:78:3:78:8 | return ... | ReturnStmt |
-| Test.kt:78:3:78:8 | return ... | ReturnStmt | Test.kt:4:2:79:2 | Exit | Method |
+| Test.kt:78:3:78:8 | return ... | ReturnStmt | Test.kt:4:2:79:2 | Normal Exit | Method |
+| Test.kt:82:1:89:1 | Exceptional Exit | Method | Test.kt:82:1:89:1 | Exit | Method |
| Test.kt:82:1:89:1 | Exit | Method | file://:0:0:0:0 | | |
+| Test.kt:82:1:89:1 | Normal Exit | Method | Test.kt:82:1:89:1 | Exit | Method |
| Test.kt:82:21:89:1 | { ... } | BlockStmt | Test.kt:83:2:88:2 | try ... | TryStmt |
| Test.kt:83:2:88:2 | try ... | TryStmt | Test.kt:83:6:86:2 | { ... } | BlockStmt |
| Test.kt:83:6:86:2 | { ... } | BlockStmt | Test.kt:84:7:84:7 | var ...; | LocalVariableDeclStmt |
@@ -116,14 +122,16 @@
| Test.kt:84:11:84:11 | o | VarAccess | Test.kt:84:11:84:18 | (...)... | CastExpr |
| Test.kt:84:11:84:18 | (...)... | CastExpr | Test.kt:84:7:84:7 | x | LocalVariableDeclExpr |
| Test.kt:84:11:84:18 | (...)... | CastExpr | Test.kt:86:4:88:2 | catch (...) | CatchClause |
-| Test.kt:85:3:85:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Exit | Method |
+| Test.kt:85:3:85:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Normal Exit | Method |
| Test.kt:85:10:85:10 | 1 | IntegerLiteral | Test.kt:85:3:85:10 | return ... | ReturnStmt |
| Test.kt:86:4:88:2 | catch (...) | CatchClause | Test.kt:86:11:86:31 | e | LocalVariableDeclExpr |
| Test.kt:86:11:86:31 | e | LocalVariableDeclExpr | Test.kt:86:34:88:2 | { ... } | BlockStmt |
| Test.kt:86:34:88:2 | { ... } | BlockStmt | Test.kt:87:10:87:10 | 2 | IntegerLiteral |
-| Test.kt:87:3:87:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Exit | Method |
+| Test.kt:87:3:87:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Normal Exit | Method |
| Test.kt:87:10:87:10 | 2 | IntegerLiteral | Test.kt:87:3:87:10 | return ... | ReturnStmt |
+| Test.kt:91:1:98:1 | Exceptional Exit | Method | Test.kt:91:1:98:1 | Exit | Method |
| Test.kt:91:1:98:1 | Exit | Method | file://:0:0:0:0 | | |
+| Test.kt:91:1:98:1 | Normal Exit | Method | Test.kt:91:1:98:1 | Exit | Method |
| Test.kt:91:22:98:1 | { ... } | BlockStmt | Test.kt:92:2:97:2 | try ... | TryStmt |
| Test.kt:92:2:97:2 | try ... | TryStmt | Test.kt:92:6:95:2 | { ... } | BlockStmt |
| Test.kt:92:6:95:2 | { ... } | BlockStmt | Test.kt:93:7:93:7 | var ...; | LocalVariableDeclStmt |
@@ -132,14 +140,16 @@
| Test.kt:93:11:93:11 | o | VarAccess | Test.kt:93:12:93:13 | ...!! | NotNullExpr |
| Test.kt:93:12:93:13 | ...!! | NotNullExpr | Test.kt:93:7:93:7 | x | LocalVariableDeclExpr |
| Test.kt:93:12:93:13 | ...!! | NotNullExpr | Test.kt:95:4:97:2 | catch (...) | CatchClause |
-| Test.kt:94:3:94:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Exit | Method |
+| Test.kt:94:3:94:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Normal Exit | Method |
| Test.kt:94:10:94:10 | 1 | IntegerLiteral | Test.kt:94:3:94:10 | return ... | ReturnStmt |
| Test.kt:95:4:97:2 | catch (...) | CatchClause | Test.kt:95:11:95:33 | e | LocalVariableDeclExpr |
| Test.kt:95:11:95:33 | e | LocalVariableDeclExpr | Test.kt:95:36:97:2 | { ... } | BlockStmt |
| Test.kt:95:36:97:2 | { ... } | BlockStmt | Test.kt:96:10:96:10 | 2 | IntegerLiteral |
-| Test.kt:96:3:96:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Exit | Method |
+| Test.kt:96:3:96:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Normal Exit | Method |
| Test.kt:96:10:96:10 | 2 | IntegerLiteral | Test.kt:96:3:96:10 | return ... | ReturnStmt |
+| Test.kt:100:1:110:1 | Exceptional Exit | Method | Test.kt:100:1:110:1 | Exit | Method |
| Test.kt:100:1:110:1 | Exit | Method | file://:0:0:0:0 | | |
+| Test.kt:100:1:110:1 | Normal Exit | Method | Test.kt:100:1:110:1 | Exit | Method |
| Test.kt:100:25:110:1 | { ... } | BlockStmt | Test.kt:101:5:103:5 | ; | ExprStmt |
| Test.kt:101:5:103:5 | ... -> ... | WhenBranch | Test.kt:101:9:101:30 | ... && ... | AndLogicalExpr |
| Test.kt:101:5:103:5 | ; | ExprStmt | Test.kt:101:5:103:5 | when ... | WhenExpr |
@@ -154,7 +164,7 @@
| Test.kt:101:22:101:30 | ... (value equals) ... | ValueEQExpr | Test.kt:105:5:109:5 | ; | ExprStmt |
| Test.kt:101:27:101:30 | null | NullLiteral | Test.kt:101:22:101:30 | ... (value equals) ... | ValueEQExpr |
| Test.kt:101:33:103:5 | { ... } | BlockStmt | Test.kt:102:15:102:25 | new Exception(...) | ClassInstanceExpr |
-| Test.kt:102:9:102:25 | throw ... | ThrowStmt | Test.kt:100:1:110:1 | Exit | Method |
+| Test.kt:102:9:102:25 | throw ... | ThrowStmt | Test.kt:100:1:110:1 | Exceptional Exit | Method |
| Test.kt:102:15:102:25 | new Exception(...) | ClassInstanceExpr | Test.kt:102:9:102:25 | throw ... | ThrowStmt |
| Test.kt:105:5:109:5 | ; | ExprStmt | Test.kt:105:5:109:5 | when ... | WhenExpr |
| Test.kt:105:5:109:5 | when ... | WhenExpr | Test.kt:105:9:107:5 | ... -> ... | WhenBranch |
@@ -165,29 +175,33 @@
| Test.kt:105:14:105:17 | null | NullLiteral | Test.kt:105:9:105:17 | ... (value not-equals) ... | ValueNEExpr |
| Test.kt:105:20:107:5 | { ... } | BlockStmt | Test.kt:106:9:106:29 | ; | ExprStmt |
| Test.kt:106:9:106:29 | ; | ExprStmt | Test.kt:106:17:106:28 | "x not null" | StringLiteral |
-| Test.kt:106:9:106:29 | println(...) | MethodCall | Test.kt:100:1:110:1 | Exit | Method |
+| Test.kt:106:9:106:29 | println(...) | MethodCall | Test.kt:100:1:110:1 | Normal Exit | Method |
| Test.kt:106:17:106:28 | "x not null" | StringLiteral | Test.kt:106:9:106:29 | println(...) | MethodCall |
| Test.kt:107:16:107:16 | y | VarAccess | Test.kt:107:21:107:24 | null | NullLiteral |
-| Test.kt:107:16:107:24 | ... (value not-equals) ... | ValueNEExpr | Test.kt:100:1:110:1 | Exit | Method |
+| Test.kt:107:16:107:24 | ... (value not-equals) ... | ValueNEExpr | Test.kt:100:1:110:1 | Normal Exit | Method |
| Test.kt:107:16:107:24 | ... (value not-equals) ... | ValueNEExpr | Test.kt:107:27:109:5 | { ... } | BlockStmt |
| Test.kt:107:16:109:5 | ... -> ... | WhenBranch | Test.kt:107:16:107:16 | y | VarAccess |
| Test.kt:107:21:107:24 | null | NullLiteral | Test.kt:107:16:107:24 | ... (value not-equals) ... | ValueNEExpr |
| Test.kt:107:27:109:5 | { ... } | BlockStmt | Test.kt:108:9:108:29 | ; | ExprStmt |
| Test.kt:108:9:108:29 | ; | ExprStmt | Test.kt:108:17:108:28 | "y not null" | StringLiteral |
-| Test.kt:108:9:108:29 | println(...) | MethodCall | Test.kt:100:1:110:1 | Exit | Method |
+| Test.kt:108:9:108:29 | println(...) | MethodCall | Test.kt:100:1:110:1 | Normal Exit | Method |
| Test.kt:108:17:108:28 | "y not null" | StringLiteral | Test.kt:108:9:108:29 | println(...) | MethodCall |
+| Test.kt:112:1:116:1 | Exceptional Exit | Method | Test.kt:112:1:116:1 | Exit | Method |
| Test.kt:112:1:116:1 | Exit | Method | file://:0:0:0:0 | | |
+| Test.kt:112:1:116:1 | Normal Exit | Method | Test.kt:112:1:116:1 | Exit | Method |
| Test.kt:112:32:116:1 | { ... } | BlockStmt | Test.kt:113:5:115:5 | ; | ExprStmt |
| Test.kt:113:5:115:5 | ... -> ... | WhenBranch | Test.kt:113:9:113:14 | ... && ... | AndLogicalExpr |
| Test.kt:113:5:115:5 | ; | ExprStmt | Test.kt:113:5:115:5 | when ... | WhenExpr |
| Test.kt:113:5:115:5 | when ... | WhenExpr | Test.kt:113:5:115:5 | ... -> ... | WhenBranch |
-| Test.kt:113:9:113:9 | x | VarAccess | Test.kt:112:1:116:1 | Exit | Method |
+| Test.kt:113:9:113:9 | x | VarAccess | Test.kt:112:1:116:1 | Normal Exit | Method |
| Test.kt:113:9:113:9 | x | VarAccess | Test.kt:113:14:113:14 | y | VarAccess |
| Test.kt:113:9:113:14 | ... && ... | AndLogicalExpr | Test.kt:113:9:113:9 | x | VarAccess |
-| Test.kt:113:14:113:14 | y | VarAccess | Test.kt:112:1:116:1 | Exit | Method |
+| Test.kt:113:14:113:14 | y | VarAccess | Test.kt:112:1:116:1 | Normal Exit | Method |
| Test.kt:113:14:113:14 | y | VarAccess | Test.kt:113:17:115:5 | { ... } | BlockStmt |
-| Test.kt:113:17:115:5 | { ... } | BlockStmt | Test.kt:112:1:116:1 | Exit | Method |
+| Test.kt:113:17:115:5 | { ... } | BlockStmt | Test.kt:112:1:116:1 | Normal Exit | Method |
+| Test.kt:118:1:124:1 | Exceptional Exit | Method | Test.kt:118:1:124:1 | Exit | Method |
| Test.kt:118:1:124:1 | Exit | Method | file://:0:0:0:0 | | |
+| Test.kt:118:1:124:1 | Normal Exit | Method | Test.kt:118:1:124:1 | Exit | Method |
| Test.kt:118:37:124:1 | { ... } | BlockStmt | Test.kt:119:2:123:12 | ; | ExprStmt |
| Test.kt:119:2:123:12 | ; | ExprStmt | Test.kt:119:2:123:12 | when ... | WhenExpr |
| Test.kt:119:2:123:12 | when ... | WhenExpr | Test.kt:120:3:123:10 | ... -> ... | WhenBranch |
@@ -197,11 +211,11 @@
| Test.kt:121:4:121:4 | x | VarAccess | Test.kt:122:12:122:16 | ... -> ... | WhenBranch |
| Test.kt:121:4:121:9 | ... -> ... | WhenBranch | Test.kt:121:4:121:4 | x | VarAccess |
| Test.kt:121:9:121:9 | ; | ExprStmt | Test.kt:121:9:121:9 | y | VarAccess |
-| Test.kt:121:9:121:9 | y | VarAccess | Test.kt:118:1:124:1 | Exit | Method |
+| Test.kt:121:9:121:9 | y | VarAccess | Test.kt:118:1:124:1 | Normal Exit | Method |
| Test.kt:121:9:121:9 | y | VarAccess | Test.kt:123:8:123:10 | { ... } | BlockStmt |
| Test.kt:122:12:122:16 | ... -> ... | WhenBranch | Test.kt:122:12:122:16 | true | BooleanLiteral |
| Test.kt:122:12:122:16 | ; | ExprStmt | Test.kt:122:12:122:16 | false | BooleanLiteral |
-| Test.kt:122:12:122:16 | false | BooleanLiteral | Test.kt:118:1:124:1 | Exit | Method |
+| Test.kt:122:12:122:16 | false | BooleanLiteral | Test.kt:118:1:124:1 | Normal Exit | Method |
| Test.kt:122:12:122:16 | true | BooleanLiteral | Test.kt:122:12:122:16 | ; | ExprStmt |
-| Test.kt:123:8:123:10 | { ... } | BlockStmt | Test.kt:118:1:124:1 | Exit | Method |
+| Test.kt:123:8:123:10 | { ... } | BlockStmt | Test.kt:118:1:124:1 | Normal Exit | Method |
missingSuccessor
diff --git a/java/ql/test-kotlin1/library-tests/controlflow/dominance/dominator.expected b/java/ql/test-kotlin1/library-tests/controlflow/dominance/dominator.expected
index 3eae2345186..31da586d630 100644
--- a/java/ql/test-kotlin1/library-tests/controlflow/dominance/dominator.expected
+++ b/java/ql/test-kotlin1/library-tests/controlflow/dominance/dominator.expected
@@ -44,7 +44,7 @@
| Test.kt:21:3:24:11 | true | Test.kt:24:11:24:11 | z |
| Test.kt:21:3:24:11 | when ... | Test.kt:21:3:24:11 | ... -> ... |
| Test.kt:21:7:21:7 | x | Test.kt:21:11:21:11 | 0 |
-| Test.kt:21:7:21:11 | ... < ... | Test.kt:2:2:79:2 | Exit |
+| Test.kt:21:7:21:11 | ... < ... | Test.kt:2:2:79:2 | Normal Exit |
| Test.kt:21:7:21:11 | ... < ... | Test.kt:21:3:24:11 | ... -> ... |
| Test.kt:21:7:21:11 | ... < ... | Test.kt:22:4:22:4 | ; |
| Test.kt:21:11:21:11 | 0 | Test.kt:21:7:21:11 | ... < ... |
@@ -142,7 +142,7 @@
| Test.kt:92:4:93:9 | ; | Test.kt:92:4:93:9 | when ... |
| Test.kt:92:4:93:9 | when ... | Test.kt:92:4:93:9 | ... -> ... |
| Test.kt:92:8:92:8 | a | Test.kt:92:13:92:14 | 10 |
-| Test.kt:92:8:92:14 | ... (value equals) ... | Test.kt:81:2:98:2 | Exit |
+| Test.kt:92:8:92:14 | ... (value equals) ... | Test.kt:81:2:98:2 | Normal Exit |
| Test.kt:92:8:92:14 | ... (value equals) ... | Test.kt:93:5:93:9 | break |
| Test.kt:92:8:92:14 | ... (value equals) ... | Test.kt:94:4:95:12 | ; |
| Test.kt:92:13:92:14 | 10 | Test.kt:92:8:92:14 | ... (value equals) ... |
diff --git a/java/ql/test-kotlin2/library-tests/controlflow/basic/bbStmts.expected b/java/ql/test-kotlin2/library-tests/controlflow/basic/bbStmts.expected
index c0f86a6ec9b..c66d50a722d 100644
--- a/java/ql/test-kotlin2/library-tests/controlflow/basic/bbStmts.expected
+++ b/java/ql/test-kotlin2/library-tests/controlflow/basic/bbStmts.expected
@@ -1,8 +1,12 @@
+| Test.kt:3:1:80:1 | Exceptional Exit | 0 | Test.kt:3:1:80:1 | Exceptional Exit |
+| Test.kt:3:1:80:1 | Exit | 0 | Test.kt:3:1:80:1 | Exit |
| Test.kt:3:1:80:1 | { ... } | 0 | Test.kt:3:1:80:1 | { ... } |
| Test.kt:3:1:80:1 | { ... } | 1 | Test.kt:3:1:80:1 | super(...) |
| Test.kt:3:1:80:1 | { ... } | 2 | Test.kt:3:1:80:1 | { ... } |
-| Test.kt:3:1:80:1 | { ... } | 3 | Test.kt:3:1:80:1 | Exit |
+| Test.kt:3:1:80:1 | { ... } | 3 | Test.kt:3:1:80:1 | Normal Exit |
+| Test.kt:4:2:79:2 | Exceptional Exit | 0 | Test.kt:4:2:79:2 | Exceptional Exit |
| Test.kt:4:2:79:2 | Exit | 0 | Test.kt:4:2:79:2 | Exit |
+| Test.kt:4:2:79:2 | Normal Exit | 0 | Test.kt:4:2:79:2 | Normal Exit |
| Test.kt:4:13:79:2 | { ... } | 0 | Test.kt:4:13:79:2 | { ... } |
| Test.kt:4:13:79:2 | { ... } | 1 | Test.kt:5:3:5:16 | var ...; |
| Test.kt:4:13:79:2 | { ... } | 2 | Test.kt:5:16:5:16 | 0 |
@@ -102,7 +106,9 @@
| Test.kt:43:3:43:8 | ; | 8 | Test.kt:77:3:77:8 | ...=... |
| Test.kt:43:3:43:8 | ; | 9 | Test.kt:78:9:78:9 | INSTANCE |
| Test.kt:43:3:43:8 | ; | 10 | Test.kt:78:3:78:8 | return ... |
+| Test.kt:82:1:89:1 | Exceptional Exit | 0 | Test.kt:82:1:89:1 | Exceptional Exit |
| Test.kt:82:1:89:1 | Exit | 0 | Test.kt:82:1:89:1 | Exit |
+| Test.kt:82:1:89:1 | Normal Exit | 0 | Test.kt:82:1:89:1 | Normal Exit |
| Test.kt:82:21:89:1 | { ... } | 0 | Test.kt:82:21:89:1 | { ... } |
| Test.kt:82:21:89:1 | { ... } | 1 | Test.kt:83:2:88:2 | try ... |
| Test.kt:82:21:89:1 | { ... } | 2 | Test.kt:83:6:86:2 | { ... } |
@@ -117,7 +123,9 @@
| Test.kt:86:4:88:2 | catch (...) | 2 | Test.kt:86:34:88:2 | { ... } |
| Test.kt:86:4:88:2 | catch (...) | 3 | Test.kt:87:10:87:10 | 2 |
| Test.kt:86:4:88:2 | catch (...) | 4 | Test.kt:87:3:87:10 | return ... |
+| Test.kt:91:1:98:1 | Exceptional Exit | 0 | Test.kt:91:1:98:1 | Exceptional Exit |
| Test.kt:91:1:98:1 | Exit | 0 | Test.kt:91:1:98:1 | Exit |
+| Test.kt:91:1:98:1 | Normal Exit | 0 | Test.kt:91:1:98:1 | Normal Exit |
| Test.kt:91:22:98:1 | { ... } | 0 | Test.kt:91:22:98:1 | { ... } |
| Test.kt:91:22:98:1 | { ... } | 1 | Test.kt:92:2:97:2 | try ... |
| Test.kt:91:22:98:1 | { ... } | 2 | Test.kt:92:6:95:2 | { ... } |
@@ -133,6 +141,7 @@
| Test.kt:95:4:97:2 | catch (...) | 3 | Test.kt:96:10:96:10 | 2 |
| Test.kt:95:4:97:2 | catch (...) | 4 | Test.kt:96:3:96:10 | return ... |
| Test.kt:100:1:110:1 | Exit | 0 | Test.kt:100:1:110:1 | Exit |
+| Test.kt:100:1:110:1 | Normal Exit | 0 | Test.kt:100:1:110:1 | Normal Exit |
| Test.kt:100:25:110:1 | { ... } | 0 | Test.kt:100:25:110:1 | { ... } |
| Test.kt:100:25:110:1 | { ... } | 1 | Test.kt:101:5:103:5 | ; |
| Test.kt:100:25:110:1 | { ... } | 2 | Test.kt:101:5:103:5 | when ... |
@@ -147,6 +156,7 @@
| Test.kt:101:33:103:5 | { ... } | 0 | Test.kt:101:33:103:5 | { ... } |
| Test.kt:101:33:103:5 | { ... } | 1 | Test.kt:102:15:102:25 | new Exception(...) |
| Test.kt:101:33:103:5 | { ... } | 2 | Test.kt:102:9:102:25 | throw ... |
+| Test.kt:101:33:103:5 | { ... } | 3 | Test.kt:100:1:110:1 | Exceptional Exit |
| Test.kt:105:5:109:5 | ; | 0 | Test.kt:105:5:109:5 | ; |
| Test.kt:105:5:109:5 | ; | 1 | Test.kt:105:5:109:5 | when ... |
| Test.kt:105:5:109:5 | ; | 2 | Test.kt:105:9:107:5 | ... -> ... |
@@ -165,7 +175,9 @@
| Test.kt:107:27:109:5 | { ... } | 1 | Test.kt:108:9:108:29 | ; |
| Test.kt:107:27:109:5 | { ... } | 2 | Test.kt:108:17:108:28 | "y not null" |
| Test.kt:107:27:109:5 | { ... } | 3 | Test.kt:108:9:108:29 | println(...) |
+| Test.kt:112:1:116:1 | Exceptional Exit | 0 | Test.kt:112:1:116:1 | Exceptional Exit |
| Test.kt:112:1:116:1 | Exit | 0 | Test.kt:112:1:116:1 | Exit |
+| Test.kt:112:1:116:1 | Normal Exit | 0 | Test.kt:112:1:116:1 | Normal Exit |
| Test.kt:112:32:116:1 | { ... } | 0 | Test.kt:112:32:116:1 | { ... } |
| Test.kt:112:32:116:1 | { ... } | 1 | Test.kt:113:5:115:5 | ; |
| Test.kt:112:32:116:1 | { ... } | 2 | Test.kt:113:5:115:5 | when ... |
@@ -174,7 +186,9 @@
| Test.kt:112:32:116:1 | { ... } | 5 | Test.kt:113:9:113:9 | x |
| Test.kt:113:14:113:14 | y | 0 | Test.kt:113:14:113:14 | y |
| Test.kt:113:17:115:5 | { ... } | 0 | Test.kt:113:17:115:5 | { ... } |
+| Test.kt:118:1:124:1 | Exceptional Exit | 0 | Test.kt:118:1:124:1 | Exceptional Exit |
| Test.kt:118:1:124:1 | Exit | 0 | Test.kt:118:1:124:1 | Exit |
+| Test.kt:118:1:124:1 | Normal Exit | 0 | Test.kt:118:1:124:1 | Normal Exit |
| Test.kt:118:37:124:1 | { ... } | 0 | Test.kt:118:37:124:1 | { ... } |
| Test.kt:118:37:124:1 | { ... } | 1 | Test.kt:119:2:123:12 | ; |
| Test.kt:118:37:124:1 | { ... } | 2 | Test.kt:119:2:123:12 | when ... |
diff --git a/java/ql/test-kotlin2/library-tests/controlflow/basic/bbStrictDominance.expected b/java/ql/test-kotlin2/library-tests/controlflow/basic/bbStrictDominance.expected
index aa23696bd55..c7e225ecc6f 100644
--- a/java/ql/test-kotlin2/library-tests/controlflow/basic/bbStrictDominance.expected
+++ b/java/ql/test-kotlin2/library-tests/controlflow/basic/bbStrictDominance.expected
@@ -1,4 +1,7 @@
+| Test.kt:3:1:80:1 | { ... } | Test.kt:3:1:80:1 | Exit |
+| Test.kt:4:2:79:2 | Normal Exit | Test.kt:4:2:79:2 | Exit |
| Test.kt:4:13:79:2 | { ... } | Test.kt:4:2:79:2 | Exit |
+| Test.kt:4:13:79:2 | { ... } | Test.kt:4:2:79:2 | Normal Exit |
| Test.kt:4:13:79:2 | { ... } | Test.kt:11:14:14:3 | { ... } |
| Test.kt:4:13:79:2 | { ... } | Test.kt:14:10:16:3 | ... -> ... |
| Test.kt:4:13:79:2 | { ... } | Test.kt:18:3:18:7 | ; |
@@ -10,6 +13,7 @@
| Test.kt:4:13:79:2 | { ... } | Test.kt:38:16:41:3 | { ... } |
| Test.kt:4:13:79:2 | { ... } | Test.kt:43:3:43:8 | ; |
| Test.kt:18:3:18:7 | ; | Test.kt:4:2:79:2 | Exit |
+| Test.kt:18:3:18:7 | ; | Test.kt:4:2:79:2 | Normal Exit |
| Test.kt:18:3:18:7 | ; | Test.kt:22:4:22:9 | ; |
| Test.kt:18:3:18:7 | ; | Test.kt:24:4:24:9 | ... -> ... |
| Test.kt:18:3:18:7 | ; | Test.kt:30:15:33:3 | { ... } |
@@ -27,13 +31,18 @@
| Test.kt:35:3:35:8 | ; | Test.kt:43:3:43:8 | ; |
| Test.kt:38:9:38:9 | x | Test.kt:38:16:41:3 | { ... } |
| Test.kt:38:9:38:9 | x | Test.kt:43:3:43:8 | ; |
+| Test.kt:82:1:89:1 | Normal Exit | Test.kt:82:1:89:1 | Exit |
| Test.kt:82:21:89:1 | { ... } | Test.kt:82:1:89:1 | Exit |
+| Test.kt:82:21:89:1 | { ... } | Test.kt:82:1:89:1 | Normal Exit |
| Test.kt:82:21:89:1 | { ... } | Test.kt:84:3:84:18 | x |
| Test.kt:82:21:89:1 | { ... } | Test.kt:86:4:88:2 | catch (...) |
+| Test.kt:91:1:98:1 | Normal Exit | Test.kt:91:1:98:1 | Exit |
| Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Exit |
+| Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Normal Exit |
| Test.kt:91:22:98:1 | { ... } | Test.kt:93:3:93:13 | x |
| Test.kt:91:22:98:1 | { ... } | Test.kt:95:4:97:2 | catch (...) |
| Test.kt:100:25:110:1 | { ... } | Test.kt:100:1:110:1 | Exit |
+| Test.kt:100:25:110:1 | { ... } | Test.kt:100:1:110:1 | Normal Exit |
| Test.kt:100:25:110:1 | { ... } | Test.kt:101:22:101:22 | y |
| Test.kt:100:25:110:1 | { ... } | Test.kt:101:33:103:5 | { ... } |
| Test.kt:100:25:110:1 | { ... } | Test.kt:105:5:109:5 | ; |
@@ -41,15 +50,20 @@
| Test.kt:100:25:110:1 | { ... } | Test.kt:107:16:109:5 | ... -> ... |
| Test.kt:100:25:110:1 | { ... } | Test.kt:107:27:109:5 | { ... } |
| Test.kt:101:22:101:22 | y | Test.kt:101:33:103:5 | { ... } |
+| Test.kt:105:5:109:5 | ; | Test.kt:100:1:110:1 | Normal Exit |
| Test.kt:105:5:109:5 | ; | Test.kt:105:20:107:5 | { ... } |
| Test.kt:105:5:109:5 | ; | Test.kt:107:16:109:5 | ... -> ... |
| Test.kt:105:5:109:5 | ; | Test.kt:107:27:109:5 | { ... } |
| Test.kt:107:16:109:5 | ... -> ... | Test.kt:107:27:109:5 | { ... } |
+| Test.kt:112:1:116:1 | Normal Exit | Test.kt:112:1:116:1 | Exit |
| Test.kt:112:32:116:1 | { ... } | Test.kt:112:1:116:1 | Exit |
+| Test.kt:112:32:116:1 | { ... } | Test.kt:112:1:116:1 | Normal Exit |
| Test.kt:112:32:116:1 | { ... } | Test.kt:113:14:113:14 | y |
| Test.kt:112:32:116:1 | { ... } | Test.kt:113:17:115:5 | { ... } |
| Test.kt:113:14:113:14 | y | Test.kt:113:17:115:5 | { ... } |
+| Test.kt:118:1:124:1 | Normal Exit | Test.kt:118:1:124:1 | Exit |
| Test.kt:118:37:124:1 | { ... } | Test.kt:118:1:124:1 | Exit |
+| Test.kt:118:37:124:1 | { ... } | Test.kt:118:1:124:1 | Normal Exit |
| Test.kt:118:37:124:1 | { ... } | Test.kt:121:9:121:9 | ; |
| Test.kt:118:37:124:1 | { ... } | Test.kt:122:12:122:16 | ... -> ... |
| Test.kt:118:37:124:1 | { ... } | Test.kt:123:8:123:10 | { ... } |
diff --git a/java/ql/test-kotlin2/library-tests/controlflow/basic/bbSuccessor.expected b/java/ql/test-kotlin2/library-tests/controlflow/basic/bbSuccessor.expected
index 006bd71a6ba..219779e73dc 100644
--- a/java/ql/test-kotlin2/library-tests/controlflow/basic/bbSuccessor.expected
+++ b/java/ql/test-kotlin2/library-tests/controlflow/basic/bbSuccessor.expected
@@ -1,3 +1,7 @@
+| Test.kt:3:1:80:1 | Exceptional Exit | Test.kt:3:1:80:1 | Exit |
+| Test.kt:3:1:80:1 | { ... } | Test.kt:3:1:80:1 | Exit |
+| Test.kt:4:2:79:2 | Exceptional Exit | Test.kt:4:2:79:2 | Exit |
+| Test.kt:4:2:79:2 | Normal Exit | Test.kt:4:2:79:2 | Exit |
| Test.kt:4:13:79:2 | { ... } | Test.kt:11:14:14:3 | { ... } |
| Test.kt:4:13:79:2 | { ... } | Test.kt:14:10:16:3 | ... -> ... |
| Test.kt:11:14:14:3 | { ... } | Test.kt:18:3:18:7 | ; |
@@ -6,21 +10,26 @@
| Test.kt:18:3:18:7 | ; | Test.kt:24:4:24:9 | ... -> ... |
| Test.kt:22:4:22:9 | ; | Test.kt:30:15:33:3 | { ... } |
| Test.kt:22:4:22:9 | ; | Test.kt:35:3:35:8 | ; |
-| Test.kt:24:4:24:9 | ... -> ... | Test.kt:4:2:79:2 | Exit |
+| Test.kt:24:4:24:9 | ... -> ... | Test.kt:4:2:79:2 | Normal Exit |
| Test.kt:30:15:33:3 | { ... } | Test.kt:35:3:35:8 | ; |
| Test.kt:35:3:35:8 | ; | Test.kt:38:9:38:9 | x |
| Test.kt:38:9:38:9 | x | Test.kt:38:16:41:3 | { ... } |
| Test.kt:38:9:38:9 | x | Test.kt:43:3:43:8 | ; |
| Test.kt:38:16:41:3 | { ... } | Test.kt:38:9:38:9 | x |
-| Test.kt:43:3:43:8 | ; | Test.kt:4:2:79:2 | Exit |
+| Test.kt:43:3:43:8 | ; | Test.kt:4:2:79:2 | Normal Exit |
+| Test.kt:82:1:89:1 | Exceptional Exit | Test.kt:82:1:89:1 | Exit |
+| Test.kt:82:1:89:1 | Normal Exit | Test.kt:82:1:89:1 | Exit |
| Test.kt:82:21:89:1 | { ... } | Test.kt:84:3:84:18 | x |
| Test.kt:82:21:89:1 | { ... } | Test.kt:86:4:88:2 | catch (...) |
-| Test.kt:84:3:84:18 | x | Test.kt:82:1:89:1 | Exit |
-| Test.kt:86:4:88:2 | catch (...) | Test.kt:82:1:89:1 | Exit |
+| Test.kt:84:3:84:18 | x | Test.kt:82:1:89:1 | Normal Exit |
+| Test.kt:86:4:88:2 | catch (...) | Test.kt:82:1:89:1 | Normal Exit |
+| Test.kt:91:1:98:1 | Exceptional Exit | Test.kt:91:1:98:1 | Exit |
+| Test.kt:91:1:98:1 | Normal Exit | Test.kt:91:1:98:1 | Exit |
| Test.kt:91:22:98:1 | { ... } | Test.kt:93:3:93:13 | x |
| Test.kt:91:22:98:1 | { ... } | Test.kt:95:4:97:2 | catch (...) |
-| Test.kt:93:3:93:13 | x | Test.kt:91:1:98:1 | Exit |
-| Test.kt:95:4:97:2 | catch (...) | Test.kt:91:1:98:1 | Exit |
+| Test.kt:93:3:93:13 | x | Test.kt:91:1:98:1 | Normal Exit |
+| Test.kt:95:4:97:2 | catch (...) | Test.kt:91:1:98:1 | Normal Exit |
+| Test.kt:100:1:110:1 | Normal Exit | Test.kt:100:1:110:1 | Exit |
| Test.kt:100:25:110:1 | { ... } | Test.kt:101:22:101:22 | y |
| Test.kt:100:25:110:1 | { ... } | Test.kt:105:5:109:5 | ; |
| Test.kt:101:22:101:22 | y | Test.kt:101:33:103:5 | { ... } |
@@ -28,18 +37,22 @@
| Test.kt:101:33:103:5 | { ... } | Test.kt:100:1:110:1 | Exit |
| Test.kt:105:5:109:5 | ; | Test.kt:105:20:107:5 | { ... } |
| Test.kt:105:5:109:5 | ; | Test.kt:107:16:109:5 | ... -> ... |
-| Test.kt:105:20:107:5 | { ... } | Test.kt:100:1:110:1 | Exit |
-| Test.kt:107:16:109:5 | ... -> ... | Test.kt:100:1:110:1 | Exit |
+| Test.kt:105:20:107:5 | { ... } | Test.kt:100:1:110:1 | Normal Exit |
+| Test.kt:107:16:109:5 | ... -> ... | Test.kt:100:1:110:1 | Normal Exit |
| Test.kt:107:16:109:5 | ... -> ... | Test.kt:107:27:109:5 | { ... } |
-| Test.kt:107:27:109:5 | { ... } | Test.kt:100:1:110:1 | Exit |
-| Test.kt:112:32:116:1 | { ... } | Test.kt:112:1:116:1 | Exit |
+| Test.kt:107:27:109:5 | { ... } | Test.kt:100:1:110:1 | Normal Exit |
+| Test.kt:112:1:116:1 | Exceptional Exit | Test.kt:112:1:116:1 | Exit |
+| Test.kt:112:1:116:1 | Normal Exit | Test.kt:112:1:116:1 | Exit |
+| Test.kt:112:32:116:1 | { ... } | Test.kt:112:1:116:1 | Normal Exit |
| Test.kt:112:32:116:1 | { ... } | Test.kt:113:14:113:14 | y |
-| Test.kt:113:14:113:14 | y | Test.kt:112:1:116:1 | Exit |
+| Test.kt:113:14:113:14 | y | Test.kt:112:1:116:1 | Normal Exit |
| Test.kt:113:14:113:14 | y | Test.kt:113:17:115:5 | { ... } |
-| Test.kt:113:17:115:5 | { ... } | Test.kt:112:1:116:1 | Exit |
+| Test.kt:113:17:115:5 | { ... } | Test.kt:112:1:116:1 | Normal Exit |
+| Test.kt:118:1:124:1 | Exceptional Exit | Test.kt:118:1:124:1 | Exit |
+| Test.kt:118:1:124:1 | Normal Exit | Test.kt:118:1:124:1 | Exit |
| Test.kt:118:37:124:1 | { ... } | Test.kt:121:9:121:9 | ; |
| Test.kt:118:37:124:1 | { ... } | Test.kt:122:12:122:16 | ... -> ... |
-| Test.kt:121:9:121:9 | ; | Test.kt:118:1:124:1 | Exit |
+| Test.kt:121:9:121:9 | ; | Test.kt:118:1:124:1 | Normal Exit |
| Test.kt:121:9:121:9 | ; | Test.kt:123:8:123:10 | { ... } |
-| Test.kt:122:12:122:16 | ... -> ... | Test.kt:118:1:124:1 | Exit |
-| Test.kt:123:8:123:10 | { ... } | Test.kt:118:1:124:1 | Exit |
+| Test.kt:122:12:122:16 | ... -> ... | Test.kt:118:1:124:1 | Normal Exit |
+| Test.kt:123:8:123:10 | { ... } | Test.kt:118:1:124:1 | Normal Exit |
diff --git a/java/ql/test-kotlin2/library-tests/controlflow/basic/getASuccessor.expected b/java/ql/test-kotlin2/library-tests/controlflow/basic/getASuccessor.expected
index 364b46d429e..c4be613c5e9 100644
--- a/java/ql/test-kotlin2/library-tests/controlflow/basic/getASuccessor.expected
+++ b/java/ql/test-kotlin2/library-tests/controlflow/basic/getASuccessor.expected
@@ -1,9 +1,13 @@
#select
+| Test.kt:3:1:80:1 | Exceptional Exit | Constructor | Test.kt:3:1:80:1 | Exit | Constructor |
| Test.kt:3:1:80:1 | Exit | Constructor | file://:0:0:0:0 | | |
+| Test.kt:3:1:80:1 | Normal Exit | Constructor | Test.kt:3:1:80:1 | Exit | Constructor |
| Test.kt:3:1:80:1 | super(...) | SuperConstructorInvocationStmt | Test.kt:3:1:80:1 | { ... } | BlockStmt |
-| Test.kt:3:1:80:1 | { ... } | BlockStmt | Test.kt:3:1:80:1 | Exit | Constructor |
+| Test.kt:3:1:80:1 | { ... } | BlockStmt | Test.kt:3:1:80:1 | Normal Exit | Constructor |
| Test.kt:3:1:80:1 | { ... } | BlockStmt | Test.kt:3:1:80:1 | super(...) | SuperConstructorInvocationStmt |
+| Test.kt:4:2:79:2 | Exceptional Exit | Method | Test.kt:4:2:79:2 | Exit | Method |
| Test.kt:4:2:79:2 | Exit | Method | file://:0:0:0:0 | | |
+| Test.kt:4:2:79:2 | Normal Exit | Method | Test.kt:4:2:79:2 | Exit | Method |
| Test.kt:4:13:79:2 | { ... } | BlockStmt | Test.kt:5:3:5:16 | var ...; | LocalVariableDeclStmt |
| Test.kt:5:3:5:16 | var ...; | LocalVariableDeclStmt | Test.kt:5:16:5:16 | 0 | IntegerLiteral |
| Test.kt:5:3:5:16 | x | LocalVariableDeclExpr | Test.kt:6:3:6:18 | var ...; | LocalVariableDeclStmt |
@@ -51,7 +55,7 @@
| Test.kt:22:4:22:9 | ; | ExprStmt | Test.kt:22:8:22:9 | 40 | LongLiteral |
| Test.kt:22:8:22:9 | 40 | LongLiteral | Test.kt:22:4:22:9 | ...=... | AssignExpr |
| Test.kt:24:4:24:9 | ... -> ... | WhenBranch | Test.kt:24:4:24:9 | true | BooleanLiteral |
-| Test.kt:24:4:24:9 | return ... | ReturnStmt | Test.kt:4:2:79:2 | Exit | Method |
+| Test.kt:24:4:24:9 | return ... | ReturnStmt | Test.kt:4:2:79:2 | Normal Exit | Method |
| Test.kt:24:4:24:9 | true | BooleanLiteral | Test.kt:24:10:24:10 | INSTANCE | VarAccess |
| Test.kt:24:10:24:10 | INSTANCE | VarAccess | Test.kt:24:4:24:9 | return ... | ReturnStmt |
| Test.kt:27:3:27:8 | ...=... | AssignExpr | Test.kt:30:3:33:3 | ; | ExprStmt |
@@ -105,9 +109,11 @@
| Test.kt:77:3:77:8 | ...=... | AssignExpr | Test.kt:78:9:78:9 | INSTANCE | VarAccess |
| Test.kt:77:3:77:8 | ; | ExprStmt | Test.kt:77:7:77:8 | 40 | IntegerLiteral |
| Test.kt:77:7:77:8 | 40 | IntegerLiteral | Test.kt:77:3:77:8 | ...=... | AssignExpr |
-| Test.kt:78:3:78:8 | return ... | ReturnStmt | Test.kt:4:2:79:2 | Exit | Method |
+| Test.kt:78:3:78:8 | return ... | ReturnStmt | Test.kt:4:2:79:2 | Normal Exit | Method |
| Test.kt:78:9:78:9 | INSTANCE | VarAccess | Test.kt:78:3:78:8 | return ... | ReturnStmt |
+| Test.kt:82:1:89:1 | Exceptional Exit | Method | Test.kt:82:1:89:1 | Exit | Method |
| Test.kt:82:1:89:1 | Exit | Method | file://:0:0:0:0 | | |
+| Test.kt:82:1:89:1 | Normal Exit | Method | Test.kt:82:1:89:1 | Exit | Method |
| Test.kt:82:21:89:1 | { ... } | BlockStmt | Test.kt:83:2:88:2 | try ... | TryStmt |
| Test.kt:83:2:88:2 | try ... | TryStmt | Test.kt:83:6:86:2 | { ... } | BlockStmt |
| Test.kt:83:6:86:2 | { ... } | BlockStmt | Test.kt:84:3:84:18 | var ...; | LocalVariableDeclStmt |
@@ -116,14 +122,16 @@
| Test.kt:84:11:84:11 | o | VarAccess | Test.kt:84:11:84:18 | (...)... | CastExpr |
| Test.kt:84:11:84:18 | (...)... | CastExpr | Test.kt:84:3:84:18 | x | LocalVariableDeclExpr |
| Test.kt:84:11:84:18 | (...)... | CastExpr | Test.kt:86:4:88:2 | catch (...) | CatchClause |
-| Test.kt:85:3:85:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Exit | Method |
+| Test.kt:85:3:85:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Normal Exit | Method |
| Test.kt:85:10:85:10 | 1 | IntegerLiteral | Test.kt:85:3:85:10 | return ... | ReturnStmt |
| Test.kt:86:4:88:2 | catch (...) | CatchClause | Test.kt:86:11:86:31 | e | LocalVariableDeclExpr |
| Test.kt:86:11:86:31 | e | LocalVariableDeclExpr | Test.kt:86:34:88:2 | { ... } | BlockStmt |
| Test.kt:86:34:88:2 | { ... } | BlockStmt | Test.kt:87:10:87:10 | 2 | IntegerLiteral |
-| Test.kt:87:3:87:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Exit | Method |
+| Test.kt:87:3:87:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Normal Exit | Method |
| Test.kt:87:10:87:10 | 2 | IntegerLiteral | Test.kt:87:3:87:10 | return ... | ReturnStmt |
+| Test.kt:91:1:98:1 | Exceptional Exit | Method | Test.kt:91:1:98:1 | Exit | Method |
| Test.kt:91:1:98:1 | Exit | Method | file://:0:0:0:0 | | |
+| Test.kt:91:1:98:1 | Normal Exit | Method | Test.kt:91:1:98:1 | Exit | Method |
| Test.kt:91:22:98:1 | { ... } | BlockStmt | Test.kt:92:2:97:2 | try ... | TryStmt |
| Test.kt:92:2:97:2 | try ... | TryStmt | Test.kt:92:6:95:2 | { ... } | BlockStmt |
| Test.kt:92:6:95:2 | { ... } | BlockStmt | Test.kt:93:3:93:13 | var ...; | LocalVariableDeclStmt |
@@ -132,14 +140,16 @@
| Test.kt:93:11:93:11 | o | VarAccess | Test.kt:93:11:93:13 | ...!! | NotNullExpr |
| Test.kt:93:11:93:13 | ...!! | NotNullExpr | Test.kt:93:3:93:13 | x | LocalVariableDeclExpr |
| Test.kt:93:11:93:13 | ...!! | NotNullExpr | Test.kt:95:4:97:2 | catch (...) | CatchClause |
-| Test.kt:94:3:94:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Exit | Method |
+| Test.kt:94:3:94:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Normal Exit | Method |
| Test.kt:94:10:94:10 | 1 | IntegerLiteral | Test.kt:94:3:94:10 | return ... | ReturnStmt |
| Test.kt:95:4:97:2 | catch (...) | CatchClause | Test.kt:95:11:95:33 | e | LocalVariableDeclExpr |
| Test.kt:95:11:95:33 | e | LocalVariableDeclExpr | Test.kt:95:36:97:2 | { ... } | BlockStmt |
| Test.kt:95:36:97:2 | { ... } | BlockStmt | Test.kt:96:10:96:10 | 2 | IntegerLiteral |
-| Test.kt:96:3:96:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Exit | Method |
+| Test.kt:96:3:96:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Normal Exit | Method |
| Test.kt:96:10:96:10 | 2 | IntegerLiteral | Test.kt:96:3:96:10 | return ... | ReturnStmt |
+| Test.kt:100:1:110:1 | Exceptional Exit | Method | Test.kt:100:1:110:1 | Exit | Method |
| Test.kt:100:1:110:1 | Exit | Method | file://:0:0:0:0 | | |
+| Test.kt:100:1:110:1 | Normal Exit | Method | Test.kt:100:1:110:1 | Exit | Method |
| Test.kt:100:25:110:1 | { ... } | BlockStmt | Test.kt:101:5:103:5 | ; | ExprStmt |
| Test.kt:101:5:103:5 | ; | ExprStmt | Test.kt:101:5:103:5 | when ... | WhenExpr |
| Test.kt:101:5:103:5 | when ... | WhenExpr | Test.kt:101:9:103:5 | ... -> ... | WhenBranch |
@@ -154,7 +164,7 @@
| Test.kt:101:22:101:30 | ... (value equals) ... | ValueEQExpr | Test.kt:105:5:109:5 | ; | ExprStmt |
| Test.kt:101:27:101:30 | null | NullLiteral | Test.kt:101:22:101:30 | ... (value equals) ... | ValueEQExpr |
| Test.kt:101:33:103:5 | { ... } | BlockStmt | Test.kt:102:15:102:25 | new Exception(...) | ClassInstanceExpr |
-| Test.kt:102:9:102:25 | throw ... | ThrowStmt | Test.kt:100:1:110:1 | Exit | Method |
+| Test.kt:102:9:102:25 | throw ... | ThrowStmt | Test.kt:100:1:110:1 | Exceptional Exit | Method |
| Test.kt:102:15:102:25 | new Exception(...) | ClassInstanceExpr | Test.kt:102:9:102:25 | throw ... | ThrowStmt |
| Test.kt:105:5:109:5 | ; | ExprStmt | Test.kt:105:5:109:5 | when ... | WhenExpr |
| Test.kt:105:5:109:5 | when ... | WhenExpr | Test.kt:105:9:107:5 | ... -> ... | WhenBranch |
@@ -165,29 +175,33 @@
| Test.kt:105:14:105:17 | null | NullLiteral | Test.kt:105:9:105:17 | ... (value not-equals) ... | ValueNEExpr |
| Test.kt:105:20:107:5 | { ... } | BlockStmt | Test.kt:106:9:106:29 | ; | ExprStmt |
| Test.kt:106:9:106:29 | ; | ExprStmt | Test.kt:106:17:106:28 | "x not null" | StringLiteral |
-| Test.kt:106:9:106:29 | println(...) | MethodCall | Test.kt:100:1:110:1 | Exit | Method |
+| Test.kt:106:9:106:29 | println(...) | MethodCall | Test.kt:100:1:110:1 | Normal Exit | Method |
| Test.kt:106:17:106:28 | "x not null" | StringLiteral | Test.kt:106:9:106:29 | println(...) | MethodCall |
| Test.kt:107:16:107:16 | y | VarAccess | Test.kt:107:21:107:24 | null | NullLiteral |
-| Test.kt:107:16:107:24 | ... (value not-equals) ... | ValueNEExpr | Test.kt:100:1:110:1 | Exit | Method |
+| Test.kt:107:16:107:24 | ... (value not-equals) ... | ValueNEExpr | Test.kt:100:1:110:1 | Normal Exit | Method |
| Test.kt:107:16:107:24 | ... (value not-equals) ... | ValueNEExpr | Test.kt:107:27:109:5 | { ... } | BlockStmt |
| Test.kt:107:16:109:5 | ... -> ... | WhenBranch | Test.kt:107:16:107:16 | y | VarAccess |
| Test.kt:107:21:107:24 | null | NullLiteral | Test.kt:107:16:107:24 | ... (value not-equals) ... | ValueNEExpr |
| Test.kt:107:27:109:5 | { ... } | BlockStmt | Test.kt:108:9:108:29 | ; | ExprStmt |
| Test.kt:108:9:108:29 | ; | ExprStmt | Test.kt:108:17:108:28 | "y not null" | StringLiteral |
-| Test.kt:108:9:108:29 | println(...) | MethodCall | Test.kt:100:1:110:1 | Exit | Method |
+| Test.kt:108:9:108:29 | println(...) | MethodCall | Test.kt:100:1:110:1 | Normal Exit | Method |
| Test.kt:108:17:108:28 | "y not null" | StringLiteral | Test.kt:108:9:108:29 | println(...) | MethodCall |
+| Test.kt:112:1:116:1 | Exceptional Exit | Method | Test.kt:112:1:116:1 | Exit | Method |
| Test.kt:112:1:116:1 | Exit | Method | file://:0:0:0:0 | | |
+| Test.kt:112:1:116:1 | Normal Exit | Method | Test.kt:112:1:116:1 | Exit | Method |
| Test.kt:112:32:116:1 | { ... } | BlockStmt | Test.kt:113:5:115:5 | ; | ExprStmt |
| Test.kt:113:5:115:5 | ; | ExprStmt | Test.kt:113:5:115:5 | when ... | WhenExpr |
| Test.kt:113:5:115:5 | when ... | WhenExpr | Test.kt:113:9:115:5 | ... -> ... | WhenBranch |
-| Test.kt:113:9:113:9 | x | VarAccess | Test.kt:112:1:116:1 | Exit | Method |
+| Test.kt:113:9:113:9 | x | VarAccess | Test.kt:112:1:116:1 | Normal Exit | Method |
| Test.kt:113:9:113:9 | x | VarAccess | Test.kt:113:14:113:14 | y | VarAccess |
| Test.kt:113:9:113:14 | ... && ... | AndLogicalExpr | Test.kt:113:9:113:9 | x | VarAccess |
| Test.kt:113:9:115:5 | ... -> ... | WhenBranch | Test.kt:113:9:113:14 | ... && ... | AndLogicalExpr |
-| Test.kt:113:14:113:14 | y | VarAccess | Test.kt:112:1:116:1 | Exit | Method |
+| Test.kt:113:14:113:14 | y | VarAccess | Test.kt:112:1:116:1 | Normal Exit | Method |
| Test.kt:113:14:113:14 | y | VarAccess | Test.kt:113:17:115:5 | { ... } | BlockStmt |
-| Test.kt:113:17:115:5 | { ... } | BlockStmt | Test.kt:112:1:116:1 | Exit | Method |
+| Test.kt:113:17:115:5 | { ... } | BlockStmt | Test.kt:112:1:116:1 | Normal Exit | Method |
+| Test.kt:118:1:124:1 | Exceptional Exit | Method | Test.kt:118:1:124:1 | Exit | Method |
| Test.kt:118:1:124:1 | Exit | Method | file://:0:0:0:0 | | |
+| Test.kt:118:1:124:1 | Normal Exit | Method | Test.kt:118:1:124:1 | Exit | Method |
| Test.kt:118:37:124:1 | { ... } | BlockStmt | Test.kt:119:2:123:12 | ; | ExprStmt |
| Test.kt:119:2:123:12 | ; | ExprStmt | Test.kt:119:2:123:12 | when ... | WhenExpr |
| Test.kt:119:2:123:12 | when ... | WhenExpr | Test.kt:120:3:123:10 | ... -> ... | WhenBranch |
@@ -197,11 +211,11 @@
| Test.kt:121:4:121:4 | x | VarAccess | Test.kt:122:12:122:16 | ... -> ... | WhenBranch |
| Test.kt:121:4:121:9 | ... -> ... | WhenBranch | Test.kt:121:4:121:4 | x | VarAccess |
| Test.kt:121:9:121:9 | ; | ExprStmt | Test.kt:121:9:121:9 | y | VarAccess |
-| Test.kt:121:9:121:9 | y | VarAccess | Test.kt:118:1:124:1 | Exit | Method |
+| Test.kt:121:9:121:9 | y | VarAccess | Test.kt:118:1:124:1 | Normal Exit | Method |
| Test.kt:121:9:121:9 | y | VarAccess | Test.kt:123:8:123:10 | { ... } | BlockStmt |
| Test.kt:122:12:122:16 | ... -> ... | WhenBranch | Test.kt:122:12:122:16 | true | BooleanLiteral |
| Test.kt:122:12:122:16 | ; | ExprStmt | Test.kt:122:12:122:16 | false | BooleanLiteral |
-| Test.kt:122:12:122:16 | false | BooleanLiteral | Test.kt:118:1:124:1 | Exit | Method |
+| Test.kt:122:12:122:16 | false | BooleanLiteral | Test.kt:118:1:124:1 | Normal Exit | Method |
| Test.kt:122:12:122:16 | true | BooleanLiteral | Test.kt:122:12:122:16 | ; | ExprStmt |
-| Test.kt:123:8:123:10 | { ... } | BlockStmt | Test.kt:118:1:124:1 | Exit | Method |
+| Test.kt:123:8:123:10 | { ... } | BlockStmt | Test.kt:118:1:124:1 | Normal Exit | Method |
missingSuccessor
diff --git a/java/ql/test-kotlin2/library-tests/controlflow/dominance/dominator.expected b/java/ql/test-kotlin2/library-tests/controlflow/dominance/dominator.expected
index d5ddea7a98b..75662bfacd4 100644
--- a/java/ql/test-kotlin2/library-tests/controlflow/dominance/dominator.expected
+++ b/java/ql/test-kotlin2/library-tests/controlflow/dominance/dominator.expected
@@ -41,7 +41,7 @@
| Test.kt:21:3:24:11 | ; | Test.kt:21:3:24:11 | when ... |
| Test.kt:21:3:24:11 | when ... | Test.kt:21:7:22:9 | ... -> ... |
| Test.kt:21:7:21:7 | x | Test.kt:21:11:21:11 | 0 |
-| Test.kt:21:7:21:11 | ... < ... | Test.kt:2:2:79:2 | Exit |
+| Test.kt:21:7:21:11 | ... < ... | Test.kt:2:2:79:2 | Normal Exit |
| Test.kt:21:7:21:11 | ... < ... | Test.kt:22:4:22:9 | ; |
| Test.kt:21:7:21:11 | ... < ... | Test.kt:24:4:24:11 | ... -> ... |
| Test.kt:21:7:22:9 | ... -> ... | Test.kt:21:7:21:7 | x |
@@ -141,7 +141,7 @@
| Test.kt:92:4:93:9 | ; | Test.kt:92:4:93:9 | when ... |
| Test.kt:92:4:93:9 | when ... | Test.kt:92:8:93:9 | ... -> ... |
| Test.kt:92:8:92:8 | a | Test.kt:92:13:92:14 | 10 |
-| Test.kt:92:8:92:14 | ... (value equals) ... | Test.kt:81:2:98:2 | Exit |
+| Test.kt:92:8:92:14 | ... (value equals) ... | Test.kt:81:2:98:2 | Normal Exit |
| Test.kt:92:8:92:14 | ... (value equals) ... | Test.kt:93:5:93:9 | break |
| Test.kt:92:8:92:14 | ... (value equals) ... | Test.kt:94:4:95:12 | ; |
| Test.kt:92:8:93:9 | ... -> ... | Test.kt:92:8:92:8 | a |
diff --git a/java/ql/test/library-tests/controlflow/basic/bbStmts.expected b/java/ql/test/library-tests/controlflow/basic/bbStmts.expected
index 0fbf3623f08..df336ce90a2 100644
--- a/java/ql/test/library-tests/controlflow/basic/bbStmts.expected
+++ b/java/ql/test/library-tests/controlflow/basic/bbStmts.expected
@@ -1,7 +1,11 @@
+| Test.java:3:14:3:17 | Exceptional Exit | 0 | Test.java:3:14:3:17 | Exceptional Exit |
+| Test.java:3:14:3:17 | Exit | 0 | Test.java:3:14:3:17 | Exit |
| Test.java:3:14:3:17 | { ... } | 0 | Test.java:3:14:3:17 | { ... } |
| Test.java:3:14:3:17 | { ... } | 1 | Test.java:3:14:3:17 | super(...) |
-| Test.java:3:14:3:17 | { ... } | 2 | Test.java:3:14:3:17 | Exit |
+| Test.java:3:14:3:17 | { ... } | 2 | Test.java:3:14:3:17 | Normal Exit |
+| Test.java:4:14:4:17 | Exceptional Exit | 0 | Test.java:4:14:4:17 | Exceptional Exit |
| Test.java:4:14:4:17 | Exit | 0 | Test.java:4:14:4:17 | Exit |
+| Test.java:4:14:4:17 | Normal Exit | 0 | Test.java:4:14:4:17 | Normal Exit |
| Test.java:4:21:76:2 | { ... } | 0 | Test.java:4:21:76:2 | { ... } |
| Test.java:4:21:76:2 | { ... } | 1 | Test.java:5:3:5:12 | var ...; |
| Test.java:4:21:76:2 | { ... } | 2 | Test.java:5:11:5:11 | 0 |
diff --git a/java/ql/test/library-tests/controlflow/basic/bbStrictDominance.expected b/java/ql/test/library-tests/controlflow/basic/bbStrictDominance.expected
index 8440209d0a4..be658fb2915 100644
--- a/java/ql/test/library-tests/controlflow/basic/bbStrictDominance.expected
+++ b/java/ql/test/library-tests/controlflow/basic/bbStrictDominance.expected
@@ -1,4 +1,7 @@
+| Test.java:3:14:3:17 | { ... } | Test.java:3:14:3:17 | Exit |
+| Test.java:4:14:4:17 | Normal Exit | Test.java:4:14:4:17 | Exit |
| Test.java:4:21:76:2 | { ... } | Test.java:4:14:4:17 | Exit |
+| Test.java:4:21:76:2 | { ... } | Test.java:4:14:4:17 | Normal Exit |
| Test.java:4:21:76:2 | { ... } | Test.java:11:14:14:3 | { ... } |
| Test.java:4:21:76:2 | { ... } | Test.java:14:10:16:3 | { ... } |
| Test.java:4:21:76:2 | { ... } | Test.java:18:3:18:8 | ; |
@@ -21,6 +24,7 @@
| Test.java:4:21:76:2 | { ... } | Test.java:63:9:66:4 | { ... } |
| Test.java:4:21:76:2 | { ... } | Test.java:70:3:70:9 | ; |
| Test.java:18:3:18:8 | ; | Test.java:4:14:4:17 | Exit |
+| Test.java:18:3:18:8 | ; | Test.java:4:14:4:17 | Normal Exit |
| Test.java:18:3:18:8 | ; | Test.java:22:4:22:10 | ; |
| Test.java:18:3:18:8 | ; | Test.java:24:4:24:10 | return ... |
| Test.java:18:3:18:8 | ; | Test.java:30:15:33:3 | { ... } |
diff --git a/java/ql/test/library-tests/controlflow/basic/bbSuccessor.expected b/java/ql/test/library-tests/controlflow/basic/bbSuccessor.expected
index 0886f784fd9..a6e5d8430c1 100644
--- a/java/ql/test/library-tests/controlflow/basic/bbSuccessor.expected
+++ b/java/ql/test/library-tests/controlflow/basic/bbSuccessor.expected
@@ -1,3 +1,7 @@
+| Test.java:3:14:3:17 | Exceptional Exit | Test.java:3:14:3:17 | Exit |
+| Test.java:3:14:3:17 | { ... } | Test.java:3:14:3:17 | Exit |
+| Test.java:4:14:4:17 | Exceptional Exit | Test.java:4:14:4:17 | Exit |
+| Test.java:4:14:4:17 | Normal Exit | Test.java:4:14:4:17 | Exit |
| Test.java:4:21:76:2 | { ... } | Test.java:11:14:14:3 | { ... } |
| Test.java:4:21:76:2 | { ... } | Test.java:14:10:16:3 | { ... } |
| Test.java:11:14:14:3 | { ... } | Test.java:18:3:18:8 | ; |
@@ -6,7 +10,7 @@
| Test.java:18:3:18:8 | ; | Test.java:24:4:24:10 | return ... |
| Test.java:22:4:22:10 | ; | Test.java:30:15:33:3 | { ... } |
| Test.java:22:4:22:10 | ; | Test.java:35:3:35:9 | ; |
-| Test.java:24:4:24:10 | return ... | Test.java:4:14:4:17 | Exit |
+| Test.java:24:4:24:10 | return ... | Test.java:4:14:4:17 | Normal Exit |
| Test.java:30:15:33:3 | { ... } | Test.java:35:3:35:9 | ; |
| Test.java:35:3:35:9 | ; | Test.java:38:9:38:9 | x |
| Test.java:38:9:38:9 | x | Test.java:38:16:41:3 | { ... } |
@@ -27,4 +31,4 @@
| Test.java:57:15:60:5 | { ... } | Test.java:70:3:70:9 | ; |
| Test.java:60:12:62:5 | { ... } | Test.java:54:26:54:26 | j |
| Test.java:63:9:66:4 | { ... } | Test.java:54:26:54:26 | j |
-| Test.java:70:3:70:9 | ; | Test.java:4:14:4:17 | Exit |
+| Test.java:70:3:70:9 | ; | Test.java:4:14:4:17 | Normal Exit |
diff --git a/java/ql/test/library-tests/controlflow/dominance/dominator.expected b/java/ql/test/library-tests/controlflow/dominance/dominator.expected
index de43e6721e6..1e385c4fd62 100644
--- a/java/ql/test/library-tests/controlflow/dominance/dominator.expected
+++ b/java/ql/test/library-tests/controlflow/dominance/dominator.expected
@@ -27,7 +27,7 @@
| Test.java:14:18:14:18 | y | Test.java:14:14:14:18 | ... + ... |
| Test.java:17:3:17:12 | if (...) | Test.java:17:7:17:7 | x |
| Test.java:17:7:17:7 | x | Test.java:17:11:17:11 | 0 |
-| Test.java:17:7:17:11 | ... < ... | Test.java:2:6:2:9 | Exit |
+| Test.java:17:7:17:11 | ... < ... | Test.java:2:6:2:9 | Normal Exit |
| Test.java:17:7:17:11 | ... < ... | Test.java:18:4:18:10 | ; |
| Test.java:17:7:17:11 | ... < ... | Test.java:20:11:20:11 | z |
| Test.java:17:11:17:11 | 0 | Test.java:17:7:17:11 | ... < ... |
@@ -163,7 +163,7 @@
| Test.java:83:9:83:9 | c | Test.java:83:5:83:9 | ...=... |
| Test.java:85:4:85:15 | if (...) | Test.java:85:8:85:8 | a |
| Test.java:85:8:85:8 | a | Test.java:85:13:85:14 | 10 |
-| Test.java:85:8:85:14 | ... == ... | Test.java:74:6:74:10 | Exit |
+| Test.java:85:8:85:14 | ... == ... | Test.java:74:6:74:10 | Normal Exit |
| Test.java:85:8:85:14 | ... == ... | Test.java:86:5:86:10 | break |
| Test.java:85:8:85:14 | ... == ... | Test.java:87:4:87:15 | if (...) |
| Test.java:85:13:85:14 | 10 | Test.java:85:8:85:14 | ... == ... |
diff --git a/java/ql/test/library-tests/guards/guards.expected b/java/ql/test/library-tests/guards/guards.expected
index 2c5bff6233a..ffe67bc3a32 100644
--- a/java/ql/test/library-tests/guards/guards.expected
+++ b/java/ql/test/library-tests/guards/guards.expected
@@ -1,3 +1,4 @@
+| Test.java:5:7:5:11 | ... < ... | false | Test.java:3:7:3:10 | Normal Exit |
| Test.java:5:7:5:11 | ... < ... | false | Test.java:8:3:8:12 | var ...; |
| Test.java:5:7:5:11 | ... < ... | false | Test.java:9:9:9:9 | x |
| Test.java:5:7:5:11 | ... < ... | false | Test.java:9:17:22:3 | { ... } |
@@ -10,6 +11,7 @@
| Test.java:5:7:5:11 | ... < ... | false | Test.java:18:24:20:4 | { ... } |
| Test.java:5:7:5:11 | ... < ... | false | Test.java:21:4:21:7 | ; |
| Test.java:5:7:5:11 | ... < ... | true | Test.java:5:14:7:3 | { ... } |
+| Test.java:9:9:9:14 | ... >= ... | false | Test.java:3:7:3:10 | Normal Exit |
| Test.java:9:9:9:14 | ... >= ... | true | Test.java:9:17:22:3 | { ... } |
| Test.java:9:9:9:14 | ... >= ... | true | Test.java:11:5:11:8 | ; |
| Test.java:9:9:9:14 | ... >= ... | true | Test.java:12:4:12:14 | if (...) |
diff --git a/java/ql/test/library-tests/guards/guardslogic.expected b/java/ql/test/library-tests/guards/guardslogic.expected
index 29c11ccd153..6bf536d3ce1 100644
--- a/java/ql/test/library-tests/guards/guardslogic.expected
+++ b/java/ql/test/library-tests/guards/guardslogic.expected
@@ -46,6 +46,11 @@
| Logic.java:36:16:36:21 | g(...) | false | Logic.java:40:5:40:18 | var ...; |
| Logic.java:37:9:37:14 | ... > ... | true | Logic.java:37:17:39:5 | { ... } |
| Logic.java:44:10:44:10 | b | false | Logic.java:44:33:44:35 | msg |
+| Logic.java:44:10:44:10 | b | true | Logic.java:43:23:43:31 | Normal Exit |
+| Logic.java:48:5:48:22 | checkTrue(...) | exception | Logic.java:47:23:47:32 | Exceptional Exit |
+| Logic.java:48:5:48:22 | checkTrue(...) | no exception | Logic.java:47:23:47:32 | Normal Exit |
+| Logic.java:48:15:48:16 | !... | true | Logic.java:47:23:47:32 | Normal Exit |
+| Logic.java:48:16:48:16 | b | false | Logic.java:47:23:47:32 | Normal Exit |
| Logic.java:52:5:52:29 | checkTrue(...) | no exception | Logic.java:53:5:53:28 | ; |
| Logic.java:52:5:52:29 | checkTrue(...) | no exception | Logic.java:54:5:54:15 | if (...) |
| Logic.java:52:5:52:29 | checkTrue(...) | no exception | Logic.java:54:17:56:5 | { ... } |
@@ -62,3 +67,8 @@
| Logic.java:53:21:53:26 | g(...) | false | Logic.java:57:5:57:18 | var ...; |
| Logic.java:54:9:54:14 | ... > ... | true | Logic.java:54:17:56:5 | { ... } |
| Logic.java:61:10:61:10 | b | false | Logic.java:61:33:61:35 | msg |
+| Logic.java:61:10:61:10 | b | true | Logic.java:60:23:60:31 | Normal Exit |
+| Logic.java:65:5:65:22 | checkTrue(...) | exception | Logic.java:64:23:64:32 | Exceptional Exit |
+| Logic.java:65:5:65:22 | checkTrue(...) | no exception | Logic.java:64:23:64:32 | Normal Exit |
+| Logic.java:65:15:65:16 | !... | true | Logic.java:64:23:64:32 | Normal Exit |
+| Logic.java:65:16:65:16 | b | false | Logic.java:64:23:64:32 | Normal Exit |
diff --git a/java/ql/test/library-tests/guards/guardspreconditions.expected b/java/ql/test/library-tests/guards/guardspreconditions.expected
index 41080a5dab6..2d4597f0282 100644
--- a/java/ql/test/library-tests/guards/guardspreconditions.expected
+++ b/java/ql/test/library-tests/guards/guardspreconditions.expected
@@ -1,20 +1,44 @@
+| Preconditions.java:8:9:8:31 | assertTrue(...) | exception | Preconditions.java:7:10:7:14 | Exceptional Exit |
| Preconditions.java:8:9:8:31 | assertTrue(...) | no exception | Preconditions.java:9:9:9:18 | ; |
+| Preconditions.java:13:9:13:32 | assertTrue(...) | exception | Preconditions.java:12:10:12:14 | Exceptional Exit |
| Preconditions.java:13:9:13:32 | assertTrue(...) | no exception | Preconditions.java:14:9:14:18 | ; |
+| Preconditions.java:18:9:18:33 | assertFalse(...) | exception | Preconditions.java:17:10:17:14 | Exceptional Exit |
| Preconditions.java:18:9:18:33 | assertFalse(...) | no exception | Preconditions.java:19:9:19:18 | ; |
+| Preconditions.java:23:9:23:32 | assertFalse(...) | exception | Preconditions.java:22:10:22:14 | Exceptional Exit |
| Preconditions.java:23:9:23:32 | assertFalse(...) | no exception | Preconditions.java:24:9:24:18 | ; |
+| Preconditions.java:28:9:28:41 | assertTrue(...) | exception | Preconditions.java:27:10:27:14 | Exceptional Exit |
| Preconditions.java:28:9:28:41 | assertTrue(...) | no exception | Preconditions.java:29:9:29:18 | ; |
+| Preconditions.java:33:9:33:42 | assertTrue(...) | exception | Preconditions.java:32:10:32:14 | Exceptional Exit |
| Preconditions.java:33:9:33:42 | assertTrue(...) | no exception | Preconditions.java:34:9:34:18 | ; |
+| Preconditions.java:38:9:38:43 | assertFalse(...) | exception | Preconditions.java:37:10:37:14 | Exceptional Exit |
| Preconditions.java:38:9:38:43 | assertFalse(...) | no exception | Preconditions.java:39:9:39:18 | ; |
+| Preconditions.java:43:9:43:42 | assertFalse(...) | exception | Preconditions.java:42:10:42:14 | Exceptional Exit |
| Preconditions.java:43:9:43:42 | assertFalse(...) | no exception | Preconditions.java:44:9:44:18 | ; |
+| Preconditions.java:48:9:48:35 | assertTrue(...) | exception | Preconditions.java:47:10:47:14 | Exceptional Exit |
| Preconditions.java:48:9:48:35 | assertTrue(...) | no exception | Preconditions.java:49:9:49:18 | ; |
+| Preconditions.java:53:9:53:36 | assertTrue(...) | exception | Preconditions.java:52:10:52:15 | Exceptional Exit |
| Preconditions.java:53:9:53:36 | assertTrue(...) | no exception | Preconditions.java:54:9:54:18 | ; |
+| Preconditions.java:58:9:58:37 | assertFalse(...) | exception | Preconditions.java:57:10:57:15 | Exceptional Exit |
| Preconditions.java:58:9:58:37 | assertFalse(...) | no exception | Preconditions.java:59:9:59:18 | ; |
+| Preconditions.java:63:9:63:36 | assertFalse(...) | exception | Preconditions.java:62:10:62:15 | Exceptional Exit |
| Preconditions.java:63:9:63:36 | assertFalse(...) | no exception | Preconditions.java:64:9:64:18 | ; |
+| Preconditions.java:68:9:68:45 | assertTrue(...) | exception | Preconditions.java:67:10:67:15 | Exceptional Exit |
| Preconditions.java:68:9:68:45 | assertTrue(...) | no exception | Preconditions.java:69:9:69:18 | ; |
+| Preconditions.java:73:9:73:46 | assertTrue(...) | exception | Preconditions.java:72:10:72:15 | Exceptional Exit |
| Preconditions.java:73:9:73:46 | assertTrue(...) | no exception | Preconditions.java:74:9:74:18 | ; |
+| Preconditions.java:78:9:78:47 | assertFalse(...) | exception | Preconditions.java:77:10:77:15 | Exceptional Exit |
| Preconditions.java:78:9:78:47 | assertFalse(...) | no exception | Preconditions.java:79:9:79:18 | ; |
+| Preconditions.java:83:9:83:46 | assertFalse(...) | exception | Preconditions.java:82:10:82:15 | Exceptional Exit |
| Preconditions.java:83:9:83:46 | assertFalse(...) | no exception | Preconditions.java:84:9:84:18 | ; |
+| Preconditions.java:88:9:88:15 | t(...) | exception | Preconditions.java:87:10:87:15 | Exceptional Exit |
| Preconditions.java:88:9:88:15 | t(...) | no exception | Preconditions.java:89:9:89:18 | ; |
+| Preconditions.java:93:9:93:16 | t(...) | exception | Preconditions.java:92:10:92:15 | Exceptional Exit |
| Preconditions.java:93:9:93:16 | t(...) | no exception | Preconditions.java:94:9:94:18 | ; |
+| Preconditions.java:98:9:98:16 | f(...) | exception | Preconditions.java:97:10:97:15 | Exceptional Exit |
| Preconditions.java:98:9:98:16 | f(...) | no exception | Preconditions.java:99:9:99:18 | ; |
+| Preconditions.java:103:9:103:15 | f(...) | exception | Preconditions.java:102:10:102:15 | Exceptional Exit |
| Preconditions.java:103:9:103:15 | f(...) | no exception | Preconditions.java:104:9:104:18 | ; |
+| Preconditions.java:108:9:108:46 | assertTrue(...) | exception | Preconditions.java:107:17:107:17 | Exceptional Exit |
+| Preconditions.java:108:9:108:46 | assertTrue(...) | no exception | Preconditions.java:107:17:107:17 | Normal Exit |
+| Preconditions.java:112:9:112:47 | assertFalse(...) | exception | Preconditions.java:111:17:111:17 | Exceptional Exit |
+| Preconditions.java:112:9:112:47 | assertFalse(...) | no exception | Preconditions.java:111:17:111:17 | Normal Exit |
diff --git a/java/ql/test/library-tests/java7/MultiCatch/MultiCatchControlFlow.expected b/java/ql/test/library-tests/java7/MultiCatch/MultiCatchControlFlow.expected
index a849ab5392d..d389eb658f5 100644
--- a/java/ql/test/library-tests/java7/MultiCatch/MultiCatchControlFlow.expected
+++ b/java/ql/test/library-tests/java7/MultiCatch/MultiCatchControlFlow.expected
@@ -1,4 +1,4 @@
-| MultiCatch.java:6:14:6:23 | super(...) | MultiCatch.java:6:14:6:23 | Exit |
+| MultiCatch.java:6:14:6:23 | super(...) | MultiCatch.java:6:14:6:23 | Normal Exit |
| MultiCatch.java:6:14:6:23 | { ... } | MultiCatch.java:6:14:6:23 | super(...) |
| MultiCatch.java:8:2:20:2 | { ... } | MultiCatch.java:9:3:19:3 | try ... |
| MultiCatch.java:9:3:19:3 | try ... | MultiCatch.java:10:3:15:3 | { ... } |
@@ -16,7 +16,7 @@
| MultiCatch.java:17:4:17:4 | e | MultiCatch.java:17:4:17:22 | printStackTrace(...) |
| MultiCatch.java:17:4:17:22 | printStackTrace(...) | MultiCatch.java:18:10:18:10 | e |
| MultiCatch.java:17:4:17:23 | ; | MultiCatch.java:17:4:17:4 | e |
-| MultiCatch.java:18:4:18:11 | throw ... | MultiCatch.java:7:14:7:23 | Exit |
+| MultiCatch.java:18:4:18:11 | throw ... | MultiCatch.java:7:14:7:23 | Exceptional Exit |
| MultiCatch.java:18:10:18:10 | e | MultiCatch.java:18:4:18:11 | throw ... |
| MultiCatch.java:23:2:33:2 | { ... } | MultiCatch.java:24:3:32:4 | try ... |
| MultiCatch.java:24:3:32:4 | try ... | MultiCatch.java:25:3:31:3 | { ... } |
@@ -31,12 +31,12 @@
| MultiCatch.java:28:12:28:12 | c | MultiCatch.java:30:10:30:24 | new Exception(...) |
| MultiCatch.java:29:5:29:29 | throw ... | MultiCatch.java:31:5:31:37 | catch (...) |
| MultiCatch.java:29:11:29:28 | new SQLException(...) | MultiCatch.java:29:5:29:29 | throw ... |
-| MultiCatch.java:30:4:30:25 | throw ... | MultiCatch.java:22:14:22:24 | Exit |
+| MultiCatch.java:30:4:30:25 | throw ... | MultiCatch.java:22:14:22:24 | Exceptional Exit |
| MultiCatch.java:30:4:30:25 | throw ... | MultiCatch.java:31:5:31:37 | catch (...) |
| MultiCatch.java:30:10:30:24 | new Exception(...) | MultiCatch.java:30:4:30:25 | throw ... |
| MultiCatch.java:31:5:31:37 | catch (...) | MultiCatch.java:31:36:31:36 | e |
| MultiCatch.java:31:36:31:36 | e | MultiCatch.java:32:3:32:4 | { ... } |
-| MultiCatch.java:32:3:32:4 | { ... } | MultiCatch.java:22:14:22:24 | Exit |
+| MultiCatch.java:32:3:32:4 | { ... } | MultiCatch.java:22:14:22:24 | Normal Exit |
| MultiCatch.java:36:2:42:2 | { ... } | MultiCatch.java:37:3:41:4 | try ... |
| MultiCatch.java:37:3:41:4 | try ... | MultiCatch.java:38:3:40:3 | { ... } |
| MultiCatch.java:38:3:40:3 | { ... } | MultiCatch.java:39:10:39:26 | new IOException(...) |
@@ -45,4 +45,4 @@
| MultiCatch.java:39:10:39:26 | new IOException(...) | MultiCatch.java:40:5:40:22 | catch (...) |
| MultiCatch.java:40:5:40:22 | catch (...) | MultiCatch.java:40:21:40:21 | e |
| MultiCatch.java:40:21:40:21 | e | MultiCatch.java:41:3:41:4 | { ... } |
-| MultiCatch.java:41:3:41:4 | { ... } | MultiCatch.java:35:14:35:26 | Exit |
+| MultiCatch.java:41:3:41:4 | { ... } | MultiCatch.java:35:14:35:26 | Normal Exit |
diff --git a/java/ql/test/library-tests/pattern-instanceof/cfg.expected b/java/ql/test/library-tests/pattern-instanceof/cfg.expected
index b6caebd532a..5ef73c8ac78 100644
--- a/java/ql/test/library-tests/pattern-instanceof/cfg.expected
+++ b/java/ql/test/library-tests/pattern-instanceof/cfg.expected
@@ -1,5 +1,9 @@
-| Test.java:1:14:1:17 | super(...) | Test.java:1:14:1:17 | Exit |
+| Test.java:1:14:1:17 | Exceptional Exit | Test.java:1:14:1:17 | Exit |
+| Test.java:1:14:1:17 | Normal Exit | Test.java:1:14:1:17 | Exit |
+| Test.java:1:14:1:17 | super(...) | Test.java:1:14:1:17 | Normal Exit |
| Test.java:1:14:1:17 | { ... } | Test.java:1:14:1:17 | super(...) |
+| Test.java:3:22:3:25 | Exceptional Exit | Test.java:3:22:3:25 | Exit |
+| Test.java:3:22:3:25 | Normal Exit | Test.java:3:22:3:25 | Exit |
| Test.java:3:40:20:3 | { ... } | Test.java:5:5:5:34 | var ...; |
| Test.java:5:5:5:34 | var ...; | Test.java:5:26:5:33 | source(...) |
| Test.java:5:12:5:33 | directTaint | Test.java:6:5:6:36 | var ...; |
@@ -29,7 +33,7 @@
| Test.java:11:12:11:12 | s | Test.java:11:7:11:13 | sink(...) |
| Test.java:14:5:14:92 | if (...) | Test.java:14:9:14:9 | o |
| Test.java:14:9:14:9 | o | Test.java:14:9:14:91 | ...instanceof... |
-| Test.java:14:9:14:91 | ...instanceof... | Test.java:3:22:3:25 | Exit |
+| Test.java:14:9:14:91 | ...instanceof... | Test.java:3:22:3:25 | Normal Exit |
| Test.java:14:9:14:91 | ...instanceof... | Test.java:14:41:14:47 | tainted |
| Test.java:14:22:14:91 | Outer(...) | Test.java:14:94:18:5 | { ... } |
| Test.java:14:28:14:67 | Inner(...) | Test.java:14:77:14:90 | alsoNotTainted |
@@ -43,17 +47,23 @@
| Test.java:16:7:16:22 | sink(...) | Test.java:17:7:17:27 | ; |
| Test.java:16:7:16:23 | ; | Test.java:16:12:16:21 | notTainted |
| Test.java:16:12:16:21 | notTainted | Test.java:16:7:16:22 | sink(...) |
-| Test.java:17:7:17:26 | sink(...) | Test.java:3:22:3:25 | Exit |
+| Test.java:17:7:17:26 | sink(...) | Test.java:3:22:3:25 | Normal Exit |
| Test.java:17:7:17:27 | ; | Test.java:17:12:17:25 | alsoNotTainted |
| Test.java:17:12:17:25 | alsoNotTainted | Test.java:17:7:17:26 | sink(...) |
+| Test.java:22:24:22:29 | Exceptional Exit | Test.java:22:24:22:29 | Exit |
+| Test.java:22:24:22:29 | Normal Exit | Test.java:22:24:22:29 | Exit |
| Test.java:22:33:22:53 | { ... } | Test.java:22:42:22:50 | "tainted" |
-| Test.java:22:35:22:51 | return ... | Test.java:22:24:22:29 | Exit |
+| Test.java:22:35:22:51 | return ... | Test.java:22:24:22:29 | Normal Exit |
| Test.java:22:42:22:50 | "tainted" | Test.java:22:35:22:51 | return ... |
-| Test.java:23:40:23:42 | { ... } | Test.java:23:22:23:25 | Exit |
+| Test.java:23:22:23:25 | Exceptional Exit | Test.java:23:22:23:25 | Exit |
+| Test.java:23:22:23:25 | Normal Exit | Test.java:23:22:23:25 | Exit |
+| Test.java:23:40:23:42 | { ... } | Test.java:23:22:23:25 | Normal Exit |
| Test.java:27:8:27:12 | ...=... | Test.java:27:8:27:12 | ; |
-| Test.java:27:8:27:12 | ...=... | Test.java:27:8:27:12 | Exit |
+| Test.java:27:8:27:12 | ...=... | Test.java:27:8:27:12 | Normal Exit |
| Test.java:27:8:27:12 | ; | Test.java:27:8:27:12 | this |
| Test.java:27:8:27:12 | ; | Test.java:27:8:27:12 | this |
+| Test.java:27:8:27:12 | Exceptional Exit | Test.java:27:8:27:12 | Exit |
+| Test.java:27:8:27:12 | Normal Exit | Test.java:27:8:27:12 | Exit |
| Test.java:27:8:27:12 | i | Test.java:27:8:27:12 | ...=... |
| Test.java:27:8:27:12 | otherField | Test.java:27:8:27:12 | ...=... |
| Test.java:27:8:27:12 | super(...) | Test.java:27:8:27:12 | ; |
@@ -61,9 +71,11 @@
| Test.java:27:8:27:12 | this | Test.java:27:8:27:12 | otherField |
| Test.java:27:8:27:12 | { ... } | Test.java:27:8:27:12 | super(...) |
| Test.java:28:8:28:12 | ...=... | Test.java:28:8:28:12 | ; |
-| Test.java:28:8:28:12 | ...=... | Test.java:28:8:28:12 | Exit |
+| Test.java:28:8:28:12 | ...=... | Test.java:28:8:28:12 | Normal Exit |
| Test.java:28:8:28:12 | ; | Test.java:28:8:28:12 | this |
| Test.java:28:8:28:12 | ; | Test.java:28:8:28:12 | this |
+| Test.java:28:8:28:12 | Exceptional Exit | Test.java:28:8:28:12 | Exit |
+| Test.java:28:8:28:12 | Normal Exit | Test.java:28:8:28:12 | Exit |
| Test.java:28:8:28:12 | nonTaintedField | Test.java:28:8:28:12 | ...=... |
| Test.java:28:8:28:12 | super(...) | Test.java:28:8:28:12 | ; |
| Test.java:28:8:28:12 | taintedField | Test.java:28:8:28:12 | ...=... |
diff --git a/java/ql/test/library-tests/pattern-switch/cfg/test.expected b/java/ql/test/library-tests/pattern-switch/cfg/test.expected
index c29059faf33..f9058bd8f4c 100644
--- a/java/ql/test/library-tests/pattern-switch/cfg/test.expected
+++ b/java/ql/test/library-tests/pattern-switch/cfg/test.expected
@@ -1,6 +1,12 @@
-| Exhaustive.java:1:14:1:23 | super(...) | Exhaustive.java:1:14:1:23 | Exit |
+| Exhaustive.java:1:14:1:23 | Exceptional Exit | Exhaustive.java:1:14:1:23 | Exit |
+| Exhaustive.java:1:14:1:23 | Normal Exit | Exhaustive.java:1:14:1:23 | Exit |
+| Exhaustive.java:1:14:1:23 | super(...) | Exhaustive.java:1:14:1:23 | Normal Exit |
| Exhaustive.java:1:14:1:23 | { ... } | Exhaustive.java:1:14:1:23 | super(...) |
-| Exhaustive.java:3:8:3:8 | super(...) | Exhaustive.java:3:8:3:8 | Exit |
+| Exhaustive.java:3:8:3:8 | Exceptional Exit | Exhaustive.java:3:8:3:8 | Exit |
+| Exhaustive.java:3:8:3:8 | Exceptional Exit | Exhaustive.java:3:8:3:8 | Exit |
+| Exhaustive.java:3:8:3:8 | Normal Exit | Exhaustive.java:3:8:3:8 | Exit |
+| Exhaustive.java:3:8:3:8 | Normal Exit | Exhaustive.java:3:8:3:8 | Exit |
+| Exhaustive.java:3:8:3:8 | super(...) | Exhaustive.java:3:8:3:8 | Normal Exit |
| Exhaustive.java:3:8:3:8 | { ... } | Exhaustive.java:3:8:3:8 | super(...) |
| Exhaustive.java:3:8:3:8 | { ... } | Exhaustive.java:3:12:3:12 | ; |
| Exhaustive.java:3:12:3:12 | ...=... | Exhaustive.java:3:15:3:15 | ; |
@@ -9,13 +15,19 @@
| Exhaustive.java:3:15:3:15 | ...=... | Exhaustive.java:3:18:3:18 | ; |
| Exhaustive.java:3:15:3:15 | ; | Exhaustive.java:3:15:3:15 | new E(...) |
| Exhaustive.java:3:15:3:15 | new E(...) | Exhaustive.java:3:15:3:15 | ...=... |
-| Exhaustive.java:3:18:3:18 | ...=... | Exhaustive.java:3:8:3:8 | Exit |
+| Exhaustive.java:3:18:3:18 | ...=... | Exhaustive.java:3:8:3:8 | Normal Exit |
| Exhaustive.java:3:18:3:18 | ; | Exhaustive.java:3:18:3:18 | new E(...) |
| Exhaustive.java:3:18:3:18 | new E(...) | Exhaustive.java:3:18:3:18 | ...=... |
-| Exhaustive.java:5:15:5:15 | super(...) | Exhaustive.java:5:15:5:15 | Exit |
+| Exhaustive.java:5:15:5:15 | Exceptional Exit | Exhaustive.java:5:15:5:15 | Exit |
+| Exhaustive.java:5:15:5:15 | Normal Exit | Exhaustive.java:5:15:5:15 | Exit |
+| Exhaustive.java:5:15:5:15 | super(...) | Exhaustive.java:5:15:5:15 | Normal Exit |
| Exhaustive.java:5:15:5:15 | { ... } | Exhaustive.java:5:15:5:15 | super(...) |
-| Exhaustive.java:6:15:6:15 | super(...) | Exhaustive.java:6:15:6:15 | Exit |
+| Exhaustive.java:6:15:6:15 | Exceptional Exit | Exhaustive.java:6:15:6:15 | Exit |
+| Exhaustive.java:6:15:6:15 | Normal Exit | Exhaustive.java:6:15:6:15 | Exit |
+| Exhaustive.java:6:15:6:15 | super(...) | Exhaustive.java:6:15:6:15 | Normal Exit |
| Exhaustive.java:6:15:6:15 | { ... } | Exhaustive.java:6:15:6:15 | super(...) |
+| Exhaustive.java:8:22:8:25 | Exceptional Exit | Exhaustive.java:8:22:8:25 | Exit |
+| Exhaustive.java:8:22:8:25 | Normal Exit | Exhaustive.java:8:22:8:25 | Exit |
| Exhaustive.java:8:47:35:3 | { ... } | Exhaustive.java:11:5:11:14 | switch (...) |
| Exhaustive.java:11:5:11:14 | switch (...) | Exhaustive.java:11:13:11:13 | o |
| Exhaustive.java:11:13:11:13 | o | Exhaustive.java:12:7:12:22 | case |
@@ -50,11 +62,15 @@
| Exhaustive.java:30:13:30:13 | i | Exhaustive.java:31:7:31:15 | case |
| Exhaustive.java:31:7:31:15 | case | Exhaustive.java:31:14:31:14 | |
| Exhaustive.java:31:7:31:15 | case | Exhaustive.java:32:7:32:15 | case |
-| Exhaustive.java:31:14:31:14 | | Exhaustive.java:8:22:8:25 | Exit |
+| Exhaustive.java:31:14:31:14 | | Exhaustive.java:8:22:8:25 | Normal Exit |
| Exhaustive.java:32:7:32:15 | case | Exhaustive.java:32:14:32:14 | |
-| Exhaustive.java:32:14:32:14 | | Exhaustive.java:8:22:8:25 | Exit |
-| Test.java:1:14:1:17 | super(...) | Test.java:1:14:1:17 | Exit |
+| Exhaustive.java:32:14:32:14 | | Exhaustive.java:8:22:8:25 | Normal Exit |
+| Test.java:1:14:1:17 | Exceptional Exit | Test.java:1:14:1:17 | Exit |
+| Test.java:1:14:1:17 | Normal Exit | Test.java:1:14:1:17 | Exit |
+| Test.java:1:14:1:17 | super(...) | Test.java:1:14:1:17 | Normal Exit |
| Test.java:1:14:1:17 | { ... } | Test.java:1:14:1:17 | super(...) |
+| Test.java:3:22:3:25 | Exceptional Exit | Test.java:3:22:3:25 | Exit |
+| Test.java:3:22:3:25 | Normal Exit | Test.java:3:22:3:25 | Exit |
| Test.java:3:41:134:3 | { ... } | Test.java:5:6:5:19 | switch (...) |
| Test.java:5:6:5:19 | switch (...) | Test.java:5:14:5:18 | thing |
| Test.java:5:14:5:18 | thing | Test.java:6:8:6:23 | case |
@@ -380,11 +396,13 @@
| Test.java:130:8:130:21 | case | Test.java:130:20:130:20 | |
| Test.java:130:8:130:21 | case | Test.java:131:8:131:15 | default |
| Test.java:130:20:130:20 | | Test.java:131:8:131:15 | default |
-| Test.java:131:8:131:15 | default | Test.java:3:22:3:25 | Exit |
+| Test.java:131:8:131:15 | default | Test.java:3:22:3:25 | Normal Exit |
| Test.java:138:8:138:8 | ...=... | Test.java:138:8:138:8 | ; |
-| Test.java:138:8:138:8 | ...=... | Test.java:138:8:138:8 | Exit |
+| Test.java:138:8:138:8 | ...=... | Test.java:138:8:138:8 | Normal Exit |
| Test.java:138:8:138:8 | ; | Test.java:138:8:138:8 | this |
| Test.java:138:8:138:8 | ; | Test.java:138:8:138:8 | this |
+| Test.java:138:8:138:8 | Exceptional Exit | Test.java:138:8:138:8 | Exit |
+| Test.java:138:8:138:8 | Normal Exit | Test.java:138:8:138:8 | Exit |
| Test.java:138:8:138:8 | b | Test.java:138:8:138:8 | ...=... |
| Test.java:138:8:138:8 | field3 | Test.java:138:8:138:8 | ...=... |
| Test.java:138:8:138:8 | super(...) | Test.java:138:8:138:8 | ; |
@@ -392,9 +410,11 @@
| Test.java:138:8:138:8 | this | Test.java:138:8:138:8 | field3 |
| Test.java:138:8:138:8 | { ... } | Test.java:138:8:138:8 | super(...) |
| Test.java:139:8:139:8 | ...=... | Test.java:139:8:139:8 | ; |
-| Test.java:139:8:139:8 | ...=... | Test.java:139:8:139:8 | Exit |
+| Test.java:139:8:139:8 | ...=... | Test.java:139:8:139:8 | Normal Exit |
| Test.java:139:8:139:8 | ; | Test.java:139:8:139:8 | this |
| Test.java:139:8:139:8 | ; | Test.java:139:8:139:8 | this |
+| Test.java:139:8:139:8 | Exceptional Exit | Test.java:139:8:139:8 | Exit |
+| Test.java:139:8:139:8 | Normal Exit | Test.java:139:8:139:8 | Exit |
| Test.java:139:8:139:8 | field1 | Test.java:139:8:139:8 | ...=... |
| Test.java:139:8:139:8 | field2 | Test.java:139:8:139:8 | ...=... |
| Test.java:139:8:139:8 | super(...) | Test.java:139:8:139:8 | ; |
diff --git a/java/ql/test/library-tests/successors/CloseReaderTest/TestSucc.expected b/java/ql/test/library-tests/successors/CloseReaderTest/TestSucc.expected
index a6f3820334a..fc529feba13 100644
--- a/java/ql/test/library-tests/successors/CloseReaderTest/TestSucc.expected
+++ b/java/ql/test/library-tests/successors/CloseReaderTest/TestSucc.expected
@@ -1,5 +1,9 @@
-| CloseReaderTest.java:8:14:8:28 | super(...) | CloseReaderTest.java:8:14:8:28 | Exit |
+| CloseReaderTest.java:8:14:8:28 | Exceptional Exit | CloseReaderTest.java:8:14:8:28 | Exit |
+| CloseReaderTest.java:8:14:8:28 | Normal Exit | CloseReaderTest.java:8:14:8:28 | Exit |
+| CloseReaderTest.java:8:14:8:28 | super(...) | CloseReaderTest.java:8:14:8:28 | Normal Exit |
| CloseReaderTest.java:8:14:8:28 | { ... } | CloseReaderTest.java:8:14:8:28 | super(...) |
+| CloseReaderTest.java:9:23:9:34 | Exceptional Exit | CloseReaderTest.java:9:23:9:34 | Exit |
+| CloseReaderTest.java:9:23:9:34 | Normal Exit | CloseReaderTest.java:9:23:9:34 | Exit |
| CloseReaderTest.java:10:2:24:2 | { ... } | CloseReaderTest.java:12:3:13:42 | ; |
| CloseReaderTest.java:12:3:12:12 | System.out | CloseReaderTest.java:12:20:12:40 | "Enter password for " |
| CloseReaderTest.java:12:3:13:41 | print(...) | CloseReaderTest.java:14:3:14:21 | ; |
@@ -19,12 +23,12 @@
| CloseReaderTest.java:16:5:16:13 | System.in | CloseReaderTest.java:15:45:16:14 | new InputStreamReader(...) |
| CloseReaderTest.java:17:3:23:3 | try ... | CloseReaderTest.java:18:3:20:3 | { ... } |
| CloseReaderTest.java:18:3:20:3 | { ... } | CloseReaderTest.java:19:11:19:15 | stdin |
-| CloseReaderTest.java:19:4:19:27 | return ... | CloseReaderTest.java:9:23:9:34 | Exit |
+| CloseReaderTest.java:19:4:19:27 | return ... | CloseReaderTest.java:9:23:9:34 | Normal Exit |
| CloseReaderTest.java:19:11:19:15 | stdin | CloseReaderTest.java:19:11:19:26 | readLine(...) |
| CloseReaderTest.java:19:11:19:26 | readLine(...) | CloseReaderTest.java:19:4:19:27 | return ... |
| CloseReaderTest.java:19:11:19:26 | readLine(...) | CloseReaderTest.java:20:5:20:26 | catch (...) |
| CloseReaderTest.java:20:5:20:26 | catch (...) | CloseReaderTest.java:20:24:20:25 | ex |
| CloseReaderTest.java:20:24:20:25 | ex | CloseReaderTest.java:21:3:23:3 | { ... } |
| CloseReaderTest.java:21:3:23:3 | { ... } | CloseReaderTest.java:22:11:22:14 | null |
-| CloseReaderTest.java:22:4:22:15 | return ... | CloseReaderTest.java:9:23:9:34 | Exit |
+| CloseReaderTest.java:22:4:22:15 | return ... | CloseReaderTest.java:9:23:9:34 | Normal Exit |
| CloseReaderTest.java:22:11:22:14 | null | CloseReaderTest.java:22:4:22:15 | return ... |
diff --git a/java/ql/test/library-tests/successors/LoopVarReadTest/TestSucc.expected b/java/ql/test/library-tests/successors/LoopVarReadTest/TestSucc.expected
index dcf2dac3cca..3566cc8753f 100644
--- a/java/ql/test/library-tests/successors/LoopVarReadTest/TestSucc.expected
+++ b/java/ql/test/library-tests/successors/LoopVarReadTest/TestSucc.expected
@@ -1,5 +1,9 @@
-| LoopVarReadTest.java:3:14:3:28 | super(...) | LoopVarReadTest.java:3:14:3:28 | Exit |
+| LoopVarReadTest.java:3:14:3:28 | Exceptional Exit | LoopVarReadTest.java:3:14:3:28 | Exit |
+| LoopVarReadTest.java:3:14:3:28 | Normal Exit | LoopVarReadTest.java:3:14:3:28 | Exit |
+| LoopVarReadTest.java:3:14:3:28 | super(...) | LoopVarReadTest.java:3:14:3:28 | Normal Exit |
| LoopVarReadTest.java:3:14:3:28 | { ... } | LoopVarReadTest.java:3:14:3:28 | super(...) |
+| LoopVarReadTest.java:4:21:4:28 | Exceptional Exit | LoopVarReadTest.java:4:21:4:28 | Exit |
+| LoopVarReadTest.java:4:21:4:28 | Normal Exit | LoopVarReadTest.java:4:21:4:28 | Exit |
| LoopVarReadTest.java:5:2:15:2 | { ... } | LoopVarReadTest.java:6:3:6:12 | var ...; |
| LoopVarReadTest.java:6:3:6:12 | var ...; | LoopVarReadTest.java:6:11:6:11 | 2 |
| LoopVarReadTest.java:6:7:6:11 | x | LoopVarReadTest.java:7:3:7:33 | for (...;...;...) |
@@ -23,6 +27,6 @@
| LoopVarReadTest.java:12:7:12:12 | q | LoopVarReadTest.java:14:3:14:28 | ; |
| LoopVarReadTest.java:12:11:12:12 | 10 | LoopVarReadTest.java:12:7:12:12 | q |
| LoopVarReadTest.java:14:3:14:12 | System.out | LoopVarReadTest.java:14:22:14:26 | "foo" |
-| LoopVarReadTest.java:14:3:14:27 | println(...) | LoopVarReadTest.java:4:21:4:28 | Exit |
+| LoopVarReadTest.java:14:3:14:27 | println(...) | LoopVarReadTest.java:4:21:4:28 | Normal Exit |
| LoopVarReadTest.java:14:3:14:28 | ; | LoopVarReadTest.java:14:3:14:12 | System.out |
| LoopVarReadTest.java:14:22:14:26 | "foo" | LoopVarReadTest.java:14:3:14:27 | println(...) |
diff --git a/java/ql/test/library-tests/successors/SaveFileTest/TestSucc.expected b/java/ql/test/library-tests/successors/SaveFileTest/TestSucc.expected
index 3c261f67ee1..640e731147f 100644
--- a/java/ql/test/library-tests/successors/SaveFileTest/TestSucc.expected
+++ b/java/ql/test/library-tests/successors/SaveFileTest/TestSucc.expected
@@ -1,5 +1,9 @@
-| SaveFileTest.java:11:14:11:25 | super(...) | SaveFileTest.java:11:14:11:25 | Exit |
+| SaveFileTest.java:11:14:11:25 | Exceptional Exit | SaveFileTest.java:11:14:11:25 | Exit |
+| SaveFileTest.java:11:14:11:25 | Normal Exit | SaveFileTest.java:11:14:11:25 | Exit |
+| SaveFileTest.java:11:14:11:25 | super(...) | SaveFileTest.java:11:14:11:25 | Normal Exit |
| SaveFileTest.java:11:14:11:25 | { ... } | SaveFileTest.java:11:14:11:25 | super(...) |
+| SaveFileTest.java:12:14:12:21 | Exceptional Exit | SaveFileTest.java:12:14:12:21 | Exit |
+| SaveFileTest.java:12:14:12:21 | Normal Exit | SaveFileTest.java:12:14:12:21 | Exit |
| SaveFileTest.java:15:2:55:2 | { ... } | SaveFileTest.java:17:3:17:25 | var ...; |
| SaveFileTest.java:17:3:17:25 | var ...; | SaveFileTest.java:17:21:17:24 | path |
| SaveFileTest.java:17:10:17:24 | savePath | SaveFileTest.java:18:3:18:27 | if (...) |
@@ -95,9 +99,11 @@
| SaveFileTest.java:48:5:48:15 | flush(...) | SaveFileTest.java:50:6:50:30 | catch (...) |
| SaveFileTest.java:48:5:48:16 | ; | SaveFileTest.java:48:5:48:7 | bos |
| SaveFileTest.java:49:5:49:7 | bos | SaveFileTest.java:49:5:49:15 | close(...) |
-| SaveFileTest.java:49:5:49:15 | close(...) | SaveFileTest.java:12:14:12:21 | Exit |
+| SaveFileTest.java:49:5:49:15 | close(...) | SaveFileTest.java:12:14:12:21 | Exceptional Exit |
+| SaveFileTest.java:49:5:49:15 | close(...) | SaveFileTest.java:12:14:12:21 | Normal Exit |
| SaveFileTest.java:49:5:49:15 | close(...) | SaveFileTest.java:50:6:50:30 | catch (...) |
| SaveFileTest.java:49:5:49:16 | ; | SaveFileTest.java:49:5:49:7 | bos |
| SaveFileTest.java:50:6:50:30 | catch (...) | SaveFileTest.java:50:23:50:29 | ignored |
| SaveFileTest.java:50:23:50:29 | ignored | SaveFileTest.java:51:4:52:4 | { ... } |
-| SaveFileTest.java:51:4:52:4 | { ... } | SaveFileTest.java:12:14:12:21 | Exit |
+| SaveFileTest.java:51:4:52:4 | { ... } | SaveFileTest.java:12:14:12:21 | Exceptional Exit |
+| SaveFileTest.java:51:4:52:4 | { ... } | SaveFileTest.java:12:14:12:21 | Normal Exit |
diff --git a/java/ql/test/library-tests/successors/SchackTest/TestSucc.expected b/java/ql/test/library-tests/successors/SchackTest/TestSucc.expected
index c645abe3507..a23f6a2bc54 100644
--- a/java/ql/test/library-tests/successors/SchackTest/TestSucc.expected
+++ b/java/ql/test/library-tests/successors/SchackTest/TestSucc.expected
@@ -1,9 +1,17 @@
-| SchackTest.java:1:14:1:23 | super(...) | SchackTest.java:1:14:1:23 | Exit |
+| SchackTest.java:1:14:1:23 | Exceptional Exit | SchackTest.java:1:14:1:23 | Exit |
+| SchackTest.java:1:14:1:23 | Normal Exit | SchackTest.java:1:14:1:23 | Exit |
+| SchackTest.java:1:14:1:23 | super(...) | SchackTest.java:1:14:1:23 | Normal Exit |
| SchackTest.java:1:14:1:23 | { ... } | SchackTest.java:1:14:1:23 | super(...) |
-| SchackTest.java:2:8:2:10 | super(...) | SchackTest.java:2:8:2:10 | Exit |
+| SchackTest.java:2:8:2:10 | Exceptional Exit | SchackTest.java:2:8:2:10 | Exit |
+| SchackTest.java:2:8:2:10 | Normal Exit | SchackTest.java:2:8:2:10 | Exit |
+| SchackTest.java:2:8:2:10 | super(...) | SchackTest.java:2:8:2:10 | Normal Exit |
| SchackTest.java:2:8:2:10 | { ... } | SchackTest.java:2:8:2:10 | super(...) |
-| SchackTest.java:3:8:3:10 | super(...) | SchackTest.java:3:8:3:10 | Exit |
+| SchackTest.java:3:8:3:10 | Exceptional Exit | SchackTest.java:3:8:3:10 | Exit |
+| SchackTest.java:3:8:3:10 | Normal Exit | SchackTest.java:3:8:3:10 | Exit |
+| SchackTest.java:3:8:3:10 | super(...) | SchackTest.java:3:8:3:10 | Normal Exit |
| SchackTest.java:3:8:3:10 | { ... } | SchackTest.java:3:8:3:10 | super(...) |
+| SchackTest.java:5:7:5:9 | Exceptional Exit | SchackTest.java:5:7:5:9 | Exit |
+| SchackTest.java:5:7:5:9 | Normal Exit | SchackTest.java:5:7:5:9 | Exit |
| SchackTest.java:5:18:24:2 | { ... } | SchackTest.java:6:3:23:3 | try ... |
| SchackTest.java:6:3:23:3 | try ... | SchackTest.java:6:7:17:3 | { ... } |
| SchackTest.java:6:7:17:3 | { ... } | SchackTest.java:7:4:15:4 | try ... |
@@ -56,18 +64,21 @@
| SchackTest.java:20:23:20:72 | "successor (but neither true nor false successor)" | SchackTest.java:20:4:20:73 | println(...) |
| SchackTest.java:21:13:23:3 | { ... } | SchackTest.java:22:4:22:41 |