Compare commits

..

1 Commits

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

5
.gitattributes vendored
View File

@@ -88,8 +88,3 @@
# swift prebuilt resources
/swift/third_party/resources/*.zip filter=lfs diff=lfs merge=lfs -text
/swift/third_party/resources/*.tar.zst filter=lfs diff=lfs merge=lfs -text
# This upgrade script must use windows line-endings to be compatible with old
# databases.
/powershell/ql/lib/upgrades/ce269c61feda10a8ca0d16519085f7e55741a694/old.dbscheme eol=crlf
/powershell/downgrades/802d5b9f407fb0dac894df1c0b4584f2215e1512/semmlecode.powershell.dbscheme eol=crlf

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

@@ -1,152 +0,0 @@
name: Microsoft CodeQL Pack Publish
on:
workflow_dispatch:
jobs:
check-branch:
runs-on: ubuntu-latest
steps:
- name: Fail if not on main branch
run: |
if [ "$GITHUB_REF" != "refs/heads/main" ]; then
echo "This workflow can only run on the 'main' branch."
exit 1
fi
codeqlversion:
needs: check-branch
runs-on: ubuntu-latest
outputs:
codeql_version: ${{ steps.set_codeql_version.outputs.codeql_version }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set CodeQL Version
id: set_codeql_version
run: |
git fetch
git fetch --tags
CURRENT_COMMIT=$(git rev-list -1 HEAD)
CURRENT_TAG=$(git describe --tags --abbrev=0 --match 'codeql-cli/v*' $CURRENT_COMMIT)
CODEQL_VERSION="${CURRENT_TAG#codeql-cli/}"
echo "CODEQL_VERSION=$CODEQL_VERSION" >> $GITHUB_OUTPUT
publishlibs:
environment: secure-publish
needs: codeqlversion
runs-on: ubuntu-latest
strategy:
matrix:
language: ['powershell']
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install CodeQL
shell: bash
run: |
gh extension install github/gh-codeql
gh codeql download "${{ needs.codeqlversion.outputs.codeql_version }}"
gh codeql set-version "${{ needs.codeqlversion.outputs.codeql_version }}"
env:
GITHUB_TOKEN: ${{ github.token }}
- name: Publish OS Microsoft CodeQL Lib Pack
shell: bash
run: |
# Download latest qlpack
gh codeql pack download "microsoft/$LANGUAGE-all"
PACK_DIR="$HOME/.codeql/packages/microsoft/$LANGUAGE-all"
VERSION_COUNT=$(ls -d "$PACK_DIR"/*/ | wc -l)
[[ "$VERSION_COUNT" -ne 1 ]] && { echo "Expected exactly one version in $PACK_DIR, but found $VERSION_COUNT. Exiting."; exit 1; }
# Increment version
CURRENT_VERSION=$(ls -v "$PACK_DIR" | tail -n 1)
MAJOR=$(echo "$CURRENT_VERSION" | cut -d. -f1)
MINOR=$(echo "$CURRENT_VERSION" | cut -d. -f2)
PATCH=$(echo "$CURRENT_VERSION" | cut -d. -f3)
NEXT_VERSION="$MAJOR.$MINOR.$((PATCH + 1))"
# Extract dependencies from the existing qlpack.yml before deleting
DEPENDENCIES=$(yq 'select(has("dependencies")) | .dependencies | {"dependencies": .}' "$LANGUAGE/ql/lib/qlpack.yml" 2>/dev/null)
DATAEXTENSIONS=$(yq 'select(has("dataExtensions")) | .dataExtensions | {"dataExtensions": .}' "$LANGUAGE/ql/lib/qlpack.yml" 2>/dev/null)
rm -f "$LANGUAGE/ql/lib/qlpack.yml" "$LANGUAGE/ql/lib/qlpack.lock"
# Create new qlpack.yml with modified content
cat <<EOF > "$LANGUAGE/ql/lib/qlpack.yml"
name: microsoft/$LANGUAGE-all
version: $NEXT_VERSION
extractor: $LANGUAGE
groups:
- $LANGUAGE
- microsoft-all
dbscheme: semmlecode.$LANGUAGE.dbscheme
extractor: $LANGUAGE
library: true
upgrades: upgrades
$DEPENDENCIES
$DATAEXTENSIONS
warnOnImplicitThis: true
EOF
# Publish pack
cat "$LANGUAGE/ql/lib/qlpack.yml"
gh codeql pack publish "$LANGUAGE/ql/lib"
env:
LANGUAGE: ${{ matrix.language }}
GITHUB_TOKEN: ${{ secrets.PACKAGE_PUBLISH }}
publish:
environment: secure-publish
needs: codeqlversion
runs-on: ubuntu-latest
strategy:
matrix:
language: ['csharp', 'cpp', 'java', 'javascript', 'python', 'ruby', 'go', 'rust', 'swift', 'powershell', 'iac']
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install CodeQL
shell: bash
run: |
gh extension install github/gh-codeql
gh codeql download "${{ needs.codeqlversion.outputs.codeql_version }}"
gh codeql set-version "${{ needs.codeqlversion.outputs.codeql_version }}"
env:
GITHUB_TOKEN: ${{ github.token }}
- name: Publish OS Microsoft CodeQL Pack
shell: bash
run: |
# Download latest qlpack
gh codeql pack download "microsoft/$LANGUAGE-queries"
PACK_DIR="$HOME/.codeql/packages/microsoft/$LANGUAGE-queries"
VERSION_COUNT=$(ls -d "$PACK_DIR"/*/ | wc -l)
[[ "$VERSION_COUNT" -ne 1 ]] && { echo "Expected exactly one version in $PACK_DIR, but found $VERSION_COUNT. Exiting."; exit 1; }
# Increment version
CURRENT_VERSION=$(ls -v "$PACK_DIR" | tail -n 1)
MAJOR=$(echo "$CURRENT_VERSION" | cut -d. -f1)
MINOR=$(echo "$CURRENT_VERSION" | cut -d. -f2)
PATCH=$(echo "$CURRENT_VERSION" | cut -d. -f3)
NEXT_VERSION="$MAJOR.$MINOR.$((PATCH + 1))"
# Extract dependencies from the existing qlpack.yml before deleting
DEPENDENCIES=$(yq 'select(has("dependencies")) | .dependencies | {"dependencies": .}' "$LANGUAGE/ql/src/qlpack.yml" 2>/dev/null)
rm -f "$LANGUAGE/ql/src/qlpack.yml" "$LANGUAGE/ql/src/qlpack.lock"
# Create new qlpack.yml with modified content
cat <<EOF > "$LANGUAGE/ql/src/qlpack.yml"
name: microsoft/$LANGUAGE-queries
version: $NEXT_VERSION
extractor: $LANGUAGE
groups:
- $LANGUAGE
- queries
$DEPENDENCIES
EOF
# Publish pack
cat "$LANGUAGE/ql/src/qlpack.yml"
gh codeql pack publish "$LANGUAGE/ql/src"
env:
LANGUAGE: ${{ matrix.language }}
GITHUB_TOKEN: ${{ secrets.PACKAGE_PUBLISH }}

View File

@@ -1,32 +0,0 @@
name: PowerShell PR Check
on:
pull_request:
branches:
- main
workflow_dispatch:
jobs:
powershell-pr-check:
name: powershell-pr-check
runs-on: windows-latest
if: github.repository == 'microsoft/codeql'
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
token: ${{ github.token }}
- name: Setup CodeQL
uses: ./.github/actions/fetch-codeql
with:
channel: release
- name: Install PowerShell
run: |
$path = Split-Path (Get-Command codeql).Source
./powershell/build-win64.ps1 $path
- name: Run QL tests
run: |
codeql test run --threads=0 powershell/ql/test

View File

@@ -1,28 +0,0 @@
name: Sync Main Tags
on:
pull_request:
types:
- closed
branches:
- main
jobs:
sync-main-tags:
name: Sync Main Tags
runs-on: ubuntu-latest
if: github.repository == 'microsoft/codeql' && github.event.pull_request.merged == true && github.event.pull_request.head.ref == 'auto/sync-main-pr'
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Push Tags
run: |
git remote add upstream https://github.com/github/codeql.git
git fetch upstream --tags --force
git push --force origin --tags
env:
GH_TOKEN: ${{ secrets.WORKFLOW_TOKEN }}

View File

@@ -1,91 +0,0 @@
name: Sync Main
on:
push:
branches:
- main
paths:
- .github/workflows/sync-main.yml
schedule:
- cron: '55 * * * *'
jobs:
sync-main:
name: Sync-main
runs-on: ubuntu-latest
if: github.repository == 'microsoft/codeql'
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
token: ${{ secrets.WORKFLOW_TOKEN }}
- name: Git config
shell: bash
run: |
git config user.name "dilanbhalla"
git config user.email "dilanbhalla@microsoft.com"
- name: Git checkout auto/sync-main-pr
shell: bash
run: |
git fetch origin
if git ls-remote --exit-code --heads origin auto/sync-main-pr > /dev/null; then
echo "Branch exists remotely. Checking it out."
git checkout -B auto/sync-main-pr origin/auto/sync-main-pr
else
echo "Branch does not exist remotely. Creating from main."
git checkout -B auto/sync-main-pr origin/main
git push -u origin auto/sync-main-pr
fi
- name: Sync origin/main
shell: bash
run: |
echo "::group::Sync with main branch"
git pull origin auto/sync-main-pr; exitCode=$?; if [ $exitCode -ne 0 ]; then exitCode=0; fi
git pull origin main --no-rebase
git push --force origin auto/sync-main-pr
echo "::endgroup::"
- name: Sync upstream/codeql-cli/latest
shell: bash
run: |
echo "::group::Set up remote"
git remote add upstream https://github.com/github/codeql.git
git fetch upstream --tags --force
echo "::endgroup::"
echo "::group::Merge codeql-cli/latest"
set -x
git merge codeql-cli/latest
set +x
echo "::endgroup::"
- name: Push sync branch
run: |
git push origin auto/sync-main-pr
env:
GITHUB_TOKEN: ${{ secrets.WORKFLOW_TOKEN }}
GH_TOKEN: ${{ secrets.WORKFLOW_TOKEN }}
- name: Create PR if it doesn't exist
shell: bash
run: |
pr_number=$(gh pr list --repo microsoft/codeql --head auto/sync-main-pr --base main --json number --jq '.[0].number')
if [ -n "$pr_number" ]; then
echo "PR from auto/sync-main-pr to main already exists (PR #$pr_number). Exiting gracefully."
else
if git fetch origin main auto/sync-main-pr && [ -n "$(git rev-list origin/main..origin/auto/sync-main-pr)" ]; then
echo "PR does not exist. Creating one..."
gh pr create --repo microsoft/codeql --fill -B main -H auto/sync-main-pr \
--label 'autogenerated' \
--title 'Sync Main (autogenerated)' \
--body "This PR syncs the latest changes from \`codeql-cli/latest\` into \`main\`." \
--reviewer 'MathiasVP' \
--reviewer 'ropwareJB'
else
echo "No changes to sync from auto/sync-main-pr to main. Exiting gracefully."
fi
fi
env:
GH_TOKEN: ${{ secrets.WORKFLOW_TOKEN }}

3
.gitmodules vendored
View File

@@ -1,3 +0,0 @@
[submodule "iac"]
path = iac
url = https://github.com/advanced-security/codeql-extractor-iac

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")
@@ -230,7 +206,6 @@ use_repo(
"kotlin-compiler-2.1.0-Beta1",
"kotlin-compiler-2.1.20-Beta1",
"kotlin-compiler-2.2.0-Beta1",
"kotlin-compiler-2.2.20-Beta2",
"kotlin-compiler-embeddable-1.6.0",
"kotlin-compiler-embeddable-1.6.20",
"kotlin-compiler-embeddable-1.7.0",
@@ -243,7 +218,6 @@ use_repo(
"kotlin-compiler-embeddable-2.1.0-Beta1",
"kotlin-compiler-embeddable-2.1.20-Beta1",
"kotlin-compiler-embeddable-2.2.0-Beta1",
"kotlin-compiler-embeddable-2.2.20-Beta2",
"kotlin-stdlib-1.6.0",
"kotlin-stdlib-1.6.20",
"kotlin-stdlib-1.7.0",
@@ -256,7 +230,6 @@ use_repo(
"kotlin-stdlib-2.1.0-Beta1",
"kotlin-stdlib-2.1.20-Beta1",
"kotlin-stdlib-2.2.0-Beta1",
"kotlin-stdlib-2.2.20-Beta2",
)
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")

View File

@@ -29,5 +29,3 @@ You can install the [CodeQL for Visual Studio Code](https://marketplace.visualst
### Tasks
The `.vscode/tasks.json` file defines custom tasks specific to working in this repository. To invoke one of these tasks, select the `Terminal | Run Task...` menu option, and then select the desired task from the dropdown. You can also invoke the `Tasks: Run Task` command from the command palette.

View File

@@ -1,41 +0,0 @@
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.8 BLOCK -->
## Security
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
## Reporting Security Issues
**Please do not report security vulnerabilities through public GitHub issues.**
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
* Full paths of source file(s) related to the manifestation of the issue
* The location of the affected source code (tag/branch/commit or direct URL)
* Any special configuration required to reproduce the issue
* Step-by-step instructions to reproduce the issue
* Proof-of-concept or exploit code (if possible)
* Impact of the issue, including how an attacker might exploit the issue
This information will help us triage your report more quickly.
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
## Preferred Languages
We prefer all communications to be in English.
## Policy
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
<!-- END MICROSOFT SECURITY.MD BLOCK -->

View File

@@ -1,13 +1,3 @@
## 0.4.14
No user-facing changes.
## 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,3 +0,0 @@
## 0.4.14
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.4.14
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
version: 0.4.13-dev
library: true
warnOnImplicitThis: true
dependencies:

View File

@@ -1,11 +1,3 @@
## 0.6.6
No user-facing changes.
## 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,3 +0,0 @@
## 0.6.6
No user-facing changes.

View File

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

View File

@@ -1,5 +1,5 @@
name: codeql/actions-queries
version: 0.6.6
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,30 +1,3 @@
## 5.4.0
### New Features
* Exposed various SSA-related classes (`Definition`, `PhiNode`, `ExplicitDefinition`, `DirectExplicitDefinition`, and `IndirectExplicitDefinition`) which were previously only usable inside the internal dataflow directory.
### Minor Analysis Improvements
* The `cpp/overrun-write` query now recognizes more bound checks and thus produces fewer false positives.
## 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

@@ -1,4 +0,0 @@
---
category: feature
---
* Added a new class `AdditionalCallTarget` for specifying additional call targets.

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,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,9 +0,0 @@
## 5.4.0
### New Features
* Exposed various SSA-related classes (`Definition`, `PhiNode`, `ExplicitDefinition`, `DirectExplicitDefinition`, and `IndirectExplicitDefinition`) which were previously only usable inside the internal dataflow directory.
### Minor Analysis Improvements
* The `cpp/overrun-write` query now recognizes more bound checks and thus produces fewer false positives.

View File

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

View File

@@ -115,10 +115,6 @@ private string normalizeFunctionName(Function f, string algType) {
(result.matches("RSA") implies not f.getName().toUpperCase().matches("%UNIVERSAL%")) and
//rsaz functions deemed to be too low level, and can be ignored
not f.getLocation().getFile().getBaseName().matches("rsaz_exp.c") and
// SHA false positives
(result.matches("SHA") implies not f.getName().toUpperCase().matches("%SHAKE%")) and
// CAST false positives
(result.matches("CAST") implies not f.getName().toUpperCase().matches(["%UPCAST%", "%DOWNCAST%"])) and
// General False positives
// Functions that 'get' do not set an algorithm, and therefore are considered ignorable
not f.getName().toLowerCase().matches("%get%")

View File

@@ -32,18 +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"]
# wdm.h
- ["", "", False, "RtlCopyVolatileMemory", "", "", "Argument[*@1]", "Argument[*@0]", "value", "manual"]
- ["", "", False, "RtlCopyDeviceMemory", "", "", "Argument[*@1]", "Argument[*@0]", "value", "manual"]
- ["", "", False, "RtlCopyMemory", "", "", "Argument[*@1]", "Argument[*@0]", "value", "manual"]
- ["", "", False, "RtlCopyMemoryNonTemporal", "", "", "Argument[*@1]", "Argument[*@0]", "value", "manual"]
- ["", "", False, "RtlCopyUnicodeString", "", "", "Argument[*1].Field[*Buffer]", "Argument[*0].Field[*Buffer]", "value", "manual"]
- ["", "", False, "RtlMoveMemory", "", "", "Argument[*@1]", "Argument[*@0]", "value", "manual"]
- ["", "", False, "RtlMoveVolatileMemory", "", "", "Argument[*@1]", "Argument[*@0]", "value", "manual"]
# winternl.h
- ["", "", False, "RtlInitUnicodeString", "", "", "Argument[*1]", "Argument[*0].Field[*Buffer]", "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.4.0
version: 5.2.1-dev
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp
@@ -15,7 +15,6 @@ dependencies:
codeql/tutorial: ${workspace}
codeql/util: ${workspace}
codeql/xml: ${workspace}
codeql/global-controlflow: ${workspace}
dataExtensions:
- ext/*.model.yml
- ext/generated/**/*.model.yml

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

@@ -15,13 +15,6 @@ class StandardSsa extends SsaHelper {
}
/**
* NOTE: If possible, prefer the SSA classes exposed by the new dataflow
* library:
* ```
* import semmle.code.cpp.dataflow.new.DataFlow
* // use `DataFlow::Ssa::Definition`
* ```
*
* A definition of one or more SSA variables, including phi node definitions.
* An _SSA variable_, as defined in the literature, is effectively the pair of
* an `SsaDefinition d` and a `StackVariable v`, written `(d, v)` in this

View File

@@ -1,11 +0,0 @@
import cpp
/**
* Provides classes for performing global (inter-procedural) control flow analyses.
*/
module ControlFlow {
private import internal.ControlFlowSpecific
private import codeql.globalcontrolflow.ControlFlow
import ControlFlowMake<Location, CppControlFlow>
import Public
}

View File

@@ -1,41 +0,0 @@
private import semmle.code.cpp.ir.IR
private import cpp as Cpp
private import ControlFlowPublic
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate as DataFlowPrivate
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon
predicate edge(Node n1, Node n2) { n1.asInstruction().getASuccessor() = n2.asInstruction() }
predicate callTarget(CallNode call, Callable target) {
exists(DataFlowPrivate::DataFlowCall dfCall | dfCall.asCallInstruction() = call.asInstruction() |
DataFlowImplCommon::viableCallableCached(dfCall).asSourceCallable() = target
or
DataFlowImplCommon::viableCallableLambda(dfCall, _).asSourceCallable() = target
)
}
predicate flowEntry(Callable c, Node entry) {
entry.asInstruction().(EnterFunctionInstruction).getEnclosingFunction() = c
}
predicate flowExit(Callable c, Node exitNode) {
exitNode.asInstruction().(ExitFunctionInstruction).getEnclosingFunction() = c
}
Callable getEnclosingCallable(Node n) { n.getEnclosingFunction() = result }
predicate hiddenNode(Node n) { n.asInstruction() instanceof PhiInstruction }
private newtype TSplit = TNone() { none() }
class Split extends TSplit {
abstract string toString();
abstract Cpp::Location getLocation();
abstract predicate entry(Node n1, Node n2);
abstract predicate exit(Node n1, Node n2);
abstract predicate blocked(Node n1, Node n2);
}

View File

@@ -1,79 +0,0 @@
private import semmle.code.cpp.ir.IR
private import cpp
private newtype TNode = TInstructionNode(Instruction i)
abstract private class NodeImpl extends TNode {
/** Gets the `Instruction` associated with this node, if any. */
Instruction asInstruction() { result = this.(InstructionNode).getInstruction() }
/** Gets the `Expr` associated with this node, if any. */
Expr asExpr() { result = this.(ExprNode).getExpr() }
/** Gets the `Parameter` associated with this node, if any. */
Parameter asParameter() { result = this.(ParameterNode).getParameter() }
/** Gets the location of this node. */
Location getLocation() { none() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
final predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets a textual representation of this node. */
abstract string toString();
/** Gets the enclosing callable of this node. */
abstract Callable getEnclosingFunction();
}
final class Node = NodeImpl;
private class InstructionNode extends NodeImpl {
Instruction instr;
InstructionNode() { this = TInstructionNode(instr) }
/** Gets the `Instruction` associated with this node. */
Instruction getInstruction() { result = instr }
final override Location getLocation() { result = instr.getLocation() }
final override string toString() { result = instr.getAst().toString() }
final override Callable getEnclosingFunction() { result = instr.getEnclosingFunction() }
}
private class ExprNode extends InstructionNode {
Expr e;
ExprNode() { e = this.getInstruction().getConvertedResultExpression() }
/** Gets the `Expr` associated with this node. */
Expr getExpr() { result = e }
}
private class ParameterNode extends InstructionNode {
override InitializeParameterInstruction instr;
Parameter p;
ParameterNode() { p = instr.getParameter() }
/** Gets the `Parameter` associated with this node. */
Parameter getParameter() { result = p }
}
class CallNode extends InstructionNode {
override CallInstruction instr;
}
class Callable = Function;

View File

@@ -1,19 +0,0 @@
/**
* Provides IR-specific definitions for use in the data flow library.
*/
private import cpp
private import codeql.globalcontrolflow.ControlFlow
module Private {
import ControlFlowPrivate
}
module Public {
import ControlFlowPublic
}
module CppControlFlow implements InputSig<Location> {
import Private
import Public
}

View File

@@ -1,5 +1,6 @@
private import cpp
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.ir.dataflow.DataFlow
private import DataFlowPrivate
private import DataFlowUtil
private import DataFlowImplCommon as DataFlowImplCommon
@@ -59,7 +60,7 @@ private module VirtualDispatch {
* `resolve` predicate to stitch that information together and resolve the
* call.
*/
abstract Node getDispatchValue();
abstract DataFlow::Node getDispatchValue();
/** Gets a candidate target for this call. */
abstract Function resolve();
@@ -71,13 +72,17 @@ private module VirtualDispatch {
* parameter is true when the search is allowed to continue backwards into
* a parameter; non-recursive callers should pass `_` for `allowFromArg`.
*/
predicate flowsFrom(Node src, boolean allowFromArg) {
predicate flowsFrom(DataFlow::Node src, boolean allowFromArg) {
src = this.getDispatchValue() and allowFromArg = true
or
exists(Node other, boolean allowOtherFromArg | this.flowsFrom(other, allowOtherFromArg) |
exists(DataFlow::Node other, boolean allowOtherFromArg |
this.flowsFrom(other, allowOtherFromArg)
|
// Call argument
exists(DataFlowCall call, Position i |
other.(ParameterNode).isParameterOf(pragma[only_bind_into](call).getStaticCallTarget(), i) and
other
.(DataFlow::ParameterNode)
.isParameterOf(pragma[only_bind_into](call).getStaticCallTarget(), i) and
src.(ArgumentNode).argumentOf(call, pragma[only_bind_into](pragma[only_bind_out](i)))
) and
allowOtherFromArg = true and
@@ -91,7 +96,7 @@ private module VirtualDispatch {
allowFromArg = false
or
// Local flow
localFlowStep(src, other) and
DataFlow::localFlowStep(src, other) and
allowFromArg = allowOtherFromArg
or
// Flow from global variable to load.
@@ -154,11 +159,11 @@ private module VirtualDispatch {
private class DataSensitiveExprCall extends DataSensitiveCall {
DataSensitiveExprCall() { not exists(this.getStaticCallTarget()) }
override Node getDispatchValue() { result.asOperand() = this.getCallTargetOperand() }
override DataFlow::Node getDispatchValue() { result.asOperand() = this.getCallTargetOperand() }
override Function resolve() {
exists(FunctionInstruction fi |
this.flowsFrom(instructionNode(fi), _) and
this.flowsFrom(DataFlow::instructionNode(fi), _) and
result = fi.getFunctionSymbol()
) and
(
@@ -181,7 +186,7 @@ private module VirtualDispatch {
)
}
override Node getDispatchValue() { result.asInstruction() = this.getArgument(-1) }
override DataFlow::Node getDispatchValue() { result.asInstruction() = this.getArgument(-1) }
override MemberFunction resolve() {
exists(Class overridingClass |
@@ -208,7 +213,7 @@ private module VirtualDispatch {
pragma[noinline]
private predicate hasFlowFromCastFrom(Class derivedClass) {
exists(ConvertToBaseInstruction toBase |
this.flowsFrom(instructionNode(toBase), _) and
this.flowsFrom(DataFlow::instructionNode(toBase), _) and
derivedClass = toBase.getDerivedClass()
)
}
@@ -265,7 +270,7 @@ private predicate mayBenefitFromCallContext(
exists(InitializeParameterInstruction init |
not exists(call.getStaticCallTarget()) and
init.getEnclosingFunction() = f.getUnderlyingCallable() and
call.flowsFrom(instructionNode(init), _) and
call.flowsFrom(DataFlow::instructionNode(init), _) and
init.getParameter().getIndex() = arg
)
}

View File

@@ -4,7 +4,7 @@ private import semmle.code.cpp.ir.IR
private import DataFlowDispatch
private import semmle.code.cpp.ir.internal.IRCppLanguage
private import semmle.code.cpp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
private import SsaImpl as Ssa
private import SsaInternals as Ssa
private import DataFlowImplCommon as DataFlowImplCommon
private import codeql.util.Unit
private import Node0ToString
@@ -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. */
@@ -1982,23 +1902,19 @@ module IteratorFlow {
predicate allowFlowIntoUncertainDef(IteratorSsa::UncertainWriteDefinition def) { any() }
class GuardValue = Void;
class Guard extends Void {
predicate hasValueBranchEdge(
SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, GuardValue val
) {
predicate hasBranchEdge(SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, boolean branch) {
none()
}
predicate valueControlsBranchEdge(
SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, GuardValue val
predicate controlsBranchEdge(
SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, boolean branch
) {
none()
}
}
predicate guardDirectlyControlsBlock(Guard guard, SsaInput::BasicBlock bb, GuardValue val) {
predicate guardDirectlyControlsBlock(Guard guard, SsaInput::BasicBlock bb, boolean branch) {
none()
}

View File

@@ -13,7 +13,7 @@ private import semmle.code.cpp.models.interfaces.DataFlow
private import semmle.code.cpp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
private import DataFlowPrivate
private import ModelUtil
private import SsaImpl as SsaImpl
private import SsaInternals as Ssa
private import DataFlowImplCommon as DataFlowImplCommon
private import codeql.util.Unit
private import Node0ToString
@@ -39,39 +39,38 @@ private newtype TIRDataFlowNode =
TNode0(Node0Impl node) { DataFlowImplCommon::forceCachingInSameStage() } or
TGlobalLikeVariableNode(GlobalLikeVariable var, int indirectionIndex) {
indirectionIndex =
[getMinIndirectionsForType(var.getUnspecifiedType()) .. SsaImpl::getMaxIndirectionsForType(var.getUnspecifiedType())]
[getMinIndirectionsForType(var.getUnspecifiedType()) .. Ssa::getMaxIndirectionsForType(var.getUnspecifiedType())]
} or
TPostUpdateNodeImpl(Operand operand, int indirectionIndex) {
operand = any(FieldAddress fa).getObjectAddressOperand() and
indirectionIndex =
[0 .. SsaImpl::countIndirectionsForCppType(SsaImpl::getLanguageType(operand))]
indirectionIndex = [0 .. Ssa::countIndirectionsForCppType(Ssa::getLanguageType(operand))]
or
SsaImpl::isModifiableByCall(operand, indirectionIndex)
Ssa::isModifiableByCall(operand, indirectionIndex)
} or
TSsaSynthNode(SsaImpl::SynthNode n) or
TSsaSynthNode(Ssa::SynthNode n) or
TSsaIteratorNode(IteratorFlow::IteratorFlowNode n) or
TRawIndirectOperand0(Node0Impl node, int indirectionIndex) {
SsaImpl::hasRawIndirectOperand(node.asOperand(), indirectionIndex)
Ssa::hasRawIndirectOperand(node.asOperand(), indirectionIndex)
} or
TRawIndirectInstruction0(Node0Impl node, int indirectionIndex) {
not exists(node.asOperand()) and
SsaImpl::hasRawIndirectInstruction(node.asInstruction(), indirectionIndex)
Ssa::hasRawIndirectInstruction(node.asInstruction(), indirectionIndex)
} or
TFinalParameterNode(Parameter p, int indirectionIndex) {
exists(SsaImpl::FinalParameterUse use |
exists(Ssa::FinalParameterUse use |
use.getParameter() = p and
use.getIndirectionIndex() = indirectionIndex
)
} or
TFinalGlobalValue(SsaImpl::GlobalUse globalUse) or
TInitialGlobalValue(SsaImpl::GlobalDef globalUse) or
TFinalGlobalValue(Ssa::GlobalUse globalUse) or
TInitialGlobalValue(Ssa::GlobalDef globalUse) or
TBodyLessParameterNodeImpl(Parameter p, int indirectionIndex) {
// Rule out parameters of catch blocks.
not exists(p.getCatchBlock()) and
// We subtract one because `getMaxIndirectionsForType` returns the maximum
// indirection for a glvalue of a given type, and this doesn't apply to
// parameters.
indirectionIndex = [0 .. SsaImpl::getMaxIndirectionsForType(p.getUnspecifiedType()) - 1] and
indirectionIndex = [0 .. Ssa::getMaxIndirectionsForType(p.getUnspecifiedType()) - 1] and
not any(InitializeParameterInstruction init).getParameter() = p
} or
TFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn)
@@ -82,7 +81,7 @@ private newtype TIRDataFlowNode =
class FieldAddress extends Operand {
FieldAddressInstruction fai;
FieldAddress() { fai = this.getDef() and not SsaImpl::ignoreOperand(this) }
FieldAddress() { fai = this.getDef() and not Ssa::ignoreOperand(this) }
/** Gets the field associated with this instruction. */
Field getField() { result = fai.getField() }
@@ -127,7 +126,7 @@ predicate conversionFlow(
)
or
additional = true and
SsaImpl::isAdditionalConversionFlow(opFrom, instrTo)
Ssa::isAdditionalConversionFlow(opFrom, instrTo)
)
or
isPointerArith = true and
@@ -184,7 +183,7 @@ class Node extends TIRDataFlowNode {
or
this.asOperand().getUse() = block.getInstruction(i)
or
exists(SsaImpl::SynthNode ssaNode |
exists(Ssa::SynthNode ssaNode |
this.(SsaSynthNode).getSynthNode() = ssaNode and
ssaNode.getBasicBlock() = block and
ssaNode.getIndex() = i
@@ -365,10 +364,10 @@ class Node extends TIRDataFlowNode {
* pointed to by `p`.
*/
Expr asDefinition(boolean uncertain) {
exists(StoreInstruction store, SsaImpl::Definition def |
exists(StoreInstruction store, Ssa::Definition def |
store = this.asInstruction() and
result = asDefinitionImpl(store) and
SsaImpl::defToNode(this, def, _) and
Ssa::defToNode(this, def, _) and
if def.isCertain() then uncertain = false else uncertain = true
)
}
@@ -489,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.
@@ -628,7 +610,7 @@ class OperandNode extends Node, Node0 {
* For example, `stripPointers(int*&)` is `int*` and `stripPointers(int*)` is `int`.
*/
Type stripPointer(Type t) {
result = any(SsaImpl::Indirection ind | ind.getType() = t).getBaseType()
result = any(Ssa::Indirection ind | ind.getType() = t).getBaseType()
or
result = t.(PointerToMemberType).getBaseType()
or
@@ -695,12 +677,12 @@ class PostFieldUpdateNode extends PostUpdateNodeImpl {
* in a data flow graph.
*/
class SsaSynthNode extends Node, TSsaSynthNode {
SsaImpl::SynthNode node;
Ssa::SynthNode node;
SsaSynthNode() { this = TSsaSynthNode(node) }
/** Gets the synthesized SSA node associated with this node. */
SsaImpl::SynthNode getSynthNode() { result = node }
Ssa::SynthNode getSynthNode() { result = node }
override DataFlowCallable getEnclosingCallable() {
result.asSourceCallable() = this.getFunction()
@@ -783,12 +765,12 @@ class SideEffectOperandNode extends Node instanceof IndirectOperand {
* from a function body.
*/
class FinalGlobalValue extends Node, TFinalGlobalValue {
SsaImpl::GlobalUse globalUse;
Ssa::GlobalUse globalUse;
FinalGlobalValue() { this = TFinalGlobalValue(globalUse) }
/** Gets the underlying SSA use. */
SsaImpl::GlobalUse getGlobalUse() { result = globalUse }
Ssa::GlobalUse getGlobalUse() { result = globalUse }
override DataFlowCallable getEnclosingCallable() {
result.asSourceCallable() = this.getFunction()
@@ -815,12 +797,12 @@ class FinalGlobalValue extends Node, TFinalGlobalValue {
* a function body.
*/
class InitialGlobalValue extends Node, TInitialGlobalValue {
SsaImpl::GlobalDef globalDef;
Ssa::GlobalDef globalDef;
InitialGlobalValue() { this = TInitialGlobalValue(globalDef) }
/** Gets the underlying SSA definition. */
SsaImpl::GlobalDef getGlobalDef() { result = globalDef }
Ssa::GlobalDef getGlobalDef() { result = globalDef }
override DataFlowCallable getEnclosingCallable() {
result.asSourceCallable() = this.getFunction()
@@ -1243,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 {
@@ -1289,11 +1271,11 @@ class UninitializedNode extends Node {
LocalVariable v;
UninitializedNode() {
exists(SsaImpl::Definition def, SsaImpl::SourceVariable sv |
exists(Ssa::Definition def, Ssa::SourceVariable sv |
def.getIndirectionIndex() = 0 and
def.getValue().asInstruction() instanceof UninitializedInstruction and
SsaImpl::defToNode(this, def, sv) and
v = sv.getBaseVariable().(SsaImpl::BaseIRVariable).getIRVariable().getAst()
Ssa::defToNode(this, def, sv) and
v = sv.getBaseVariable().(Ssa::BaseIRVariable).getIRVariable().getAst()
)
}
@@ -1723,7 +1705,7 @@ private module Cached {
cached
predicate flowsToBackEdge(Node n) {
exists(Node succ, IRBlock bb1, IRBlock bb2 |
SsaImpl::ssaFlow(n, succ) and
Ssa::ssaFlow(n, succ) and
bb1 = n.getBasicBlock() and
bb2 = succ.getBasicBlock() and
bb1 != bb2 and
@@ -1821,7 +1803,7 @@ private module Cached {
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo, string model) {
(
// Def-use/Use-use flow
SsaImpl::ssaFlow(nodeFrom, nodeTo)
Ssa::ssaFlow(nodeFrom, nodeTo)
or
IteratorFlow::localFlowStep(nodeFrom, nodeTo)
or
@@ -1834,7 +1816,7 @@ private module Cached {
|
simpleOperandLocalFlowStep(iFrom, opTo) and
// Omit when the instruction node also represents the operand.
not iFrom = SsaImpl::getIRRepresentationOfOperand(opTo)
not iFrom = Ssa::getIRRepresentationOfOperand(opTo)
)
or
// Indirect operand -> (indirect) instruction flow
@@ -1907,7 +1889,7 @@ private module Cached {
// We also want a write coming out of an `OutNode` to flow `nodeTo`.
// This is different from `reverseFlowInstruction` since `nodeFrom` can never
// be an `OutNode` when it's defined by an instruction.
SsaImpl::outNodeHasAddressAndIndex(nodeFrom, address, indirectionIndex)
Ssa::outNodeHasAddressAndIndex(nodeFrom, address, indirectionIndex)
)
}
@@ -2100,7 +2082,7 @@ private newtype TContent =
TFieldContent(Field f, int indirectionIndex) {
// the indirection index for field content starts at 1 (because `TFieldContent` is thought of as
// the address of the field, `FieldAddress` in the IR).
indirectionIndex = [1 .. SsaImpl::getMaxIndirectionsForType(f.getUnspecifiedType())] and
indirectionIndex = [1 .. Ssa::getMaxIndirectionsForType(f.getUnspecifiedType())] and
// Reads and writes of union fields are tracked using `UnionContent`.
not f.getDeclaringType() instanceof Union
} or
@@ -2112,9 +2094,7 @@ private newtype TContent =
// field can be read by any read of the union's fields. Again, the indirection index
// is 1-based (because 0 is considered the address).
indirectionIndex =
[1 .. max(SsaImpl::getMaxIndirectionsForType(getAFieldWithSize(u, bytes)
.getUnspecifiedType())
)]
[1 .. max(Ssa::getMaxIndirectionsForType(getAFieldWithSize(u, bytes).getUnspecifiedType()))]
)
} or
TElementContent(int indirectionIndex) {
@@ -2357,7 +2337,7 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
controls(g, result, edge)
)
or
result = SsaImpl::BarrierGuard<guardChecksNode/3>::getABarrierNode()
result = Ssa::BarrierGuard<guardChecksNode/3>::getABarrierNode()
}
/**
@@ -2456,7 +2436,7 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
)
or
result =
SsaImpl::BarrierGuardWithIntParam<guardChecksIndirectNode/4>::getABarrierNode(indirectionIndex)
Ssa::BarrierGuardWithIntParam<guardChecksIndirectNode/4>::getABarrierNode(indirectionIndex)
}
}
@@ -2493,7 +2473,7 @@ module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardCheck
controls(g, result, edge)
)
or
result = SsaImpl::BarrierGuard<guardChecksNode/3>::getABarrierNode()
result = Ssa::BarrierGuard<guardChecksNode/3>::getABarrierNode()
}
bindingset[value, n]
@@ -2523,7 +2503,7 @@ module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardCheck
)
or
result =
SsaImpl::BarrierGuardWithIntParam<guardChecksIndirectNode/4>::getABarrierNode(indirectionIndex)
Ssa::BarrierGuardWithIntParam<guardChecksIndirectNode/4>::getABarrierNode(indirectionIndex)
}
}
@@ -2579,16 +2559,3 @@ Function getARuntimeTarget(Call call) {
result = DataFlowImplCommon::viableCallableLambda(dfCall, _).asSourceCallable()
)
}
/** A module that provides static single assignment (SSA) information. */
module Ssa {
class Definition = SsaImpl::Definition;
class ExplicitDefinition = SsaImpl::ExplicitDefinition;
class DirectExplicitDefinition = SsaImpl::DirectExplicitDefinition;
class IndirectExplicitDefinition = SsaImpl::IndirectExplicitDefinition;
class PhiNode = SsaImpl::PhiNode;
}

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

@@ -4,15 +4,15 @@
*/
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs
private import semmle.code.cpp.ir.dataflow.DataFlow
private import DataFlowUtil
private import DataFlowPrivate
private import SsaImpl as Ssa
private import SsaInternals as Ssa
/**
* Gets the instruction that goes into `input` for `call`.
*/
Node callInput(CallInstruction call, FunctionInput input) {
DataFlow::Node callInput(CallInstruction call, FunctionInput input) {
// An argument or qualifier
exists(int index |
result.asOperand() = call.getArgumentOperand(index) and
@@ -62,8 +62,8 @@ Node callOutput(CallInstruction call, FunctionOutput output) {
result = callOutputWithIndirectionIndex(call, output, _)
}
Node callInput(CallInstruction call, FunctionInput input, int d) {
exists(Node n | n = callInput(call, input) and d > 0 |
DataFlow::Node callInput(CallInstruction call, FunctionInput input, int d) {
exists(DataFlow::Node n | n = callInput(call, input) and d > 0 |
// An argument or qualifier
hasOperandAndIndex(result, n.asOperand(), d)
or
@@ -85,7 +85,7 @@ private IndirectReturnOutNode getIndirectReturnOutNode(CallInstruction call, int
*/
bindingset[d]
Node callOutput(CallInstruction call, FunctionOutput output, int d) {
exists(Node n, int indirectionIndex |
exists(DataFlow::Node n, int indirectionIndex |
n = callOutputWithIndirectionIndex(call, output, indirectionIndex) and d > 0
|
// The return value

View File

@@ -1,6 +1,6 @@
private import cpp
private import semmle.code.cpp.ir.IR
private import SsaImpl as Ssa
private import SsaInternals as Ssa
/**
* A property provider that hides all instructions and operands that are not relevant for IR dataflow.

View File

@@ -2,7 +2,7 @@ private import cpp
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
private import SsaImpl as Ssa
private import SsaInternals as Ssa
private import PrintIRUtilities
/**

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@ private import semmle.code.cpp.models.interfaces.DataFlow
private import semmle.code.cpp.models.interfaces.SideEffect
private import DataFlowUtil
private import DataFlowPrivate
private import SsaImpl as Ssa
private import SsaInternals as Ssa
private import semmle.code.cpp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
private import semmle.code.cpp.ir.dataflow.FlowSteps

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

@@ -26,14 +26,6 @@ private class IteratorTraits extends Class {
}
Type getIteratorType() { result = this.getTemplateArgument(0) }
Type getValueType() {
exists(TypedefType t |
this.getAMember() = t and
t.getName() = "value_type" and
result = t.getUnderlyingType()
)
}
}
/**
@@ -42,13 +34,16 @@ private class IteratorTraits extends Class {
*/
private class IteratorByTraits extends Iterator {
IteratorTraits trait;
IteratorByTraits() {
trait.getIteratorType() = this and
not trait.getValueType() = this
IteratorByTraits() { trait.getIteratorType() = this }
override Type getValueType() {
exists(TypedefType t |
trait.getAMember() = t and
t.getName() = "value_type" and
result = t.getUnderlyingType()
)
}
override Type getValueType() { result = trait.getValueType() }
}
/**

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

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