Compare commits

..

1 Commits

Author SHA1 Message Date
Paolo Tranquilli
840d166efe WIP: integration test 2025-07-01 14:52:03 +02:00
1101 changed files with 29349 additions and 106661 deletions

View File

@@ -2,10 +2,3 @@ When reviewing code:
* do not review changes in files with `.expected` extension (they are automatically ensured to be correct).
* in `.ql` and `.qll` files, do not try to review the code itself as you don't understand the programming language
well enough to make comments in these languages. You can still check for typos or comment improvements.
When editing `.ql` and `.qll` files:
* All edited `.ql` and `.qll` files should be autoformatted afterwards using the CodeQL CLI.
* To install and use the CodeQL CLI autoformatter:
1. Download and extract CodeQL CLI: `cd /tmp && curl -L -o codeql-linux64.zip https://github.com/github/codeql-cli-binaries/releases/latest/download/codeql-linux64.zip && unzip -q codeql-linux64.zip`
2. Add to PATH: `export PATH="/tmp/codeql:$PATH"`
3. Run autoformatter: `codeql query format [file] --in-place`

35
.github/workflows/go-tests-other-os.yml vendored Normal file
View File

@@ -0,0 +1,35 @@
name: "Go: Run Tests - Other OS"
on:
pull_request:
paths:
- "go/**"
- "!go/documentation/**"
- "!go/ql/**" # don't run other-os if only ql/ files changed
- .github/workflows/go-tests-other-os.yml
- .github/actions/**
- codeql-workspace.yml
- MODULE.bazel
- .bazelrc
- misc/bazel/**
permissions:
contents: read
jobs:
test-mac:
name: Test MacOS
runs-on: macos-latest
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Run tests
uses: ./go/actions/test
test-win:
name: Test Windows
runs-on: windows-latest
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Run tests
uses: ./go/actions/test

22
.github/workflows/go-tests-rtjo.yml vendored Normal file
View File

@@ -0,0 +1,22 @@
name: "Go: Run RTJO Tests"
on:
pull_request:
types:
- labeled
permissions:
contents: read
jobs:
test-linux:
if: "github.repository_owner == 'github' && github.event.label.name == 'Run: RTJO Language Tests'"
name: RTJO Test Linux (Ubuntu)
runs-on: ubuntu-latest-xl
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Run tests
uses: ./go/actions/test
with:
run-code-checks: true
dynamic-join-order-mode: all

View File

@@ -1,6 +1,6 @@
name: "Go: Run Tests"
on:
pull_request:
push:
paths:
- "go/**"
- "!go/documentation/**"
@@ -8,6 +8,17 @@ on:
- .github/workflows/go-tests.yml
- .github/actions/**
- codeql-workspace.yml
branches:
- main
- "rc/*"
pull_request:
paths:
- "go/**"
- "!go/documentation/**"
- "shared/**"
- .github/workflows/go-tests.yml
- .github/actions/**
- codeql-workspace.yml
- MODULE.bazel
- .bazelrc
- misc/bazel/**

View File

@@ -37,7 +37,6 @@ bazel_dep(name = "buildifier_prebuilt", version = "6.4.0", dev_dependency = True
# the versions there are canonical, the versions here are used for CI in github/codeql, as well as for the vendoring of dependencies.
RUST_EDITION = "2024"
# run buildutils-internal/scripts/fill-rust-sha256s.py when updating (internal repo)
RUST_VERSION = "1.86.0"
rust = use_extension("@rules_rust//rust:extensions.bzl", "rust")
@@ -48,29 +47,6 @@ rust.toolchain(
"x86_64-apple-darwin",
"aarch64-apple-darwin",
],
# generated by buildutils-internal/scripts/fill-rust-sha256s.py (internal repo)
sha256s = {
"rustc-1.86.0-x86_64-unknown-linux-gnu.tar.xz": "4438b809ce4a083af31ed17aeeedcc8fc60ccffc0625bef1926620751b6989d7",
"rustc-1.86.0-x86_64-apple-darwin.tar.xz": "42b76253626febb7912541a30d3379f463dec89581aad4cb72c6c04fb5a71dc5",
"rustc-1.86.0-aarch64-apple-darwin.tar.xz": "23b8f52102249a47ab5bc859d54c9a3cb588a3259ba3f00f557d50edeca4fde9",
"rustc-1.86.0-x86_64-pc-windows-msvc.tar.xz": "fdde839fea274529a31e51eb85c6df1782cc8479c9d1bc24e2914d66a0de41ab",
"clippy-1.86.0-x86_64-unknown-linux-gnu.tar.xz": "02aaff2c1407d2da8dba19aa4970dd873e311902b120a66cbcdbe51eb8836edf",
"clippy-1.86.0-x86_64-apple-darwin.tar.xz": "bb85efda7bbffaf124867f5ca36d50932b1e8f533c62ee923438afb32ff8fe9a",
"clippy-1.86.0-aarch64-apple-darwin.tar.xz": "239fa3a604b124f0312f2af08537874a1227dba63385484b468cca62e7c4f2f2",
"clippy-1.86.0-x86_64-pc-windows-msvc.tar.xz": "d00498f47d49219f032e2c5eeebdfc3d32317c0dc3d3fd7125327445bc482cb4",
"cargo-1.86.0-x86_64-unknown-linux-gnu.tar.xz": "c5c1590f7e9246ad9f4f97cfe26ffa92707b52a769726596a9ef81565ebd908b",
"cargo-1.86.0-x86_64-apple-darwin.tar.xz": "af163eb02d1a178044d1b4f2375960efd47130f795f6e33d09e345454bb26f4e",
"cargo-1.86.0-aarch64-apple-darwin.tar.xz": "3cb13873d48c3e1e4cc684d42c245226a11fba52af6b047c3346ed654e7a05c0",
"cargo-1.86.0-x86_64-pc-windows-msvc.tar.xz": "e57a9d89619b5604899bac443e68927bdd371e40f2e03e18950b6ceb3eb67966",
"llvm-tools-1.86.0-x86_64-unknown-linux-gnu.tar.xz": "282145ab7a63c98b625856f44b905b4dc726b497246b824632a5790debe95a78",
"llvm-tools-1.86.0-x86_64-apple-darwin.tar.xz": "b55706e92f7da989207c50c13c7add483a9fedd233bc431b106eca2a8f151ec9",
"llvm-tools-1.86.0-aarch64-apple-darwin.tar.xz": "04d3618c686845853585f036e3211eb9e18f2d290f4610a7a78bdc1fcce1ebd9",
"llvm-tools-1.86.0-x86_64-pc-windows-msvc.tar.xz": "721a17cc8dc219177e4277a3592253934ef08daa1e1b12eda669a67d15fad8dd",
"rust-std-1.86.0-x86_64-unknown-linux-gnu.tar.xz": "67be7184ea388d8ce0feaf7fdea46f1775cfc2970930264343b3089898501d37",
"rust-std-1.86.0-x86_64-apple-darwin.tar.xz": "3b1140d54870a080080e84700143f4a342fbd02a410a319b05d9c02e7dcf44cc",
"rust-std-1.86.0-aarch64-apple-darwin.tar.xz": "0fb121fb3b8fa9027d79ff598500a7e5cd086ddbc3557482ed3fdda00832c61b",
"rust-std-1.86.0-x86_64-pc-windows-msvc.tar.xz": "3d5354b7b9cb950b58bff3fce18a652aa374bb30c8f70caebd3bd0b43cb41a33",
},
versions = [RUST_VERSION],
)
use_repo(rust, "rust_toolchains")

View File

@@ -1,9 +1,3 @@
## 0.4.13
### Bug Fixes
* The `actions/artifact-poisoning/critical` and `actions/artifact-poisoning/medium` queries now exclude artifacts downloaded to `$[{ runner.temp }}` in addition to `/tmp`.
## 0.4.12
### Minor Analysis Improvements

View File

@@ -1,5 +0,0 @@
## 0.4.13
### Bug Fixes
* The `actions/artifact-poisoning/critical` and `actions/artifact-poisoning/medium` queries now exclude artifacts downloaded to `$[{ runner.temp }}` in addition to `/tmp`.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.4.13
lastReleaseVersion: 0.4.12

View File

@@ -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

View File

@@ -262,10 +262,8 @@ class ArtifactPoisoningSink extends DataFlow::Node {
ArtifactPoisoningSink() {
download.getAFollowingStep() = poisonable and
// excluding artifacts downloaded to the temporary directory
// excluding artifacts downloaded to /tmp
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
(

View File

@@ -1,5 +1,5 @@
name: codeql/actions-all
version: 0.4.14-dev
version: 0.4.13-dev
library: true
warnOnImplicitThis: true
dependencies:

View File

@@ -1,7 +1,3 @@
## 0.6.5
No user-facing changes.
## 0.6.4
No user-facing changes.

View File

@@ -1,3 +0,0 @@
## 0.6.5
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.6.5
lastReleaseVersion: 0.6.4

View File

@@ -1,5 +1,5 @@
name: codeql/actions-queries
version: 0.6.6-dev
version: 0.6.5-dev
library: false
warnOnImplicitThis: true
groups: [actions, queries]

View File

@@ -1,19 +0,0 @@
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

View File

@@ -1,19 +0,0 @@
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

View File

@@ -1,19 +0,0 @@
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

View File

@@ -1,18 +0,0 @@
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

View File

@@ -1,19 +0,0 @@
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

View File

@@ -13,7 +13,6 @@ 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 |
@@ -45,8 +44,6 @@ 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 |
@@ -69,7 +66,6 @@ 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 |

View File

@@ -13,7 +13,6 @@ 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 |
@@ -45,8 +44,6 @@ 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 |

View File

@@ -51,16 +51,6 @@ 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 |

View File

@@ -231,10 +231,35 @@
"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",

View File

@@ -2,9 +2,6 @@ language: cpp
strategy: dca
destination: cpp/ql/lib/ext/generated
targets:
- name: glibc
with-sinks: false
with-sources: false
- name: zlib
with-sinks: false
with-sources: false

View File

@@ -1,2 +0,0 @@
description: Uncomment cases in dbscheme
compatibility: full

View File

@@ -1,2 +0,0 @@
description: Remove unused external_package tables from the dbscheme
compatibility: full

View File

@@ -1,9 +0,0 @@
class Function extends @function {
string toString() { none() }
}
from Function f, string n, int k, int new_k
where
functions(f, n, k) and
if builtin_functions(f) then new_k = 6 else new_k = k
select f, n, new_k

View File

@@ -1,4 +0,0 @@
description: Move builtin function identification to its own table
compatibility: full
functions.rel: run functions.qlo
builtin_functions.rel: delete

View File

@@ -4,3 +4,4 @@
int main() {
return ONE + TWO + THREE + FOUR;
}
// semmle-extractor-options: --clang -include-pch ${testdir}/clang-pch.testproj/a.pch -Iextra_dummy_path

View File

@@ -1,20 +1,3 @@
## 5.3.0
### Deprecated APIs
* The `UnknownDefaultLocation`, `UnknownExprLocation`, and `UnknownStmtLocation` classes have been deprecated. Use `UnknownLocation` instead.
### New Features
* Added a `isFinalValueOfParameter` predicate to `DataFlow::Node` which holds when a dataflow node represents the final value of an output parameter of a function.
### Minor Analysis Improvements
* The `FunctionWithWrappers` library (`semmle.code.cpp.security.FunctionWithWrappers`) no longer considers calls through function pointers as wrapper functions.
* The analysis of C/C++ code targeting 64-bit Arm platforms has been improved. This includes support for the Arm-specific builtin functions, support for the `arm_neon.h` header and Neon vector types, and support for the `fp8` scalar type. The `arm_sve.h` header and scalable vectors are only partially supported at this point.
* Added support for `__fp16 _Complex` and `__bf16 _Complex` types
* Added `sql-injection` sink models for the Oracle Call Interface (OCI) database library functions `OCIStmtPrepare` and `OCIStmtPrepare2`.
## 5.2.0
### Deprecated APIs

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added `sql-injection` sink models for the Oracle Call Interface (OCI) database library functions `OCIStmtPrepare` and `OCIStmtPrepare2`.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The analysis of C/C++ code targeting 64-bit Arm platforms has been improved. This includes support for the Arm-specific builtin functions, support for the `arm_neon.h` header and Neon vector types, and support for the `fp8` scalar type. The `arm_sve.h` header and scalable vectors are only partially supported at this point.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added support for `__fp16 _Complex` and `__bf16 _Complex` types

View File

@@ -0,0 +1,4 @@
---
category: deprecated
---
* The `UnknownDefaultLocation`, `UnknownExprLocation`, and `UnknownStmtLocation` classes have been deprecated. Use `UnknownLocation` instead.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* The `cpp/overrun-write` query now recognizes more bound checks and thus produces fewer false positives.

View File

@@ -1,16 +0,0 @@
## 5.3.0
### Deprecated APIs
* The `UnknownDefaultLocation`, `UnknownExprLocation`, and `UnknownStmtLocation` classes have been deprecated. Use `UnknownLocation` instead.
### New Features
* Added a `isFinalValueOfParameter` predicate to `DataFlow::Node` which holds when a dataflow node represents the final value of an output parameter of a function.
### Minor Analysis Improvements
* The `FunctionWithWrappers` library (`semmle.code.cpp.security.FunctionWithWrappers`) no longer considers calls through function pointers as wrapper functions.
* The analysis of C/C++ code targeting 64-bit Arm platforms has been improved. This includes support for the Arm-specific builtin functions, support for the `arm_neon.h` header and Neon vector types, and support for the `fp8` scalar type. The `arm_sve.h` header and scalable vectors are only partially supported at this point.
* Added support for `__fp16 _Complex` and `__bf16 _Complex` types
* Added `sql-injection` sink models for the Oracle Call Interface (OCI) database library functions `OCIStmtPrepare` and `OCIStmtPrepare2`.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 5.3.0
lastReleaseVersion: 5.2.0

View File

@@ -32,8 +32,4 @@ extensions:
- ["", "", False, "CommandLineToArgvA", "", "", "Argument[*0]", "ReturnValue[**]", "taint", "manual"]
- ["", "", False, "CommandLineToArgvW", "", "", "Argument[*0]", "ReturnValue[**]", "taint", "manual"]
# fileapi.h
- ["", "", False, "ReadFileEx", "", "", "Argument[*3].Field[@hEvent]", "Argument[4].Parameter[*2].Field[@hEvent]", "value", "manual"]
# processthreadsapi.h
- ["", "", False, "CreateThread", "", "", "Argument[@3]", "Argument[2].Parameter[@0]", "value", "manual"]
- ["", "", False, "CreateRemoteThread", "", "", "Argument[@4]", "Argument[3].Parameter[@0]", "value", "manual"]
- ["", "", False, "CreateRemoteThreadEx", "", "", "Argument[@4]", "Argument[3].Parameter[@0]", "value", "manual"]
- ["", "", False, "ReadFileEx", "", "", "Argument[*3].Field[@hEvent]", "Argument[4].Parameter[*2].Field[@hEvent]", "value", "manual"]

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +0,0 @@
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"]

View File

@@ -1,11 +0,0 @@
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"]

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all
version: 5.3.1-dev
version: 5.2.1-dev
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp

View File

@@ -57,9 +57,7 @@ class RequiresExpr extends Expr, @requires_expr {
/**
* A C++ requirement in a requires expression.
*/
class RequirementExpr extends Expr {
RequirementExpr() { this.getParent() instanceof RequiresExpr }
}
class RequirementExpr extends Expr { }
/**
* A C++ simple requirement in a requires expression.
@@ -72,6 +70,7 @@ 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
@@ -90,6 +89,8 @@ 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" }
}
@@ -139,7 +140,7 @@ class CompoundRequirementExpr extends RequirementExpr, @compound_requirement {
* with `T` a template parameter, then `requires std::is_same<T, int>::value;` is
* a nested requirement.
*/
class NestedRequirementExpr extends RequirementExpr, @nested_requirement {
class NestedRequirementExpr extends Expr, @nested_requirement {
override string toString() { result = "requires ..." }
override string getAPrimaryQlClass() { result = "NestedRequirementExpr" }
@@ -162,7 +163,7 @@ class NestedRequirementExpr extends RequirementExpr, @nested_requirement {
* then `C<int, 1>` is a concept id expression that refers to
* the concept `C`.
*/
class ConceptIdExpr extends Expr, @concept_id {
class ConceptIdExpr extends RequirementExpr, @concept_id {
override string toString() {
result = this.getConcept().getName() + "<...>"
or

View File

@@ -282,12 +282,9 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
* definition, if possible.)
*/
override Location getLocation() {
if this instanceof BuiltInFunction
then result instanceof UnknownLocation // a dummy location for the built-in function
else
if exists(this.getDefinition())
then result = this.getDefinitionLocation()
else result = this.getADeclarationLocation()
if exists(this.getDefinition())
then result = this.getDefinitionLocation()
else result = this.getADeclarationLocation()
}
/** Gets a child declaration of this function. */
@@ -899,9 +896,17 @@ class FunctionTemplateSpecialization extends Function {
* A GCC built-in function. For example: `__builtin___memcpy_chk`.
*/
class BuiltInFunction extends Function {
BuiltInFunction() { builtin_functions(underlyingElement(this)) }
BuiltInFunction() { functions(underlyingElement(this), _, 6) }
/** Gets a dummy location for the built-in function. */
override Location getLocation() {
suppressUnusedThis(this) and
result instanceof UnknownLocation
}
}
private predicate suppressUnusedThis(Function f) { any() }
/**
* A C++ user-defined literal [N4140 13.5.8].
*/

View File

@@ -1382,89 +1382,16 @@ predicate neverSkipInPathGraph(Node n) {
exists(n.asIndirectDefinition())
}
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()
)
}
class LambdaCallKind = Unit;
/** Holds if `creation` is an expression that creates a lambda of kind `kind` for `c`. */
predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) {
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)
)
creation.asInstruction().(FunctionAddressInstruction).getFunctionSymbol() = c.asSourceCallable() and
exists(kind)
}
/** 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
@@ -1473,15 +1400,8 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
// has a result for `getStaticCallTarget`.
not exists(call.getStaticCallTarget()) and
call.asCallInstruction().getCallTargetOperand() = receiver.asOperand()
)
or
kind.isFunctor() and
(
call.(SummaryCall).getReceiver() = receiver.(FlowSummaryNode).getSummaryNode()
or
not exists(call.getStaticCallTarget()) and
call.asCallInstruction().getThisArgumentOperand() = receiver.asOperand()
)
) and
exists(kind)
}
/** Extra data-flow steps needed for lambda flow analysis. */

View File

@@ -488,23 +488,6 @@ 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.
@@ -1242,7 +1225,7 @@ import RawIndirectNodes
/**
* INTERNAL: do not use.
*
* A node representing the value of an output parameter
* A node representing the value of an update parameter
* just before reaching the end of a function.
*/
class FinalParameterNode extends Node, TFinalParameterNode {

View File

@@ -151,7 +151,7 @@ private module Cached {
)
or
// Similarly for `i++` and `++i` we pretend that the generated
// `StoreInstruction` contains the result of the expression even though
// `StoreInstruction` is contains the result of the expression even though
// this isn't totally aligned with the C/C++ standard.
exists(TranslatedCrementOperation tco |
store = tco.getInstruction(CrementStoreTag()) and

View File

@@ -153,10 +153,6 @@ 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

View File

@@ -42,7 +42,6 @@ private newtype TOpcode =
TCompareGT() or
TCompareLE() or
TCompareGE() or
TSpaceship() or
TPointerAdd() or
TPointerSub() or
TPointerDiff() or
@@ -93,9 +92,7 @@ private newtype TOpcode =
TUninitializedGroup() or
TInlineAsm() or
TUnreached() or
TNewObj() or
TTypeidExpr() or
TTypeidType()
TNewObj()
/**
* An opcode that specifies the operation performed by an `Instruction`.
@@ -766,15 +763,6 @@ 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`.
*
@@ -1293,29 +1281,4 @@ 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" }
}
}

View File

@@ -725,20 +725,6 @@ 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()
}
}
/**
@@ -1604,13 +1590,6 @@ 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.
@@ -2300,26 +2279,3 @@ 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 }
}

View File

@@ -725,20 +725,6 @@ 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()
}
}
/**
@@ -1604,13 +1590,6 @@ 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.
@@ -2300,26 +2279,3 @@ 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 }
}

View File

@@ -1808,11 +1808,6 @@ 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.
*/
@@ -1872,8 +1867,7 @@ class TranslatedBinaryOperation extends TranslatedSingleInstructionExpr {
override Opcode getOpcode() {
result = binaryArithmeticOpcode(expr) or
result = binaryBitwiseOpcode(expr) or
result = comparisonOpcode(expr) or
result = spaceShipOpcode(expr)
result = comparisonOpcode(expr)
}
override Type getExprType() {
@@ -4152,8 +4146,7 @@ predicate exprNeedsCopyIfNotLoaded(Expr expr) {
private predicate exprImmediatelyDiscarded(Expr expr) {
exists(ExprStmt s |
s = expr.getParent() and
not exists(StmtExpr se | s = se.getStmt().(BlockStmt).getLastStmt()) and
not exists(expr.getConversion())
not exists(StmtExpr se | s = se.getStmt().(BlockStmt).getLastStmt())
)
or
exists(CommaExpr c | c.getLeftOperand() = expr)
@@ -4191,52 +4184,3 @@ 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())
}
}

View File

@@ -725,20 +725,6 @@ 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()
}
}
/**
@@ -1604,13 +1590,6 @@ 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.
@@ -2300,26 +2279,3 @@ 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 }
}

View File

@@ -17,6 +17,7 @@
import cpp
import PrintfLike
private import semmle.code.cpp.ir.dataflow.ResolveCall
bindingset[index]
private string toCause(Function func, int index) {
@@ -36,9 +37,9 @@ private predicate wrapperFunctionStep(
not target.isVirtual() and
not source.isVirtual() and
source.hasDefinition() and
exists(FunctionCall call, Expr arg, Parameter sourceParam |
exists(Call call, Expr arg, Parameter sourceParam |
// there is a 'call' to 'target' with argument 'arg' at index 'targetParamIndex'
target = call.getTarget() and
target = resolveCall(call) and
arg = call.getArgument(targetParamIndex) and
// 'call' is enclosed in 'source'
source = call.getEnclosingFunction() and
@@ -153,8 +154,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, FunctionCall call, int argIndex |
targetFunc = call.getTarget() and
exists(Function targetFunc, Call call, int argIndex |
targetFunc = resolveCall(call) and
this.wrapperFunction(targetFunc, argIndex, callChain) and
(
exists(Function sourceFunc | sourceFunc = call.getEnclosingFunction() |

View File

@@ -53,12 +53,44 @@
private import cpp
private import semmle.code.cpp.ir.dataflow.internal.ProductFlow
private import semmle.code.cpp.security.ProductFlowUtils.ProductFlowUtils
private import semmle.code.cpp.ir.ValueNumbering
private import semmle.code.cpp.controlflow.IRGuards
private import codeql.util.Unit
private import semmle.code.cpp.rangeanalysis.new.RangeAnalysisUtil
private VariableAccess getAVariableAccess(Expr e) { e.getAChild*() = result }
/**
* Gets a (sub)expression that may be the result of evaluating `size`.
*
* For example, `getASizeCandidate(a ? b : c)` gives `a ? b : c`, `b` and `c`.
*/
bindingset[size]
pragma[inline_late]
private Expr getASizeCandidate(Expr size) {
result = size
or
result = [size.(ConditionalExpr).getThen(), size.(ConditionalExpr).getElse()]
}
/**
* Holds if the `(n, state)` pair represents the source of flow for the size
* expression associated with `alloc`.
*/
predicate hasSize(HeuristicAllocationExpr alloc, DataFlow::Node n, int state) {
exists(VariableAccess va, Expr size, int delta, Expr s |
size = alloc.getSizeExpr() and
s = getASizeCandidate(size) and
// Get the unique variable in a size expression like `x` in `malloc(x + 1)`.
va = unique( | | getAVariableAccess(s)) and
// Compute `delta` as the constant difference between `x` and `x + 1`.
bounded1(any(Instruction instr | instr.getUnconvertedResultExpression() = s),
any(LoadInstruction load | load.getUnconvertedResultExpression() = va), delta) and
n.asExpr() = va and
state = delta
)
}
/**
* Gets the virtual dispatch branching limit when calculating field flow while searching
* for flow from an allocation to the construction of an out-of-bounds pointer.
@@ -68,6 +100,125 @@ private import semmle.code.cpp.rangeanalysis.new.RangeAnalysisUtil
*/
int allocationToInvalidPointerFieldFlowBranchLimit() { result = 0 }
/**
* A module that encapsulates a barrier guard to remove false positives from flow like:
* ```cpp
* char *p = new char[size];
* // ...
* unsigned n = size;
* // ...
* if(n < size) {
* use(*p[n]);
* }
* ```
* In this case, the sink pair identified by the product flow library (without any additional barriers)
* would be `(p, n)` (where `n` is the `n` in `p[n]`), because there exists a pointer-arithmetic
* instruction `pai = a + b` such that:
* 1. the allocation flows to `a`, and
* 2. `b <= n` where `n` is the `n` in `p[n]`
* but because there's a strict comparison that compares `n` against the size of the allocation this
* snippet is fine.
*/
private module SizeBarrier {
private module SizeBarrierConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
// The sources is the same as in the sources for the second
// projection in the `AllocToInvalidPointerConfig` module.
hasSize(_, source, _) and
InterestingPointerAddInstruction::isInterestingSize(source)
}
int fieldFlowBranchLimit() { result = allocationToInvalidPointerFieldFlowBranchLimit() }
/**
* Holds if `small <= large + k` holds if `g` evaluates to `testIsTrue`.
*/
additional predicate isSink(
DataFlow::Node small, DataFlow::Node large, IRGuardCondition g, int k, boolean testIsTrue
) {
// The sink is any "large" side of a relational comparison. i.e., the `large` expression
// in a guard such as `small <= large + k`.
g.comparesLt(small.asOperand(), large.asOperand(), k + 1, true, testIsTrue)
}
predicate isSink(DataFlow::Node sink) { isSink(_, sink, _, _, _) }
}
module SizeBarrierFlow = DataFlow::Global<SizeBarrierConfig>;
private int getASizeAddend(DataFlow::Node node) {
exists(DataFlow::Node source |
SizeBarrierFlow::flow(source, node) and
hasSize(_, source, result)
)
}
/**
* Holds if `small <= large + k` holds if `g` evaluates to `edge`.
*/
private predicate operandGuardChecks(
IRGuardCondition g, Operand small, DataFlow::Node large, int k, boolean edge
) {
SizeBarrierFlow::flowTo(large) and
SizeBarrierConfig::isSink(DataFlow::operandNode(small), large, g, k, edge)
}
/**
* Gets an instruction `instr` that is guarded by a check such as `instr <= small + delta` where
* `small <= _ + k` and `small` is the "small side" of of a relational comparison that checks
* whether `small <= size` where `size` is the size of an allocation.
*/
Instruction getABarrierInstruction0(int delta, int k) {
exists(
IRGuardCondition g, ValueNumber value, Operand small, boolean edge, DataFlow::Node large
|
// We know:
// 1. result <= value + delta (by `bounded`)
// 2. value <= large + k (by `operandGuardChecks`).
// So:
// result <= value + delta (by 1.)
// <= large + k + delta (by 2.)
small = value.getAUse() and
operandGuardChecks(pragma[only_bind_into](g), pragma[only_bind_into](small), large,
pragma[only_bind_into](k), pragma[only_bind_into](edge)) and
bounded(result, value.getAnInstruction(), delta) and
g.controls(result.getBlock(), edge) and
k < getASizeAddend(large)
)
}
/**
* Gets an instruction that is guarded by a guard condition which ensures that
* the value of the instruction is upper-bounded by size of some allocation.
*/
bindingset[state]
pragma[inline_late]
Instruction getABarrierInstruction(int state) {
exists(int delta, int k |
state > k + delta and
// result <= "size of allocation" + delta + k
// < "size of allocation" + state
result = getABarrierInstruction0(delta, k)
)
}
/**
* Gets a `DataFlow::Node` that is guarded by a guard condition which ensures that
* the value of the node is upper-bounded by size of some allocation.
*/
DataFlow::Node getABarrierNode(int state) {
exists(DataFlow::Node source, int delta, int k |
SizeBarrierFlow::flow(source, result) and
hasSize(_, source, state) and
result.asInstruction() = SizeBarrier::getABarrierInstruction0(delta, k) and
state > k + delta
// so now we have:
// result <= "size of allocation" + delta + k
// < "size of allocation" + state
)
}
}
private module InterestingPointerAddInstruction {
private module PointerAddInstructionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
@@ -76,7 +227,7 @@ private module InterestingPointerAddInstruction {
hasSize(source.asExpr(), _, _)
}
predicate fieldFlowBranchLimit = allocationToInvalidPointerFieldFlowBranchLimit/0;
int fieldFlowBranchLimit() { result = allocationToInvalidPointerFieldFlowBranchLimit() }
predicate isSink(DataFlow::Node sink) {
sink.asInstruction() = any(PointerAddInstruction pai).getLeft()
@@ -112,17 +263,6 @@ private module InterestingPointerAddInstruction {
}
}
private module SizeBarrierInput implements SizeBarrierInputSig {
predicate fieldFlowBranchLimit = allocationToInvalidPointerFieldFlowBranchLimit/0;
predicate isSource(DataFlow::Node source) {
// The sources is the same as in the sources for the second
// projection in the `AllocToInvalidPointerConfig` module.
hasSize(_, source, _) and
InterestingPointerAddInstruction::isInterestingSize(source)
}
}
/**
* A product-flow configuration for flow from an `(allocation, size)` pair to a
* pointer-arithmetic operation `pai` such that `pai <= allocation + size`.
@@ -161,7 +301,7 @@ private module Config implements ProductFlow::StateConfigSig {
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
predicate isBarrier2(DataFlow::Node node, FlowState2 state) {
node = SizeBarrier<SizeBarrierInput>::getABarrierNode(state)
node = SizeBarrier::getABarrierNode(state)
}
predicate isBarrier2(DataFlow::Node node) {
@@ -217,8 +357,8 @@ private predicate pointerAddInstructionHasBounds0(
sizeInstr = sizeSink.asInstruction() and
// pai.getRight() <= sizeSink + delta
bounded1(right, sizeInstr, delta) and
not right = SizeBarrier<SizeBarrierInput>::getABarrierInstruction(delta) and
not sizeInstr = SizeBarrier<SizeBarrierInput>::getABarrierInstruction(delta)
not right = SizeBarrier::getABarrierInstruction(delta) and
not sizeInstr = SizeBarrier::getABarrierInstruction(delta)
)
}

View File

@@ -1,167 +0,0 @@
/**
* This file provides the `SizeBarrier` module which provides barriers for
* both the `cpp/invalid-pointer-deref` query and the `cpp/overrun-write`
* query.
*/
private import cpp
private import semmle.code.cpp.dataflow.new.DataFlow
private import semmle.code.cpp.ir.ValueNumbering
private import semmle.code.cpp.controlflow.IRGuards
private import semmle.code.cpp.rangeanalysis.new.RangeAnalysisUtil
private VariableAccess getAVariableAccess(Expr e) { e.getAChild*() = result }
/**
* Gets a (sub)expression that may be the result of evaluating `size`.
*
* For example, `getASizeCandidate(a ? b : c)` gives `a ? b : c`, `b` and `c`.
*/
bindingset[size]
pragma[inline_late]
private Expr getASizeCandidate(Expr size) {
result = size
or
result = [size.(ConditionalExpr).getThen(), size.(ConditionalExpr).getElse()]
}
/**
* Holds if the `(n, state)` pair represents the source of flow for the size
* expression associated with `alloc`.
*/
predicate hasSize(HeuristicAllocationExpr alloc, DataFlow::Node n, int state) {
exists(VariableAccess va, Expr size, int delta, Expr s |
size = alloc.getSizeExpr() and
s = getASizeCandidate(size) and
// Get the unique variable in a size expression like `x` in `malloc(x + 1)`.
va = unique( | | getAVariableAccess(s)) and
// Compute `delta` as the constant difference between `x` and `x + 1`.
bounded1(any(Instruction instr | instr.getUnconvertedResultExpression() = s),
any(LoadInstruction load | load.getUnconvertedResultExpression() = va), delta) and
n.asExpr() = va and
state = delta
)
}
/** Provides the input specification of the `SizeBarrier` module. */
signature module SizeBarrierInputSig {
/** Gets the virtual dispatch branching limit when calculating field flow. */
int fieldFlowBranchLimit();
/** Holds if `source` is a relevant data flow source. */
predicate isSource(DataFlow::Node source);
}
/**
* A module that encapsulates a barrier guard to remove false positives from flow like:
* ```cpp
* char *p = new char[size];
* // ...
* unsigned n = size;
* // ...
* if(n < size) {
* use(*p[n]);
* }
* ```
* In this case, the sink pair identified by the product flow library (without any additional barriers)
* would be `(p, n)` (where `n` is the `n` in `p[n]`), because there exists a pointer-arithmetic
* instruction `pai = a + b` such that:
* 1. the allocation flows to `a`, and
* 2. `b <= n` where `n` is the `n` in `p[n]`
* but because there's a strict comparison that compares `n` against the size of the allocation this
* snippet is fine.
*/
module SizeBarrier<SizeBarrierInputSig Input> {
private module SizeBarrierConfig implements DataFlow::ConfigSig {
predicate isSource = Input::isSource/1;
predicate fieldFlowBranchLimit = Input::fieldFlowBranchLimit/0;
/**
* Holds if `small <= large + k` holds if `g` evaluates to `testIsTrue`.
*/
additional predicate isSink(
DataFlow::Node small, DataFlow::Node large, IRGuardCondition g, int k, boolean testIsTrue
) {
// The sink is any "large" side of a relational comparison. i.e., the `large` expression
// in a guard such as `small <= large + k`.
g.comparesLt(small.asOperand(), large.asOperand(), k + 1, true, testIsTrue)
}
predicate isSink(DataFlow::Node sink) { isSink(_, sink, _, _, _) }
}
private module SizeBarrierFlow = DataFlow::Global<SizeBarrierConfig>;
private int getASizeAddend(DataFlow::Node node) {
exists(DataFlow::Node source |
SizeBarrierFlow::flow(source, node) and
hasSize(_, source, result)
)
}
/**
* Holds if `small <= large + k` holds if `g` evaluates to `edge`.
*/
private predicate operandGuardChecks(
IRGuardCondition g, Operand small, DataFlow::Node large, int k, boolean edge
) {
SizeBarrierFlow::flowTo(large) and
SizeBarrierConfig::isSink(DataFlow::operandNode(small), large, g, k, edge)
}
/**
* Gets an instruction `instr` that is guarded by a check such as `instr <= small + delta` where
* `small <= _ + k` and `small` is the "small side" of a relational comparison that checks
* whether `small <= size` where `size` is the size of an allocation.
*/
private Instruction getABarrierInstruction0(int delta, int k) {
exists(
IRGuardCondition g, ValueNumber value, Operand small, boolean edge, DataFlow::Node large
|
// We know:
// 1. result <= value + delta (by `bounded`)
// 2. value <= large + k (by `operandGuardChecks`).
// So:
// result <= value + delta (by 1.)
// <= large + k + delta (by 2.)
small = value.getAUse() and
operandGuardChecks(pragma[only_bind_into](g), pragma[only_bind_into](small), large,
pragma[only_bind_into](k), pragma[only_bind_into](edge)) and
bounded(result, value.getAnInstruction(), delta) and
g.controls(result.getBlock(), edge) and
k < getASizeAddend(large)
)
}
/**
* Gets an instruction that is guarded by a guard condition which ensures that
* the value of the instruction is upper-bounded by size of some allocation.
*/
bindingset[state]
pragma[inline_late]
Instruction getABarrierInstruction(int state) {
exists(int delta, int k |
state > k + delta and
// result <= "size of allocation" + delta + k
// < "size of allocation" + state
result = getABarrierInstruction0(delta, k)
)
}
/**
* Gets a `DataFlow::Node` that is guarded by a guard condition which ensures that
* the value of the node is upper-bounded by size of some allocation.
*/
DataFlow::Node getABarrierNode(int state) {
exists(DataFlow::Node source, int delta, int k |
SizeBarrierFlow::flow(source, result) and
hasSize(_, source, state) and
result.asInstruction() = getABarrierInstruction0(delta, k) and
state > k + delta
// so now we have:
// result <= "size of allocation" + delta + k
// < "size of allocation" + state
)
}
}

View File

@@ -217,6 +217,33 @@ diagnostics(
/*- C++ dbscheme -*/
/**
* Information about packages that provide code used during compilation.
* The `id` is just a unique identifier.
* The `namespace` is typically the name of the package manager that
* provided the package (e.g. "dpkg" or "yum").
* The `package_name` is the name of the package, and `version` is its
* version (as a string).
*/
external_packages(
unique int id: @external_package,
string namespace : string ref,
string package_name : string ref,
string version : string ref
);
/**
* Holds if File `fileid` was provided by package `package`.
*/
header_to_external_package(
int fileid : @file ref,
int package : @external_package ref
);
/*
* C++ dbscheme
*/
extractor_version(
string codeql_version: string ref,
string frontend_version: string ref
@@ -282,17 +309,18 @@ macro_argument_expanded(
string text: string ref
);
/*
case @function.kind of
0 = @unknown_function
| 1 = @normal_function
1 = @normal_function
| 2 = @constructor
| 3 = @destructor
| 4 = @conversion_function
| 5 = @operator
// ... 6 = @builtin_function deprecated // GCC built-in functions, e.g. __builtin___memcpy_chk
| 6 = @builtin_function // GCC built-in functions, e.g. __builtin___memcpy_chk
| 7 = @user_defined_literal
| 8 = @deduction_guide
;
*/
functions(
unique int id: @function,
@@ -300,10 +328,6 @@ functions(
int kind: int ref
);
builtin_functions(
int id: @function ref
)
function_entry_point(
int id: @function ref,
unique int entry_point: @stmt ref
@@ -712,8 +736,9 @@ decltypes(
boolean parentheses_would_change_meaning: boolean ref
);
/*
case @type_operator.kind of
0 = @typeof // The frontend does not differentiate between typeof and typeof_unqual
| 0 = @typeof // The frontend does not differentiate between typeof and typeof_unqual
| 1 = @underlying_type
| 2 = @bases
| 3 = @direct_bases
@@ -734,6 +759,7 @@ case @type_operator.kind of
| 18 = @remove_volatile
| 19 = @remove_reference
;
*/
type_operators(
unique int id: @type_operator,
@@ -742,8 +768,9 @@ type_operators(
int base_type: @type ref
)
/*
case @usertype.kind of
0 = @unknown_usertype
| 0 = @unknown_usertype
| 1 = @struct
| 2 = @class
| 3 = @union
@@ -763,6 +790,7 @@ case @usertype.kind of
| 17 = @template_union
| 18 = @alias
;
*/
usertypes(
unique int id: @usertype,

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +0,0 @@
class Function extends @function {
string toString() { none() }
}
from Function f
where functions(f, _, 6)
select f

View File

@@ -1,9 +0,0 @@
class Function extends @function {
string toString() { none() }
}
from Function f, string n, int k, int new_k
where
functions(f, n, k) and
if k = 6 then new_k = 1 else new_k = k
select f, n, new_k

View File

@@ -1,4 +0,0 @@
description: Move builtin function identification to its own table
compatibility: full
functions.rel: run functions.qlo
builtin_functions.rel: run builtin_functions.qlo

View File

@@ -1,2 +0,0 @@
description: Uncomment cases in dbscheme
compatibility: full

View File

@@ -1,4 +0,0 @@
description: Remove unused external_package tables from the dbscheme
compatibility: full
external_packages.rel: delete
header_to_external_package.rel: delete

View File

@@ -1,21 +1,8 @@
## 1.4.4
### Minor Analysis Improvements
* 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.
* Added flow models for the Win32 API functions `CreateThread`, `CreateRemoteThread`, and `CreateRemoteThreadEx`.
* Improved support for dataflow through function objects and lambda expressions.
* Added flow models for `pthread_create` and `std::thread`.
* The `cpp/incorrect-string-type-conversion` query no longer alerts on incorrect type conversions that occur in unreachable code.
* Added flow models for the GNU C Library.
* Fixed a number of false positives and false negatives in `cpp/global-use-before-init`. Note that this query is not part of any of the default query suites.
* The query `cpp/sql-injection` now can be extended using the `sql-injection` Models as Data (MaD) sink kind.
## 1.4.3
### Minor Analysis Improvements
* 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.
* 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.
## 1.4.2
@@ -25,7 +12,7 @@ No user-facing changes.
### Minor Analysis Improvements
* Added flow models for the `SQLite` and `OpenSSL` libraries. This may result in more alerts when running queries on codebases that use these libraries.
* Added flow model for the `SQLite` and `OpenSSL` libraries. This may result in more alerts when running queries on codebases that use these libraries.
## 1.4.0

View File

@@ -21,29 +21,13 @@ predicate initFunc(GlobalVariable v, Function f) {
)
}
/** Holds if `v` has an initializer in function `f` that dominates `node`. */
predicate dominatingInitInFunc(GlobalVariable v, Function f, ControlFlowNode node) {
exists(VariableAccess initAccess |
v.getAnAccess() = initAccess and
initAccess.isUsedAsLValue() and
initAccess.getEnclosingFunction() = f and
dominates(initAccess, node)
)
}
predicate safeAccess(VariableAccess access) {
// it is safe if the variable access is part of a `sizeof` expression
exists(SizeofExprOperator e | e.getAChild*() = access)
}
predicate useFunc(GlobalVariable v, Function f) {
exists(VariableAccess access |
v.getAnAccess() = access and
access.isRValue() and
access.getEnclosingFunction() = f and
not safeAccess(access) and
not dominatingInitInFunc(v, f, access)
)
access.getEnclosingFunction() = f
) and
not initFunc(v, f)
}
predicate uninitialisedBefore(GlobalVariable v, Function f) {
@@ -54,14 +38,12 @@ predicate uninitialisedBefore(GlobalVariable v, Function f) {
exists(Call call, Function g |
uninitialisedBefore(v, g) and
call.getEnclosingFunction() = g and
(not functionInitialises(g, v) or locallyUninitialisedAt(v, call)) and
(not functionInitialises(f, v) or locallyUninitialisedAt(v, call)) and
resolvedCall(call, f)
)
}
predicate functionInitialises(Function f, GlobalVariable v) {
initFunc(v, f)
or
exists(Call call |
call.getEnclosingFunction() = f and
initialisedBy(v, call)
@@ -78,8 +60,7 @@ predicate locallyUninitialisedAt(GlobalVariable v, Call call) {
exists(Call mid |
locallyUninitialisedAt(v, mid) and not initialisedBy(v, mid) and callPair(mid, call)
)
) and
not dominatingInitInFunc(v, call.getEnclosingFunction(), call)
)
}
predicate initialisedBy(GlobalVariable v, Call call) {

View File

@@ -49,16 +49,21 @@ 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:
<i>1. It may be possible to generalize some of the utility functions beyond the
<ul>
<li>
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.
</li>
2. It's usually impossible for the class author to know every possible
<li>
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.
</i>
</li>
</ul>
To refactor a class like this, simply move its utility functions elsewhere,
paring its public interface down to the bare minimum.

View File

@@ -46,17 +46,21 @@ need to be part of the class. (A classic example of this is the
<code>std::string</code> class in the C++ Standard Library.) As [Sutter]
observes, there are at least two key problems with this approach:
<i>
1. It may be possible to generalize some of the utility functions beyond the
<ul>
<li>
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.
</li>
2. It's usually impossible for the class author to know every possible
<li>
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.
</i>
</li>
</ul>
To refactor a class like this, simply move its utility functions elsewhere,
paring its public interface down to the bare minimum.

View File

@@ -26,6 +26,12 @@ private newtype LibraryT =
LibraryTElement(LibraryElement lib, string name, string version) {
lib.getName() = name and
lib.getVersion() = version
} or
LibraryTExternalPackage(@external_package ep, string name, string version) {
exists(string package_name |
external_packages(ep, _, package_name, version) and
name = package_name
)
}
/**
@@ -35,7 +41,10 @@ class Library extends LibraryT {
string name;
string version;
Library() { this = LibraryTElement(_, name, version) }
Library() {
this = LibraryTElement(_, name, version) or
this = LibraryTExternalPackage(_, name, version)
}
string getName() { result = name }
@@ -54,6 +63,11 @@ class Library extends LibraryT {
this = LibraryTElement(lib, _, _) and
result = lib.getAFile()
)
or
exists(@external_package ep |
this = LibraryTExternalPackage(ep, _, _) and
header_to_external_package(unresolveElement(result), ep)
)
}
}

View File

@@ -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.asIndirectExpr()
call.getArgument(processOperationArg) = [arg.asExpr(), arg.asIndirectExpr()]
)
}

View File

@@ -20,7 +20,6 @@ import semmle.code.cpp.models.interfaces.Allocation
import semmle.code.cpp.models.interfaces.ArrayFunction
import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysis
import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExprSpecific
import semmle.code.cpp.security.ProductFlowUtils.ProductFlowUtils
import semmle.code.cpp.rangeanalysis.new.RangeAnalysisUtil
import StringSizeFlow::PathGraph1
import codeql.util.Unit
@@ -44,28 +43,20 @@ predicate hasSize(HeuristicAllocationExpr alloc, DataFlow::Node n, int state) {
)
}
/**
* Holds if `c` a call to an `ArrayFunction` with buffer argument `bufSink`,
* and a size argument `sizeInstr` which satisfies `sizeInstr <= sizeBound + delta`.
*
* Furthermore, the `sizeSink` node is the dataflow node corresponding to
* `sizeBound`, and the expression `eBuf` is the expression corresponding
* to `bufInstr`.
*/
predicate isSinkPairImpl0(
CallInstruction c, DataFlow::Node bufSink, DataFlow::Node sizeSink, int delta, Expr eBuf,
Instruction sizeBound, Instruction sizeInstr
predicate isSinkPairImpl(
CallInstruction c, DataFlow::Node bufSink, DataFlow::Node sizeSink, int delta, Expr eBuf
) {
exists(int bufIndex, int sizeIndex, Instruction bufInstr, ArrayFunction func |
exists(
int bufIndex, int sizeIndex, Instruction sizeInstr, Instruction bufInstr, ArrayFunction func
|
bufInstr = bufSink.asInstruction() and
c.getArgument(bufIndex) = bufInstr and
sizeBound = sizeSink.asInstruction() and
c.getArgument(sizeIndex) = sizeInstr and
sizeInstr = sizeSink.asInstruction() and
c.getStaticCallTarget() = func and
pragma[only_bind_into](func)
.hasArrayWithVariableSize(pragma[only_bind_into](bufIndex),
pragma[only_bind_into](sizeIndex)) and
bounded(sizeInstr, sizeBound, delta) and
bounded(c.getArgument(sizeIndex), sizeInstr, delta) and
eBuf = bufInstr.getUnconvertedResultExpression()
)
}
@@ -95,39 +86,99 @@ module ValidState {
private module ValidStateConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { hasSize(_, source, _) }
predicate isSink(DataFlow::Node sink) { isSinkPairImpl0(_, _, sink, _, _, _, _) }
predicate isSink(DataFlow::Node sink) { isSinkPairImpl(_, _, sink, _, _) }
predicate isBarrierOut(DataFlow::Node node) { DataFlow::flowsToBackEdge(node) }
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
isAdditionalFlowStep2(node1, node2, _)
}
predicate includeHiddenNodes() { any() }
}
private import DataFlow::Global<ValidStateConfig>
predicate validState(DataFlow::Node source, DataFlow::Node sink, int value) {
hasSize(_, source, value) and
flow(source, sink)
private predicate inLoop(PathNode n) { n.getASuccessor+() = n }
/**
* Holds if `value` is a possible offset for `n`.
*
* To ensure termination, we limit `value` to be in the
* range `[-2, 2]` if the node is part of a loop. Without
* this restriction we wouldn't terminate on an example like:
* ```cpp
* while(unknown()) { size++; }
* ```
*/
private predicate validStateImpl(PathNode n, int value) {
// If the dataflow node depends recursively on itself we restrict the range.
(inLoop(n) implies value = [-2 .. 2]) and
(
// For the dataflow source we have an allocation such as `malloc(size + k)`,
// and the value of the flow-state is then `k`.
hasSize(_, n.getNode(), value)
or
// For a dataflow sink any `value` that is strictly smaller than the delta
// needs to be a valid flow-state. That is, for a snippet like:
// ```
// p = b ? new char[size] : new char[size + 1];
// memset(p, 0, size + 2);
// ```
// the valid flow-states at the `memset` must include the set `{0, 1}` since the
// flow-state at `new char[size]` is `0`, and the flow-state at `new char[size + 1]`
// is `1`.
//
// So we find a valid flow-state at the sink's predecessor, and use the definition
// of our sink predicate to compute the valid flow-states at the sink.
exists(int delta, PathNode n0 |
n0.getASuccessor() = n and
validStateImpl(n0, value) and
isSinkPairImpl(_, _, n.getNode(), delta, _) and
delta > value
)
or
// For a non-source and non-sink node there is two cases to consider.
// 1. A node where we have to update the flow-state, or
// 2. A node that doesn't update the flow-state.
//
// For case 1, we compute the new flow-state by adding the constant operand of the
// `AddInstruction` to the flow-state of any predecessor node.
// For case 2 we simply propagate the valid flow-states from the predecessor node to
// the next one.
exists(PathNode n0, DataFlow::Node node0, DataFlow::Node node, int value0 |
n0.getASuccessor() = n and
validStateImpl(n0, value0) and
node = n.getNode() and
node0 = n0.getNode()
|
exists(int delta |
isAdditionalFlowStep2(node0, node, delta) and
value0 = value + delta
)
or
not isAdditionalFlowStep2(node0, node, _) and
value = value0
)
)
}
predicate validState(DataFlow::Node n, int value) {
validStateImpl(any(PathNode pn | pn.getNode() = n), value)
}
}
import ValidState
module SizeBarrierInput implements SizeBarrierInputSig {
int fieldFlowBranchLimit() { result = 2 }
predicate isSource(DataFlow::Node source) {
exists(int state |
hasSize(_, source, state) and
validState(source, _, state)
)
}
}
predicate isSinkPairImpl(
CallInstruction c, DataFlow::Node bufSink, DataFlow::Node sizeSink, int delta, Expr eBuf
) {
exists(Instruction sizeBound, Instruction sizeInstr |
isSinkPairImpl0(c, bufSink, sizeSink, delta, eBuf, sizeBound, sizeInstr) and
not sizeBound = SizeBarrier<SizeBarrierInput>::getABarrierInstruction(delta) and
not sizeInstr = SizeBarrier<SizeBarrierInput>::getABarrierInstruction(delta)
/**
* Holds if `node2` is a dataflow node that represents an addition of two operands `op1`
* and `op2` such that:
* 1. `node1` is the dataflow node that represents `op1`, and
* 2. the value of `op2` can be upper bounded by `delta.`
*/
predicate isAdditionalFlowStep2(DataFlow::Node node1, DataFlow::Node node2, int delta) {
exists(AddInstruction add, Operand op |
add.hasOperands(node1.asOperand(), op) and
semBounded(getSemanticExpr(op.getDef()), any(SemZeroBound zero), delta, true, _) and
node2.asInstruction() = add
)
}
@@ -147,14 +198,14 @@ module StringSizeConfig implements ProductFlow::StateConfigSig {
// to the size of the allocation. This state is then checked in `isSinkPair`.
exists(state1) and
hasSize(bufSource.asExpr(), sizeSource, state2) and
validState(sizeSource, _, state2)
validState(sizeSource, state2)
}
predicate isSinkPair(
DataFlow::Node bufSink, FlowState1 state1, DataFlow::Node sizeSink, FlowState2 state2
) {
exists(state1) and
validState(_, sizeSink, state2) and
validState(sizeSink, state2) and
exists(int delta |
isSinkPairImpl(_, bufSink, sizeSink, delta, _) and
delta > state2
@@ -163,8 +214,14 @@ module StringSizeConfig implements ProductFlow::StateConfigSig {
predicate isBarrierOut2(DataFlow::Node node) { DataFlow::flowsToBackEdge(node) }
predicate isBarrier2(DataFlow::Node node, FlowState2 state) {
node = SizeBarrier<SizeBarrierInput>::getABarrierNode(state)
predicate isAdditionalFlowStep2(
DataFlow::Node node1, FlowState2 state1, DataFlow::Node node2, FlowState2 state2
) {
validState(node2, state2) and
exists(int delta |
isAdditionalFlowStep2(node1, node2, delta) and
state1 = state2 + delta
)
}
}

View File

@@ -14,7 +14,6 @@
import cpp
import semmle.code.cpp.controlflow.Guards
import semmle.code.cpp.ir.IR
class WideCharPointerType extends PointerType {
WideCharPointerType() { this.getBaseType() instanceof WideCharType }
@@ -109,9 +108,7 @@ 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) and
// Avoid cases in unreachable blocks.
any(EnterFunctionInstruction e).getASuccessor+().getAst() = e1
not isLikelyDynamicallyChecked(e1)
select e1,
"Conversion from " + e1.getType().toString() + " to " + e2.getType().toString() +
". Use of invalid string can lead to undefined behavior."

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The query `cpp/sql-injection` now can be extended using the `sql-injection` Models as Data (MaD) sink kind.

View File

@@ -2,4 +2,4 @@
### Minor Analysis Improvements
* Added flow models for the `SQLite` and `OpenSSL` libraries. This may result in more alerts when running queries on codebases that use these libraries.
* Added flow model for the `SQLite` and `OpenSSL` libraries. This may result in more alerts when running queries on codebases that use these libraries.

View File

@@ -2,4 +2,4 @@
### Minor Analysis Improvements
* 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.
* 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.

View File

@@ -1,12 +0,0 @@
## 1.4.4
### Minor Analysis Improvements
* 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.
* Added flow models for the Win32 API functions `CreateThread`, `CreateRemoteThread`, and `CreateRemoteThreadEx`.
* Improved support for dataflow through function objects and lambda expressions.
* Added flow models for `pthread_create` and `std::thread`.
* The `cpp/incorrect-string-type-conversion` query no longer alerts on incorrect type conversions that occur in unreachable code.
* Added flow models for the GNU C Library.
* Fixed a number of false positives and false negatives in `cpp/global-use-before-init`. Note that this query is not part of any of the default query suites.
* The query `cpp/sql-injection` now can be extended using the `sql-injection` Models as Data (MaD) sink kind.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.4.4
lastReleaseVersion: 1.4.3

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 1.4.5-dev
version: 1.4.4-dev
groups:
- cpp
- queries

View File

@@ -37,21 +37,4 @@ void test_aggregate_literal() {
int xs[] = {1, 2, 3}; // $ asExpr=1 asExpr=2 asExpr=3 asExpr={...}
const int ys[] = {[0] = 4, [1] = 5, [0] = 6}; // $ asExpr=4 asExpr=5 asExpr=6 asExpr={...}
}
void test_postfix_crement(int *p, int q) {
p++; // $ asExpr="... ++" asIndirectExpr="... ++" asExpr=p asIndirectExpr=p
q++; // $ asExpr="... ++" asExpr=q
(p++); // $ asExpr="... ++" asIndirectExpr="... ++" asExpr="p(... ++)" asIndirectExpr="p(*... ++)"
(q++); // $ asExpr="... ++" asExpr="q(... ++)"
(void)(p++); // $ asExpr="p(... ++)" asIndirectExpr="p(*... ++)"
(void)(q++); // $ asExpr="q(... ++)"
(void)p++; // $ asExpr="p(... ++)" asIndirectExpr="p(*... ++)"
(void)q++; // $ asExpr="q(... ++)"
int *p1 = p++; // $ asExpr="... ++" asIndirectExpr="... ++" asExpr="p(... ++)" asIndirectExpr="p(*... ++)"
int q1 = q++; // $ asExpr="... ++" asExpr="q(... ++)"
(int*)(p++); // $ asExpr="... ++" asIndirectExpr="... ++" asExpr="p(... ++)" asIndirectExpr="p(*... ++)"
(int)(q++); // $ asExpr="... ++" asExpr="q(... ++)"
int *p2 = (int*)(p++); // $ asExpr="... ++" asIndirectExpr="... ++" asExpr="p(... ++)" asIndirectExpr="p(*... ++)"
int q2 = (int)(q++); // $ asExpr="... ++" asExpr="q(... ++)"
}
}

View File

@@ -6,15 +6,9 @@ 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

View File

@@ -24,9 +24,10 @@ 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(DataFlow::Node n, int i | n.isFinalValueOfParameter(_, i) | i)] and
k = [0 .. max(FinalParameterNode n | | n.getIndirectionIndex())] and
(if k = 0 then result = "" else result = "*" + stars(k - 1))
}
@@ -34,14 +35,14 @@ module IRTest {
string getARelevantTag() { result = "ir-def" }
predicate hasActualResult(Location location, string element, string tag, string value) {
exists(Function f, Parameter p, DataFlow::Node n, int i |
exists(Function f, Parameter p, FinalParameterNode n |
p.isNamed() and
n.isFinalValueOfParameter(p, i) and
n.getParameter() = p and
n.getFunction() = f and
location = f.getLocation() and
element = p.toString() and
tag = "ir-def" and
value = stars(i) + p.getName()
value = stars(n.getIndirectionIndex()) + p.getName()
)
}
}

View File

@@ -1153,6 +1153,4 @@ namespace conflation_regression {
*p = source(0);
read_deref_deref(p);
}
}
int recursion = (sink(recursion), source()); // clean
}

View File

@@ -17,18 +17,13 @@ models
| 16 | Source: ; ; false; ymlSource; ; ; ReturnValue; local; manual |
| 17 | Source: boost::asio; ; false; read_until; ; ; Argument[*1]; remote; manual |
| 18 | Summary: ; ; false; CommandLineToArgvA; ; ; Argument[*0]; ReturnValue[**]; taint; manual |
| 19 | Summary: ; ; false; CreateRemoteThread; ; ; Argument[@4]; Argument[3].Parameter[@0]; value; manual |
| 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; 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 |
| 19 | Summary: ; ; false; ReadFileEx; ; ; Argument[*3].Field[@hEvent]; Argument[4].Parameter[*2].Field[@hEvent]; value; manual |
| 20 | Summary: ; ; false; ymlStepGenerated; ; ; Argument[0]; ReturnValue; taint; df-generated |
| 21 | Summary: ; ; false; ymlStepManual; ; ; Argument[0]; ReturnValue; taint; manual |
| 22 | Summary: ; ; false; ymlStepManual_with_body; ; ; Argument[0]; ReturnValue; taint; manual |
| 23 | 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:28 |
| 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:23 |
| 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 |
@@ -37,10 +32,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: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 |
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:23 |
| 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:21 |
| 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:20 |
| 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:22 |
| 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 |
@@ -52,49 +47,19 @@ 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:26 |
| test.cpp:17:24:17:24 | x | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | MaD:21 |
| 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:25 |
| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | MaD:20 |
| 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:27 |
| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | MaD:22 |
| 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 | |
@@ -108,8 +73,8 @@ edges
| windows.cpp:39:36:39:38 | GetEnvironmentVariableA output argument | windows.cpp:41:10:41:13 | * ... | provenance | Src:MaD:5 |
| windows.cpp:90:6:90:15 | [summary param] *3 in ReadFileEx [*hEvent] | windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[*hEvent] in ReadFileEx | provenance | |
| windows.cpp:90:6:90:15 | [summary param] *3 in ReadFileEx [hEvent] | windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[hEvent] in ReadFileEx | provenance | |
| windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[*hEvent] in ReadFileEx | windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[*hEvent] in ReadFileEx | provenance | MaD:22 |
| windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[hEvent] in ReadFileEx | windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[hEvent] in ReadFileEx | provenance | MaD:22 |
| windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[*hEvent] in ReadFileEx | windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[*hEvent] in ReadFileEx | provenance | MaD:19 |
| windows.cpp:90:6:90:15 | [summary] read: Argument[*3].Field[hEvent] in ReadFileEx | windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[hEvent] in ReadFileEx | provenance | MaD:19 |
| windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2] in ReadFileEx [*hEvent] | windows.cpp:147:16:147:27 | *lpOverlapped [*hEvent] | provenance | |
| windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2] in ReadFileEx [hEvent] | windows.cpp:157:16:157:27 | *lpOverlapped [hEvent] | provenance | |
| windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2].Field[*hEvent] in ReadFileEx | windows.cpp:90:6:90:15 | [summary] to write: Argument[4].Parameter[*2] in ReadFileEx [*hEvent] | provenance | |
@@ -157,29 +122,6 @@ edges
| windows.cpp:332:23:332:40 | *call to MapViewOfFileNuma2 | windows.cpp:332:23:332:40 | *call to MapViewOfFileNuma2 | provenance | Src:MaD:12 |
| windows.cpp:332:23:332:40 | *call to MapViewOfFileNuma2 | windows.cpp:333:20:333:52 | *pMapView | provenance | |
| windows.cpp:333:20:333:52 | *pMapView | windows.cpp:335:10:335:16 | * ... | provenance | |
| windows.cpp:349:8:349:19 | [summary param] *3 in CreateThread [x] | windows.cpp:349:8:349:19 | [summary] to write: Argument[2].Parameter[*0] in CreateThread [x] | provenance | MaD:21 |
| windows.cpp:349:8:349:19 | [summary] to write: Argument[2].Parameter[*0] in CreateThread [x] | windows.cpp:403:26:403:36 | *lpParameter [x] | provenance | |
| windows.cpp:357:8:357:25 | [summary param] *4 in CreateRemoteThread [x] | windows.cpp:357:8:357:25 | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThread [x] | provenance | MaD:19 |
| windows.cpp:357:8:357:25 | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThread [x] | windows.cpp:410:26:410:36 | *lpParameter [x] | provenance | |
| windows.cpp:387:8:387:27 | [summary param] *4 in CreateRemoteThreadEx [x] | windows.cpp:387:8:387:27 | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThreadEx [x] | provenance | MaD:20 |
| windows.cpp:387:8:387:27 | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThreadEx [x] | windows.cpp:417:26:417:36 | *lpParameter [x] | provenance | |
| windows.cpp:403:26:403:36 | *lpParameter [x] | windows.cpp:405:10:405:25 | *lpParameter [x] | provenance | |
| windows.cpp:405:10:405:25 | *lpParameter [x] | windows.cpp:406:8:406:8 | *s [x] | provenance | |
| windows.cpp:406:8:406:8 | *s [x] | windows.cpp:406:8:406:11 | x | provenance | |
| windows.cpp:410:26:410:36 | *lpParameter [x] | windows.cpp:412:10:412:25 | *lpParameter [x] | provenance | |
| windows.cpp:412:10:412:25 | *lpParameter [x] | windows.cpp:413:8:413:8 | *s [x] | provenance | |
| windows.cpp:413:8:413:8 | *s [x] | windows.cpp:413:8:413:11 | x | provenance | |
| windows.cpp:417:26:417:36 | *lpParameter [x] | windows.cpp:419:10:419:25 | *lpParameter [x] | provenance | |
| windows.cpp:419:10:419:25 | *lpParameter [x] | windows.cpp:420:8:420:8 | *s [x] | provenance | |
| windows.cpp:420:8:420:8 | *s [x] | windows.cpp:420:8:420:11 | x | provenance | |
| windows.cpp:431:3:431:3 | *s [post update] [x] | windows.cpp:439:7:439:8 | *& ... [x] | provenance | |
| windows.cpp:431:3:431:3 | *s [post update] [x] | windows.cpp:451:7:451:8 | *& ... [x] | provenance | |
| windows.cpp:431:3:431:3 | *s [post update] [x] | windows.cpp:464:7:464:8 | *& ... [x] | provenance | |
| windows.cpp:431:3:431:16 | ... = ... | windows.cpp:431:3:431:3 | *s [post update] [x] | provenance | |
| windows.cpp:431:9:431:14 | call to source | windows.cpp:431:3:431:16 | ... = ... | provenance | |
| windows.cpp:439:7:439:8 | *& ... [x] | windows.cpp:349:8:349:19 | [summary param] *3 in CreateThread [x] | provenance | |
| windows.cpp:451:7:451:8 | *& ... [x] | windows.cpp:357:8:357:25 | [summary param] *4 in CreateRemoteThread [x] | provenance | |
| windows.cpp:464:7:464:8 | *& ... [x] | windows.cpp:387:8:387:27 | [summary param] *4 in CreateRemoteThreadEx [x] | provenance | |
nodes
| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | semmle.label | [summary param] *0 in buffer |
| asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | semmle.label | [summary] to write: ReturnValue in buffer |
@@ -221,38 +163,6 @@ 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 |
@@ -328,30 +238,6 @@ nodes
| windows.cpp:332:23:332:40 | *call to MapViewOfFileNuma2 | semmle.label | *call to MapViewOfFileNuma2 |
| windows.cpp:333:20:333:52 | *pMapView | semmle.label | *pMapView |
| windows.cpp:335:10:335:16 | * ... | semmle.label | * ... |
| windows.cpp:349:8:349:19 | [summary param] *3 in CreateThread [x] | semmle.label | [summary param] *3 in CreateThread [x] |
| windows.cpp:349:8:349:19 | [summary] to write: Argument[2].Parameter[*0] in CreateThread [x] | semmle.label | [summary] to write: Argument[2].Parameter[*0] in CreateThread [x] |
| windows.cpp:357:8:357:25 | [summary param] *4 in CreateRemoteThread [x] | semmle.label | [summary param] *4 in CreateRemoteThread [x] |
| windows.cpp:357:8:357:25 | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThread [x] | semmle.label | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThread [x] |
| windows.cpp:387:8:387:27 | [summary param] *4 in CreateRemoteThreadEx [x] | semmle.label | [summary param] *4 in CreateRemoteThreadEx [x] |
| windows.cpp:387:8:387:27 | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThreadEx [x] | semmle.label | [summary] to write: Argument[3].Parameter[*0] in CreateRemoteThreadEx [x] |
| windows.cpp:403:26:403:36 | *lpParameter [x] | semmle.label | *lpParameter [x] |
| windows.cpp:405:10:405:25 | *lpParameter [x] | semmle.label | *lpParameter [x] |
| windows.cpp:406:8:406:8 | *s [x] | semmle.label | *s [x] |
| windows.cpp:406:8:406:11 | x | semmle.label | x |
| windows.cpp:410:26:410:36 | *lpParameter [x] | semmle.label | *lpParameter [x] |
| windows.cpp:412:10:412:25 | *lpParameter [x] | semmle.label | *lpParameter [x] |
| windows.cpp:413:8:413:8 | *s [x] | semmle.label | *s [x] |
| windows.cpp:413:8:413:11 | x | semmle.label | x |
| windows.cpp:417:26:417:36 | *lpParameter [x] | semmle.label | *lpParameter [x] |
| windows.cpp:419:10:419:25 | *lpParameter [x] | semmle.label | *lpParameter [x] |
| windows.cpp:420:8:420:8 | *s [x] | semmle.label | *s [x] |
| windows.cpp:420:8:420:11 | x | semmle.label | x |
| windows.cpp:431:3:431:3 | *s [post update] [x] | semmle.label | *s [post update] [x] |
| windows.cpp:431:3:431:16 | ... = ... | semmle.label | ... = ... |
| windows.cpp:431:9:431:14 | call to source | semmle.label | call to source |
| windows.cpp:439:7:439:8 | *& ... [x] | semmle.label | *& ... [x] |
| windows.cpp:451:7:451:8 | *& ... [x] | semmle.label | *& ... [x] |
| windows.cpp:464:7:464:8 | *& ... [x] | semmle.label | *& ... [x] |
subpaths
| asio_streams.cpp:100:64:100:71 | *send_str | 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 | asio_streams.cpp:100:44:100:62 | call to buffer |
| test.cpp:17:24:17:24 | x | test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | test.cpp:17:10:17:22 | call to ymlStepManual |

View File

@@ -16,5 +16,4 @@ 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"]
- ["", "", False, "callWithArgument", "", "", "Argument[1]", "Argument[0].Parameter[0]", "value", "manual"]
- ["", "", False, "ymlStepGenerated_with_body", "", "", "Argument[0]", "ReturnValue", "taint", "df-generated"]

View File

@@ -8,8 +8,3 @@
| 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 |

View File

@@ -1,7 +1,5 @@
| 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 |

View File

@@ -35,71 +35,3 @@ 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<typename F>
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);
}

Some files were not shown because too many files have changed in this diff Show More