mirror of
https://github.com/github/codeql.git
synced 2026-05-26 00:51:25 +02:00
Compare commits
25 Commits
changedocs
...
calumgrant
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4788444cf4 | ||
|
|
991a337106 | ||
|
|
fb7bec75fd | ||
|
|
62a6a2479b | ||
|
|
c92be9fcd7 | ||
|
|
996811d918 | ||
|
|
179a7f3fdb | ||
|
|
0c164b0552 | ||
|
|
6b38ca3db9 | ||
|
|
4acc51bb7f | ||
|
|
4316ab6518 | ||
|
|
8d12d0d1ac | ||
|
|
2b052b18e2 | ||
|
|
213711029a | ||
|
|
7407b55f75 | ||
|
|
e950ddcb1c | ||
|
|
c4e2a52dc3 | ||
|
|
190c5ca9c0 | ||
|
|
3ae2652040 | ||
|
|
8b0293d189 | ||
|
|
3550e1f837 | ||
|
|
66e56e2e39 | ||
|
|
1bc6bc8049 | ||
|
|
ff379714b6 | ||
|
|
74b51313e0 |
11
.bazelrc
11
.bazelrc
@@ -10,19 +10,16 @@ common --override_module=semmle_code=%workspace%/misc/bazel/semmle_code_stub
|
||||
|
||||
build --repo_env=CC=clang --repo_env=CXX=clang++
|
||||
|
||||
# we use transitions that break builds of `...`, so for `test` to work with that we need the following
|
||||
test --build_tests_only
|
||||
build:linux --cxxopt=-std=c++20
|
||||
# we currently cannot built the swift extractor for ARM
|
||||
build:macos --cxxopt=-std=c++20 --copt=-arch --copt=x86_64 --linkopt=-arch --linkopt=x86_64
|
||||
build:windows --cxxopt=/std:c++20 --cxxopt=/Zc:preprocessor
|
||||
|
||||
# this requires developer mode, but is required to have pack installer functioning
|
||||
startup --windows_enable_symlinks
|
||||
common --enable_runfiles
|
||||
|
||||
# with the above, we can avoid building python zips which is the default on windows as that's expensive
|
||||
build --nobuild_python_zip
|
||||
|
||||
common --registry=file:///%workspace%/misc/bazel/registry
|
||||
common --registry=https://bcr.bazel.build
|
||||
|
||||
common --@rules_dotnet//dotnet/settings:strict_deps=false
|
||||
|
||||
try-import %workspace%/local.bazelrc
|
||||
|
||||
@@ -2,9 +2,3 @@
|
||||
|
||||
common --registry=file:///%workspace%/ql/misc/bazel/registry
|
||||
common --registry=https://bcr.bazel.build
|
||||
|
||||
# See bazelbuild/rules_dotnet#413: strict_deps in C# also appliy to 3rd-party deps, and when we pull
|
||||
# in (for example) the xunit package, there's no code in this at all, it just depends transitively on
|
||||
# its implementation packages without providing any code itself.
|
||||
# We either can depend on internal implementation details, or turn of strict deps.
|
||||
common --@rules_dotnet//dotnet/settings:strict_deps=false
|
||||
|
||||
@@ -1 +1 @@
|
||||
7.2.1
|
||||
7.1.2
|
||||
|
||||
14
.devcontainer/swift/root.sh
Executable file → Normal file
14
.devcontainer/swift/root.sh
Executable file → Normal file
@@ -3,16 +3,6 @@ set -xe
|
||||
BAZELISK_VERSION=v1.12.0
|
||||
BAZELISK_DOWNLOAD_SHA=6b0bcb2ea15bca16fffabe6fda75803440375354c085480fe361d2cbf32501db
|
||||
|
||||
# install git lfs apt source
|
||||
curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash
|
||||
|
||||
# install gh apt source
|
||||
(type -p wget >/dev/null || (sudo apt update && sudo apt-get install wget -y)) \
|
||||
&& sudo mkdir -p -m 755 /etc/apt/keyrings \
|
||||
&& wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \
|
||||
&& sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
|
||||
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
|
||||
|
||||
apt-get update
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get -y install --no-install-recommends \
|
||||
@@ -20,9 +10,7 @@ apt-get -y install --no-install-recommends \
|
||||
uuid-dev \
|
||||
python3-distutils \
|
||||
python3-pip \
|
||||
bash-completion \
|
||||
git-lfs \
|
||||
gh
|
||||
bash-completion
|
||||
|
||||
# Install Bazel
|
||||
curl -fSsL -o /usr/local/bin/bazelisk https://github.com/bazelbuild/bazelisk/releases/download/${BAZELISK_VERSION}/bazelisk-linux-amd64
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
set -xe
|
||||
|
||||
git lfs install
|
||||
|
||||
# add the workspace to the codeql search path
|
||||
mkdir -p /home/vscode/.config/codeql
|
||||
echo "--search-path /workspaces/codeql" > /home/vscode/.config/codeql/config
|
||||
|
||||
35
.gitattributes
vendored
35
.gitattributes
vendored
@@ -50,40 +50,31 @@
|
||||
*.dll -text
|
||||
*.pdb -text
|
||||
|
||||
/java/ql/test/stubs/**/*.java linguist-generated=true
|
||||
/java/ql/test/experimental/stubs/**/*.java linguist-generated=true
|
||||
/java/kotlin-extractor/deps/*.jar filter=lfs diff=lfs merge=lfs -text
|
||||
java/ql/test/stubs/**/*.java linguist-generated=true
|
||||
java/ql/test/experimental/stubs/**/*.java linguist-generated=true
|
||||
|
||||
# Force git not to modify line endings for go or html files under the go/ql directory
|
||||
/go/ql/**/*.go -text
|
||||
/go/ql/**/*.html -text
|
||||
go/ql/**/*.go -text
|
||||
go/ql/**/*.html -text
|
||||
# Force git not to modify line endings for go dbschemes
|
||||
/go/*.dbscheme -text
|
||||
go/*.dbscheme -text
|
||||
# Preserve unusual line ending from codeql-go merge
|
||||
/go/extractor/opencsv/CSVReader.java -text
|
||||
go/extractor/opencsv/CSVReader.java -text
|
||||
|
||||
# For some languages, upgrade script testing references really old dbscheme
|
||||
# files from legacy upgrades that have CRLF line endings. Since upgrade
|
||||
# resolution relies on object hashes, we must suppress line ending conversion
|
||||
# for those testing dbscheme files.
|
||||
/*/ql/lib/upgrades/initial/*.dbscheme -text
|
||||
*/ql/lib/upgrades/initial/*.dbscheme -text
|
||||
|
||||
# Auto-generated modeling for Python
|
||||
/python/ql/lib/semmle/python/frameworks/data/internal/subclass-capture/*.yml linguist-generated=true
|
||||
python/ql/lib/semmle/python/frameworks/data/internal/subclass-capture/*.yml linguist-generated=true
|
||||
|
||||
# auto-generated bazel lock file
|
||||
/ruby/extractor/cargo-bazel-lock.json linguist-generated=true
|
||||
/ruby/extractor/cargo-bazel-lock.json -merge
|
||||
ruby/extractor/cargo-bazel-lock.json linguist-generated=true
|
||||
ruby/extractor/cargo-bazel-lock.json -merge
|
||||
|
||||
# auto-generated files for the C# build
|
||||
/csharp/paket.lock linguist-generated=true
|
||||
# needs eol=crlf, as `paket` touches this file and saves it as crlf
|
||||
/csharp/.paket/Paket.Restore.targets linguist-generated=true eol=crlf
|
||||
/csharp/paket.main.bzl linguist-generated=true
|
||||
/csharp/paket.main_extension.bzl linguist-generated=true
|
||||
|
||||
# ripunzip tool
|
||||
/misc/ripunzip/ripunzip-* filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
# swift prebuilt resources
|
||||
/swift/third_party/resource-dir/*.zip filter=lfs diff=lfs merge=lfs -text
|
||||
csharp/paket.lock linguist-generated=true
|
||||
# needs eol=crlf, as `paket` touches this file and saves it als crlf
|
||||
csharp/.paket/Paket.Restore.targets linguist-generated=true eol=crlf
|
||||
|
||||
74
.github/workflows/build-ripunzip.yml
vendored
74
.github/workflows/build-ripunzip.yml
vendored
@@ -1,74 +0,0 @@
|
||||
name: Build runzip
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ripunzip-version:
|
||||
description: "what reference to checktout from google/runzip"
|
||||
required: false
|
||||
default: v1.2.1
|
||||
openssl-version:
|
||||
description: "what reference to checkout from openssl/openssl for Linux"
|
||||
required: false
|
||||
default: openssl-3.3.0
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-20.04, macos-12, windows-2019]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
repository: google/ripunzip
|
||||
ref: ${{ inputs.ripunzip-version }}
|
||||
# we need to avoid ripunzip dynamically linking into libssl
|
||||
# see https://github.com/sfackler/rust-openssl/issues/183
|
||||
- if: runner.os == 'Linux'
|
||||
name: checkout openssl
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: openssl/openssl
|
||||
path: openssl
|
||||
ref: ${{ inputs.openssl-version }}
|
||||
- if: runner.os == 'Linux'
|
||||
name: build and install openssl with fPIC
|
||||
shell: bash
|
||||
working-directory: openssl
|
||||
run: |
|
||||
./config -fPIC --prefix=$HOME/.local --openssldir=$HOME/.local/ssl
|
||||
make -j $(nproc)
|
||||
make install_sw -j $(nproc)
|
||||
- if: runner.os == 'Linux'
|
||||
name: build (linux)
|
||||
shell: bash
|
||||
run: |
|
||||
env OPENSSL_LIB_DIR=$HOME/.local/lib64 OPENSSL_INCLUDE_DIR=$HOME/.local/include OPENSSL_STATIC=yes cargo build --release
|
||||
mv target/release/ripunzip ripunzip-linux
|
||||
- if: runner.os == 'Windows'
|
||||
name: build (windows)
|
||||
shell: bash
|
||||
run: |
|
||||
cargo build --release
|
||||
mv target/release/ripunzip ripunzip-windows
|
||||
- name: build (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
shell: bash
|
||||
run: |
|
||||
rustup target install x86_64-apple-darwin
|
||||
rustup target install aarch64-apple-darwin
|
||||
cargo build --target x86_64-apple-darwin --release
|
||||
cargo build --target aarch64-apple-darwin --release
|
||||
lipo -create -output ripunzip-macos \
|
||||
-arch x86_64 target/x86_64-apple-darwin/release/ripunzip \
|
||||
-arch arm64 target/aarch64-apple-darwin/release/ripunzip
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ripunzip-${{ runner.os }}
|
||||
path: ripunzip-*
|
||||
- name: Check built binary
|
||||
shell: bash
|
||||
run: |
|
||||
./ripunzip-* --version
|
||||
4
.github/workflows/csharp-qltest.yml
vendored
4
.github/workflows/csharp-qltest.yml
vendored
@@ -65,7 +65,7 @@ jobs:
|
||||
key: csharp-qltest-${{ matrix.slice }}
|
||||
- name: Run QL tests
|
||||
run: |
|
||||
codeql test run --threads=0 --ram 50000 --slice ${{ matrix.slice }} --search-path "${{ github.workspace }}" --check-databases --check-undefined-labels --check-repeated-labels --check-redefined-labels --consistency-queries ql/consistency-queries ql/test --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
|
||||
codeql test run --threads=0 --ram 50000 --slice ${{ matrix.slice }} --search-path extractor-pack --check-databases --check-undefined-labels --check-repeated-labels --check-redefined-labels --consistency-queries ql/consistency-queries ql/test --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
unit-tests:
|
||||
@@ -101,6 +101,6 @@ jobs:
|
||||
# Update existing stubs in the repo with the freshly generated ones
|
||||
mv "$STUBS_PATH/output/stubs/_frameworks" ql/test/resources/stubs/
|
||||
git status
|
||||
codeql test run --threads=0 --search-path "${{ github.workspace }}" --check-databases --check-undefined-labels --check-repeated-labels --check-redefined-labels --consistency-queries ql/consistency-queries -- ql/test/library-tests/dataflow/flowsources/aspremote
|
||||
codeql test run --threads=0 --search-path extractor-pack --check-databases --check-undefined-labels --check-repeated-labels --check-redefined-labels --consistency-queries ql/consistency-queries -- ql/test/library-tests/dataflow/flowsources/aspremote
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
|
||||
3
.github/workflows/go-tests-other-os.yml
vendored
3
.github/workflows/go-tests-other-os.yml
vendored
@@ -7,9 +7,6 @@ on:
|
||||
- .github/workflows/go-tests-other-os.yml
|
||||
- .github/actions/**
|
||||
- codeql-workspace.yml
|
||||
- MODULE.bazel
|
||||
- .bazelrc
|
||||
- misc/bazel/**
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
3
.github/workflows/go-tests.yml
vendored
3
.github/workflows/go-tests.yml
vendored
@@ -15,9 +15,6 @@ on:
|
||||
- .github/workflows/go-tests.yml
|
||||
- .github/actions/**
|
||||
- codeql-workspace.yml
|
||||
- MODULE.bazel
|
||||
- .bazelrc
|
||||
- misc/bazel/**
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
28
.github/workflows/kotlin-build.yml
vendored
28
.github/workflows/kotlin-build.yml
vendored
@@ -1,28 +0,0 @@
|
||||
name: "Kotlin Build"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "java/kotlin-extractor/**"
|
||||
- "misc/bazel/**"
|
||||
- "misc/codegen/**"
|
||||
- "*.bazel*"
|
||||
- .github/workflows/kotlin-build.yml
|
||||
branches:
|
||||
- main
|
||||
- rc/*
|
||||
- codeql-cli-*
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: |
|
||||
bazel query //java/kotlin-extractor/...
|
||||
# only build the default version as a quick check that we can build from `codeql`
|
||||
# the full official build will be checked by QLucie
|
||||
bazel build //java/kotlin-extractor
|
||||
10
.github/workflows/ql-for-ql-build.yml
vendored
10
.github/workflows/ql-for-ql-build.yml
vendored
@@ -49,20 +49,20 @@ jobs:
|
||||
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-rust-cargo-${{ hashFiles('ql/**/Cargo.lock') }}
|
||||
- name: Release build
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
run: cd ql; ./scripts/create-extractor-pack.sh
|
||||
run: cd ql; ./scripts/create-extractor-pack.sh
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
- name: Cache compilation cache
|
||||
id: query-cache
|
||||
uses: ./.github/actions/cache-query-compilation
|
||||
with:
|
||||
with:
|
||||
key: run-ql-for-ql
|
||||
- name: Make database and analyze
|
||||
run: |
|
||||
./ql/target/release/buramu | tee deprecated.blame # Add a blame file for the extractor to parse.
|
||||
${CODEQL} database create -l=ql ${DB} --search-path "${{ github.workspace }}"
|
||||
${CODEQL} database create -l=ql --search-path ql/extractor-pack ${DB}
|
||||
${CODEQL} database analyze -j0 --format=sarif-latest --output=ql-for-ql.sarif ${DB} ql/ql/src/codeql-suites/ql-code-scanning.qls --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
|
||||
env:
|
||||
env:
|
||||
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
||||
DB: ${{ runner.temp }}/DB
|
||||
LGTM_INDEX_FILTERS: |
|
||||
|
||||
@@ -53,8 +53,8 @@ jobs:
|
||||
- name: Create database
|
||||
run: |
|
||||
"${CODEQL}" database create \
|
||||
--search-path "${{ github.workspace }}"
|
||||
--threads 4 \
|
||||
--search-path "ql/extractor-pack" \
|
||||
--threads 4 \
|
||||
--language ql --source-root "${{ github.workspace }}/repo" \
|
||||
"${{ runner.temp }}/database"
|
||||
env:
|
||||
|
||||
13
.github/workflows/ql-for-ql-tests.yml
vendored
13
.github/workflows/ql-for-ql-tests.yml
vendored
@@ -49,15 +49,15 @@ jobs:
|
||||
- name: Cache compilation cache
|
||||
id: query-cache
|
||||
uses: ./.github/actions/cache-query-compilation
|
||||
with:
|
||||
with:
|
||||
key: ql-for-ql-tests
|
||||
- name: Run QL tests
|
||||
run: |
|
||||
"${CODEQL}" test run --check-databases --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --search-path "${{ github.workspace }}" --consistency-queries ql/ql/consistency-queries --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" ql/ql/test
|
||||
"${CODEQL}" test run --check-databases --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --search-path "${{ github.workspace }}/ql/extractor-pack" --consistency-queries ql/ql/consistency-queries --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" ql/ql/test
|
||||
env:
|
||||
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
||||
|
||||
other-os:
|
||||
other-os:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest]
|
||||
@@ -65,7 +65,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install GNU tar
|
||||
- name: Install GNU tar
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
brew install gnu-tar
|
||||
@@ -100,7 +100,7 @@ jobs:
|
||||
- name: Run a single QL tests - Unix
|
||||
if: runner.os != 'Windows'
|
||||
run: |
|
||||
"${CODEQL}" test run --check-databases --search-path "${{ github.workspace }}" ql/ql/test/queries/style/DeadCode/DeadCode.qlref
|
||||
"${CODEQL}" test run --check-databases --search-path "${{ github.workspace }}/ql/extractor-pack" ql/ql/test/queries/style/DeadCode/DeadCode.qlref
|
||||
env:
|
||||
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
||||
- name: Run a single QL tests - Windows
|
||||
@@ -108,4 +108,5 @@ jobs:
|
||||
shell: pwsh
|
||||
run: |
|
||||
$Env:PATH += ";$(dirname ${{ steps.find-codeql.outputs.codeql-path }})"
|
||||
codeql test run --check-databases --search-path "${{ github.workspace }}" ql/ql/test/queries/style/DeadCode/DeadCode.qlref
|
||||
codeql test run --check-databases --search-path "${{ github.workspace }}/ql/extractor-pack" ql/ql/test/queries/style/DeadCode/DeadCode.qlref
|
||||
|
||||
2
.github/workflows/ruby-build.yml
vendored
2
.github/workflows/ruby-build.yml
vendored
@@ -7,7 +7,6 @@ on:
|
||||
- .github/workflows/ruby-build.yml
|
||||
- .github/actions/fetch-codeql/action.yml
|
||||
- codeql-workspace.yml
|
||||
- "shared/tree-sitter-extractor/**"
|
||||
branches:
|
||||
- main
|
||||
- "rc/*"
|
||||
@@ -17,7 +16,6 @@ on:
|
||||
- .github/workflows/ruby-build.yml
|
||||
- .github/actions/fetch-codeql/action.yml
|
||||
- codeql-workspace.yml
|
||||
- "shared/tree-sitter-extractor/**"
|
||||
branches:
|
||||
- main
|
||||
- "rc/*"
|
||||
|
||||
2
.github/workflows/ruby-dataset-measure.yml
vendored
2
.github/workflows/ruby-dataset-measure.yml
vendored
@@ -44,7 +44,7 @@ jobs:
|
||||
- name: Create database
|
||||
run: |
|
||||
codeql database create \
|
||||
--search-path "${{ github.workspace }}" \
|
||||
--search-path "${{ github.workspace }}/ruby/extractor-pack" \
|
||||
--threads 4 \
|
||||
--language ruby --source-root "${{ github.workspace }}/repo" \
|
||||
"${{ runner.temp }}/database"
|
||||
|
||||
4
.github/workflows/ruby-qltest.yml
vendored
4
.github/workflows/ruby-qltest.yml
vendored
@@ -64,10 +64,10 @@ jobs:
|
||||
- name: Cache compilation cache
|
||||
id: query-cache
|
||||
uses: ./.github/actions/cache-query-compilation
|
||||
with:
|
||||
with:
|
||||
key: ruby-qltest
|
||||
- name: Run QL tests
|
||||
run: |
|
||||
codeql test run --threads=0 --ram 50000 --search-path "${{ github.workspace }}" --check-databases --check-undefined-labels --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --consistency-queries ql/consistency-queries ql/test --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
|
||||
codeql test run --threads=0 --ram 50000 --search-path "${{ github.workspace }}/ruby/extractor-pack" --check-databases --check-undefined-labels --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --consistency-queries ql/consistency-queries ql/test --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
|
||||
15
.github/workflows/swift.yml
vendored
15
.github/workflows/swift.yml
vendored
@@ -68,6 +68,21 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./swift/actions/run-ql-tests
|
||||
integration-tests-linux:
|
||||
if: github.repository_owner == 'github'
|
||||
needs: build-and-test-linux
|
||||
runs-on: ubuntu-latest-xl
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./swift/actions/run-integration-tests
|
||||
integration-tests-macos:
|
||||
if: ${{ github.repository_owner == 'github' && github.event_name == 'pull_request' }}
|
||||
needs: build-and-test-macos
|
||||
runs-on: macos-12-xl
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./swift/actions/run-integration-tests
|
||||
clang-format:
|
||||
if : ${{ github.event_name == 'pull_request' }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
23
.github/workflows/zipmerge-test.yml
vendored
23
.github/workflows/zipmerge-test.yml
vendored
@@ -1,23 +0,0 @@
|
||||
name: "Test zipmerge code"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "misc/bazel/internal/zipmerge/**"
|
||||
- "MODULE.bazel"
|
||||
- ".bazelrc*"
|
||||
branches:
|
||||
- main
|
||||
- "rc/*"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: |
|
||||
bazel test //misc/bazel/internal/zipmerge:test --test_output=all
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -62,6 +62,3 @@ node_modules/
|
||||
|
||||
# Temporary folders for working with generated models
|
||||
.model-temp
|
||||
|
||||
# bazel-built in-tree extractor packs
|
||||
/*/extractor-pack
|
||||
|
||||
@@ -2,6 +2,4 @@
|
||||
# codeql is publicly forked by many users, and we don't want any LFS file polluting their working
|
||||
# copies. We therefore exclude everything by default.
|
||||
# For files required by bazel builds, use rules in `misc/bazel/lfs.bzl` to download them on demand.
|
||||
# we go for `fetchinclude` to something not exsiting rather than `fetchexclude = *` because the
|
||||
# former is easier to override (with `git -c` or a local git config) to fetch something specific
|
||||
fetchinclude = /nothing
|
||||
|
||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"omnisharp.autoStart": false,
|
||||
"cmake.sourceDirectory": "${workspaceFolder}/swift",
|
||||
"cmake.buildDirectory": "${workspaceFolder}/bazel-cmake-build"
|
||||
"cmake.buildDirectory": "${workspaceFolder}/bazel-cmake-build",
|
||||
"codeQL.githubDatabase.download": "never"
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
exports_files(["LICENSE"])
|
||||
|
||||
133
MODULE.bazel
133
MODULE.bazel
@@ -13,54 +13,19 @@ local_path_override(
|
||||
|
||||
# see https://registry.bazel.build/ for a list of available packages
|
||||
|
||||
bazel_dep(name = "platforms", version = "0.0.10")
|
||||
bazel_dep(name = "rules_go", version = "0.48.0")
|
||||
bazel_dep(name = "platforms", version = "0.0.9")
|
||||
bazel_dep(name = "rules_go", version = "0.47.0")
|
||||
bazel_dep(name = "rules_pkg", version = "0.10.1")
|
||||
bazel_dep(name = "rules_nodejs", version = "6.2.0-codeql.1")
|
||||
bazel_dep(name = "rules_python", version = "0.32.2")
|
||||
bazel_dep(name = "bazel_skylib", version = "1.6.1")
|
||||
bazel_dep(name = "rules_nodejs", version = "6.0.3")
|
||||
bazel_dep(name = "rules_python", version = "0.31.0")
|
||||
bazel_dep(name = "bazel_skylib", version = "1.5.0")
|
||||
bazel_dep(name = "abseil-cpp", version = "20240116.0", repo_name = "absl")
|
||||
bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json")
|
||||
bazel_dep(name = "fmt", version = "10.0.0")
|
||||
bazel_dep(name = "rules_kotlin", version = "1.9.4-codeql.1")
|
||||
bazel_dep(name = "gazelle", version = "0.37.0")
|
||||
bazel_dep(name = "rules_dotnet", version = "0.15.1")
|
||||
bazel_dep(name = "googletest", version = "1.14.0.bcr.1")
|
||||
bazel_dep(name = "rules_rust", version = "0.46.0")
|
||||
bazel_dep(name = "gazelle", version = "0.36.0")
|
||||
|
||||
bazel_dep(name = "buildifier_prebuilt", version = "6.4.0", dev_dependency = True)
|
||||
|
||||
crate = use_extension(
|
||||
"@rules_rust//crate_universe:extension.bzl",
|
||||
"crate",
|
||||
)
|
||||
crate.from_cargo(
|
||||
name = "py_deps",
|
||||
cargo_lockfile = "//python/extractor/tsg-python:Cargo.lock",
|
||||
manifests = [
|
||||
"//python/extractor/tsg-python:Cargo.toml",
|
||||
"//python/extractor/tsg-python/tsp:Cargo.toml",
|
||||
],
|
||||
)
|
||||
crate.from_cargo(
|
||||
name = "ruby_deps",
|
||||
cargo_lockfile = "//ruby/extractor:Cargo.lock",
|
||||
manifests = [
|
||||
"//ruby/extractor:Cargo.toml",
|
||||
"//ruby/extractor/codeql-extractor-fake-crate:Cargo.toml",
|
||||
],
|
||||
)
|
||||
use_repo(crate, "py_deps", "ruby_deps")
|
||||
|
||||
dotnet = use_extension("@rules_dotnet//dotnet:extensions.bzl", "dotnet")
|
||||
dotnet.toolchain(dotnet_version = "8.0.101")
|
||||
use_repo(dotnet, "dotnet_toolchains")
|
||||
|
||||
register_toolchains("@dotnet_toolchains//:all")
|
||||
|
||||
csharp_main_extension = use_extension("//csharp:paket.main_extension.bzl", "main_extension")
|
||||
use_repo(csharp_main_extension, "paket.main")
|
||||
|
||||
pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
|
||||
pip.parse(
|
||||
hub_name = "codegen_deps",
|
||||
@@ -85,99 +50,13 @@ use_repo(
|
||||
node = use_extension("@rules_nodejs//nodejs:extensions.bzl", "node")
|
||||
node.toolchain(
|
||||
name = "nodejs",
|
||||
node_urls = [
|
||||
"https://nodejs.org/dist/v{version}/{filename}",
|
||||
"https://mirrors.dotsrc.org/nodejs/release/v{version}/{filename}",
|
||||
],
|
||||
node_version = "18.15.0",
|
||||
)
|
||||
use_repo(node, "nodejs", "nodejs_toolchains")
|
||||
|
||||
kotlin_extractor_deps = use_extension("//java/kotlin-extractor:deps.bzl", "kotlin_extractor_deps")
|
||||
|
||||
# following list can be kept in sync by running `bazel mod tidy` in `codeql`
|
||||
use_repo(
|
||||
kotlin_extractor_deps,
|
||||
"codeql_kotlin_defaults",
|
||||
"codeql_kotlin_embeddable",
|
||||
"kotlin-compiler-1.5.0",
|
||||
"kotlin-compiler-1.5.10",
|
||||
"kotlin-compiler-1.5.20",
|
||||
"kotlin-compiler-1.5.30",
|
||||
"kotlin-compiler-1.6.0",
|
||||
"kotlin-compiler-1.6.20",
|
||||
"kotlin-compiler-1.7.0",
|
||||
"kotlin-compiler-1.7.20",
|
||||
"kotlin-compiler-1.8.0",
|
||||
"kotlin-compiler-1.9.0-Beta",
|
||||
"kotlin-compiler-1.9.20-Beta",
|
||||
"kotlin-compiler-2.0.0-RC1",
|
||||
"kotlin-compiler-2.0.20-Beta2",
|
||||
"kotlin-compiler-embeddable-1.5.0",
|
||||
"kotlin-compiler-embeddable-1.5.10",
|
||||
"kotlin-compiler-embeddable-1.5.20",
|
||||
"kotlin-compiler-embeddable-1.5.30",
|
||||
"kotlin-compiler-embeddable-1.6.0",
|
||||
"kotlin-compiler-embeddable-1.6.20",
|
||||
"kotlin-compiler-embeddable-1.7.0",
|
||||
"kotlin-compiler-embeddable-1.7.20",
|
||||
"kotlin-compiler-embeddable-1.8.0",
|
||||
"kotlin-compiler-embeddable-1.9.0-Beta",
|
||||
"kotlin-compiler-embeddable-1.9.20-Beta",
|
||||
"kotlin-compiler-embeddable-2.0.0-RC1",
|
||||
"kotlin-compiler-embeddable-2.0.20-Beta2",
|
||||
"kotlin-stdlib-1.5.0",
|
||||
"kotlin-stdlib-1.5.10",
|
||||
"kotlin-stdlib-1.5.20",
|
||||
"kotlin-stdlib-1.5.30",
|
||||
"kotlin-stdlib-1.6.0",
|
||||
"kotlin-stdlib-1.6.20",
|
||||
"kotlin-stdlib-1.7.0",
|
||||
"kotlin-stdlib-1.7.20",
|
||||
"kotlin-stdlib-1.8.0",
|
||||
"kotlin-stdlib-1.9.0-Beta",
|
||||
"kotlin-stdlib-1.9.20-Beta",
|
||||
"kotlin-stdlib-2.0.0-RC1",
|
||||
"kotlin-stdlib-2.0.20-Beta2",
|
||||
)
|
||||
|
||||
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
|
||||
go_sdk.download(version = "1.22.2")
|
||||
|
||||
go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
|
||||
go_deps.from_file(go_mod = "//go/extractor:go.mod")
|
||||
use_repo(go_deps, "org_golang_x_mod", "org_golang_x_tools")
|
||||
|
||||
lfs_files = use_repo_rule("//misc/bazel:lfs.bzl", "lfs_files")
|
||||
|
||||
lfs_files(
|
||||
name = "ripunzip-linux",
|
||||
srcs = ["//misc/ripunzip:ripunzip-linux"],
|
||||
executable = True,
|
||||
)
|
||||
|
||||
lfs_files(
|
||||
name = "ripunzip-windows",
|
||||
srcs = ["//misc/ripunzip:ripunzip-windows.exe"],
|
||||
executable = True,
|
||||
)
|
||||
|
||||
lfs_files(
|
||||
name = "ripunzip-macos",
|
||||
srcs = ["//misc/ripunzip:ripunzip-macos"],
|
||||
executable = True,
|
||||
)
|
||||
|
||||
lfs_files(
|
||||
name = "swift-resource-dir-linux",
|
||||
srcs = ["//swift/third_party/resource-dir:resource-dir-linux.zip"],
|
||||
)
|
||||
|
||||
lfs_files(
|
||||
name = "swift-resource-dir-macos",
|
||||
srcs = ["//swift/third_party/resource-dir:resource-dir-macos.zip"],
|
||||
)
|
||||
|
||||
register_toolchains(
|
||||
"@nodejs_toolchains//:all",
|
||||
)
|
||||
|
||||
@@ -6,16 +6,19 @@ provide:
|
||||
- "*/ql/consistency-queries/qlpack.yml"
|
||||
- "*/ql/automodel/src/qlpack.yml"
|
||||
- "*/ql/automodel/test/qlpack.yml"
|
||||
- "*/extractor-pack/codeql-extractor.yml"
|
||||
- "python/extractor/qlpack.yml"
|
||||
- "shared/**/qlpack.yml"
|
||||
- "cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml"
|
||||
- "go/ql/config/legacy-support/qlpack.yml"
|
||||
- "go/build/codeql-extractor-go/codeql-extractor.yml"
|
||||
- "csharp/ql/campaigns/Solorigate/lib/qlpack.yml"
|
||||
- "csharp/ql/campaigns/Solorigate/src/qlpack.yml"
|
||||
- "csharp/ql/campaigns/Solorigate/test/qlpack.yml"
|
||||
- "misc/legacy-support/*/qlpack.yml"
|
||||
- "misc/suite-helpers/qlpack.yml"
|
||||
- "ruby/extractor-pack/codeql-extractor.yml"
|
||||
- "swift/extractor-pack/codeql-extractor.yml"
|
||||
- "ql/extractor-pack/codeql-extractor.yml"
|
||||
- ".github/codeql/extensions/**/codeql-pack.yml"
|
||||
|
||||
versionPolicies:
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
"/*- Yaml dbscheme -*/",
|
||||
"/*- Blame dbscheme -*/",
|
||||
"/*- JSON dbscheme -*/",
|
||||
"/*- Python dbscheme -*/",
|
||||
"/*- Empty location -*/"
|
||||
"/*- Python dbscheme -*/"
|
||||
]
|
||||
}
|
||||
@@ -61,6 +61,10 @@
|
||||
"java/ql/src/utils/modelgenerator/internal/CaptureModels.qll",
|
||||
"csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll"
|
||||
],
|
||||
"Model as Data Generation Java/C# - CaptureModelsPrinting": [
|
||||
"java/ql/src/utils/modelgenerator/internal/CaptureModelsPrinting.qll",
|
||||
"csharp/ql/src/utils/modelgenerator/internal/CaptureModelsPrinting.qll"
|
||||
],
|
||||
"Sign Java/C#": [
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/Sign.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/Sign.qll"
|
||||
@@ -181,6 +185,11 @@
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysisImports.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysisImports.qll"
|
||||
],
|
||||
"C++ IR ValueNumberingImports": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingImports.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingImports.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingImports.qll"
|
||||
],
|
||||
"IR SSA SSAConstruction": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll"
|
||||
@@ -355,9 +364,5 @@
|
||||
"Python model summaries test extension": [
|
||||
"python/ql/test/library-tests/dataflow/model-summaries/InlineTaintTest.ext.yml",
|
||||
"python/ql/test/library-tests/dataflow/model-summaries/NormalDataflowTest.ext.yml"
|
||||
],
|
||||
"shared tree-sitter extractor cargo.toml": [
|
||||
"shared/tree-sitter-extractor/Cargo.toml",
|
||||
"ruby/extractor/codeql-extractor-fake-crate/Cargo.toml"
|
||||
]
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,4 +0,0 @@
|
||||
description: Revert support for using-enum declarations.
|
||||
compatibility: partial
|
||||
usings.rel: run usings.qlo
|
||||
using_container.rel: run using_container.qlo
|
||||
@@ -1,14 +0,0 @@
|
||||
class UsingEntry extends @using {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Element extends @element {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
from UsingEntry u, Element parent, int kind
|
||||
where
|
||||
usings(u, _, _, kind) and
|
||||
using_container(parent, u) and
|
||||
kind != 3
|
||||
select parent, u
|
||||
@@ -1,17 +0,0 @@
|
||||
class UsingEntry extends @using {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Element extends @element {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Location extends @location_default {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
from UsingEntry u, Element target, Location loc, int kind
|
||||
where
|
||||
usings(u, target, loc, kind) and
|
||||
kind != 3
|
||||
select u, target, loc
|
||||
@@ -1,17 +0,0 @@
|
||||
class Expr extends @expr {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Location extends @location_expr {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
predicate isExprWithNewBuiltin(Expr expr) {
|
||||
exists(int kind | exprs(expr, kind, _) | 364 <= kind and kind <= 384)
|
||||
}
|
||||
|
||||
from Expr expr, int kind, int kind_new, Location location
|
||||
where
|
||||
exprs(expr, kind, location) and
|
||||
if isExprWithNewBuiltin(expr) then kind_new = 1 else kind_new = kind
|
||||
select expr, kind_new, location
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,3 +0,0 @@
|
||||
description: Add new builtin operations
|
||||
compatibility: partial
|
||||
exprs.rel: run exprs.qlo
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
||||
description: Support destroying deletes
|
||||
compatibility: full
|
||||
@@ -6,7 +6,7 @@ pkg_files(
|
||||
["**"],
|
||||
exclude = ["BUILD.bazel"],
|
||||
),
|
||||
prefix = "downgrades",
|
||||
prefix = "cpp/downgrades",
|
||||
strip_prefix = strip_prefix.from_pkg(),
|
||||
visibility = ["//cpp:__pkg__"],
|
||||
)
|
||||
|
||||
@@ -5,9 +5,11 @@ package(default_visibility = ["//cpp:__pkg__"])
|
||||
pkg_files(
|
||||
name = "dbscheme",
|
||||
srcs = ["semmlecode.cpp.dbscheme"],
|
||||
prefix = "cpp",
|
||||
)
|
||||
|
||||
pkg_files(
|
||||
name = "dbscheme-stats",
|
||||
srcs = ["semmlecode.cpp.dbscheme.stats"],
|
||||
prefix = "cpp",
|
||||
)
|
||||
|
||||
@@ -1,43 +1,3 @@
|
||||
## 1.3.0
|
||||
|
||||
### New Features
|
||||
|
||||
* Models-as-data alert provenance information has been extended to the C/C++ language. Any qltests that include the edges relation in their output (for example, `.qlref`s that reference path-problem queries) will need to be have their expected output updated accordingly.
|
||||
* Added subclasses of `BuiltInOperations` for `__builtin_has_attribute`, `__builtin_is_corresponding_member`, `__builtin_is_pointer_interconvertible_with_class`, `__is_assignable_no_precondition_check`, `__is_bounded_array`, `__is_convertible`, `__is_corresponding_member`, `__is_nothrow_convertible`, `__is_pointer_interconvertible_with_class`, `__is_referenceable`, `__is_same_as`, `__is_trivially_copy_assignable`, `__is_unbounded_array`, `__is_valid_winrt_type`, `_is_win_class`, `__is_win_interface`, `__reference_binds_to_temporary`, `__reference_constructs_from_temporary`, and `__reference_converts_from_temporary`.
|
||||
* The class `NewArrayExpr` adds a predicate `getArraySize()` to allow a more convenient way to access the static size of the array when the extent is missing.
|
||||
|
||||
## 1.2.0
|
||||
|
||||
### New Features
|
||||
|
||||
* The syntax for models-as-data rows has been extended to make it easier to select sources, sinks, and summaries that involve templated functions and classes. Additionally, the syntax has also been extended to make it easier to specify models with arbitrary levels of indirection. See `dataflow/ExternalFlow.qll` for the updated documentation and specification for the model format.
|
||||
* It is now possible to extend the classes `AllocationFunction` and `DeallocationFunction` via data extensions. Extensions of these classes should be added to the `lib/ext/allocation` and `lib/ext/deallocation` directories respectively.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The queries "Potential double free" (`cpp/double-free`) and "Potential use after free" (`cpp/use-after-free`) now produce fewer false positives.
|
||||
* The "Guards" library (`semmle.code.cpp.controlflow.Guards`) now also infers guards from calls to the builtin operation `__builtin_expect`. As a result, some queries may produce fewer false positives.
|
||||
|
||||
## 1.1.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.1.0
|
||||
|
||||
### New Features
|
||||
|
||||
* Data models can now be added with data extensions. In this way source, sink and summary models can be added in extension `.model.yml` files, rather than by writing classes in QL code. New models should be added in the `lib/ext` folder.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* A partial model for the `Boost.Asio` network library has been added. This includes sources, sinks and summaries for certain functions in `Boost.Asio`, such as `read_until` and `write`.
|
||||
|
||||
## 1.0.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* CodeQL package management is now generally available, and all GitHub-produced CodeQL packages have had their version numbers increased to 1.0.0.
|
||||
|
||||
## 0.13.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
## 1.0.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
* CodeQL package management is now generally available, and all GitHub-produced CodeQL packages have had their version numbers increased to 1.0.0.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* A `isDestroyingDeleteDeallocation` predicate was added to the `NewOrNewArrayExpr` and `DeleteOrDeleteArrayExpr` classes to indicate whether the deallocation function is a destroying delete.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* A `UsingEnumDeclarationEntry` class has been added for C++ `using enum` declarations. As part of this, synthesized `UsingDeclarationEntry`s are no longer emitted for individual enumerators of the referenced enumeration.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Improved performance of alias analysis of large function bodies. In rare cases, alerts that depend on alias analysis of large function bodies may be affected.
|
||||
@@ -1,9 +0,0 @@
|
||||
## 1.1.0
|
||||
|
||||
### New Features
|
||||
|
||||
* Data models can now be added with data extensions. In this way source, sink and summary models can be added in extension `.model.yml` files, rather than by writing classes in QL code. New models should be added in the `lib/ext` folder.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* A partial model for the `Boost.Asio` network library has been added. This includes sources, sinks and summaries for certain functions in `Boost.Asio`, such as `read_until` and `write`.
|
||||
@@ -1,3 +0,0 @@
|
||||
## 1.1.1
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,11 +0,0 @@
|
||||
## 1.2.0
|
||||
|
||||
### New Features
|
||||
|
||||
* The syntax for models-as-data rows has been extended to make it easier to select sources, sinks, and summaries that involve templated functions and classes. Additionally, the syntax has also been extended to make it easier to specify models with arbitrary levels of indirection. See `dataflow/ExternalFlow.qll` for the updated documentation and specification for the model format.
|
||||
* It is now possible to extend the classes `AllocationFunction` and `DeallocationFunction` via data extensions. Extensions of these classes should be added to the `lib/ext/allocation` and `lib/ext/deallocation` directories respectively.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The queries "Potential double free" (`cpp/double-free`) and "Potential use after free" (`cpp/use-after-free`) now produce fewer false positives.
|
||||
* The "Guards" library (`semmle.code.cpp.controlflow.Guards`) now also infers guards from calls to the builtin operation `__builtin_expect`. As a result, some queries may produce fewer false positives.
|
||||
@@ -1,7 +0,0 @@
|
||||
## 1.3.0
|
||||
|
||||
### New Features
|
||||
|
||||
* Models-as-data alert provenance information has been extended to the C/C++ language. Any qltests that include the edges relation in their output (for example, `.qlref`s that reference path-problem queries) will need to be have their expected output updated accordingly.
|
||||
* Added subclasses of `BuiltInOperations` for `__builtin_has_attribute`, `__builtin_is_corresponding_member`, `__builtin_is_pointer_interconvertible_with_class`, `__is_assignable_no_precondition_check`, `__is_bounded_array`, `__is_convertible`, `__is_corresponding_member`, `__is_nothrow_convertible`, `__is_pointer_interconvertible_with_class`, `__is_referenceable`, `__is_same_as`, `__is_trivially_copy_assignable`, `__is_unbounded_array`, `__is_valid_winrt_type`, `_is_win_class`, `__is_win_interface`, `__reference_binds_to_temporary`, `__reference_constructs_from_temporary`, and `__reference_converts_from_temporary`.
|
||||
* The class `NewArrayExpr` adds a predicate `getArraySize()` to allow a more convenient way to access the static size of the array when the extent is missing.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.3.0
|
||||
lastReleaseVersion: 0.13.1
|
||||
|
||||
88
cpp/ql/lib/experimental/buildless/ASTSig.qll
Normal file
88
cpp/ql/lib/experimental/buildless/ASTSig.qll
Normal file
@@ -0,0 +1,88 @@
|
||||
import cpp
|
||||
|
||||
/*
|
||||
The syntax of a C++ program.
|
||||
*/
|
||||
signature module BuildlessASTSig
|
||||
{
|
||||
class Node;
|
||||
predicate nodeLocation(Node node, Location location);
|
||||
|
||||
// Parent/child relationship between AST nodes
|
||||
predicate edge(Node parent, int index, Node child);
|
||||
|
||||
// Include graph
|
||||
predicate userInclude(Node include, string path);
|
||||
predicate systemInclude(Node include, string path);
|
||||
|
||||
// Namespaces
|
||||
predicate namespace(Node ns);
|
||||
predicate namespaceName(Node ns, string name);
|
||||
predicate namespaceMember(Node ns, Node member);
|
||||
|
||||
// Functions
|
||||
predicate function(Node fn);
|
||||
predicate functionBody(Node fn, Node body);
|
||||
predicate functionReturn(Node fn, Node returnType);
|
||||
predicate functionName(Node fn, string name);
|
||||
predicate functionParameter(Node fn, int i, Node parameterDecl);
|
||||
predicate functionDefinition(Node fn); // If a definition as opposed to a declaration
|
||||
|
||||
// Statements
|
||||
predicate stmt(Node node);
|
||||
predicate blockStmt(Node stmt);
|
||||
predicate blockMember(Node stmt, int index, Node child);
|
||||
predicate ifStmt(Node stmt, Node condition, Node thenBranch);
|
||||
predicate ifStmt(Node tmt, Node condition, Node thenBranch, Node elseBranch);
|
||||
predicate whileStmt(Node stmt, Node condition, Node body);
|
||||
predicate doWhileStmt(Node stmt, Node condition, Node body);
|
||||
predicate forStmt(Node stmt, Node init, Node condition, Node update, Node body);
|
||||
predicate exprStmt(Node stmt, Node expr);
|
||||
predicate returnStmt(Node stmt, Node expr);
|
||||
predicate returnVoidStmt(Node stmt);
|
||||
// etc
|
||||
|
||||
// Types
|
||||
predicate type(Node type);
|
||||
predicate ptrType(Node type, Node element);
|
||||
predicate refType(Node type, Node element);
|
||||
predicate constType(Node type, Node element);
|
||||
predicate rvalueRefType(Node type, Node element);
|
||||
predicate arrayType(Node type, Node element, Node size);
|
||||
predicate arrayType(Node type, Node element);
|
||||
predicate typename(Node node, string name); // Any named type, including built-in types
|
||||
predicate templated(Node node);
|
||||
predicate typeDefinition(Node node); // If a definition as opposed to a declaration
|
||||
|
||||
predicate classOrStructDefinition(Node node);
|
||||
predicate classMember(Node classOrStruct, int child, Node member);
|
||||
|
||||
// Templates
|
||||
predicate templateParameter(Node node, int i, Node parameter);
|
||||
predicate typeParameter(Node templateParameter, Node type, Node parameter);
|
||||
predicate typeParameterDefault(Node templateParameter, Node defaultTypeOrValue);
|
||||
|
||||
// Declarations
|
||||
predicate variableDeclaration(Node decl);
|
||||
predicate variableDeclarationType(Node decl, Node type);
|
||||
predicate variableDeclarationEntry(Node decl, int index, Node entry);
|
||||
predicate variableDeclarationEntryInitializer(Node entry, Node initializer);
|
||||
predicate variableName(Node entry, string name);
|
||||
predicate ptrEntry(Node entry, Node element);
|
||||
predicate refEntry(Node entry, Node element);
|
||||
predicate rvalueRefEntry(Node entry, Node element);
|
||||
predicate arrayEntry(Node entry, Node element); // ?? Size
|
||||
|
||||
// Expressions
|
||||
predicate expression(Node node);
|
||||
predicate prefixExpr(Node expr, string operator, Node operand);
|
||||
predicate postfixExpr(Node expr, Node operand, string operator);
|
||||
predicate binaryExpr(Node expr, Node lhs, string operator, Node rhs);
|
||||
predicate castExpr(Node expr, Node type, Node operand);
|
||||
predicate callExpr(Node call);
|
||||
predicate callArgument(Node call, int i, Node arg);
|
||||
predicate callReceiver(Node call, Node receiver);
|
||||
predicate accessExpr(Node expr, string name);
|
||||
predicate literal(Node expr, string value);
|
||||
predicate stringLiteral(Node expr, string value);
|
||||
}
|
||||
304
cpp/ql/lib/experimental/buildless/CompiledAST.qll
Normal file
304
cpp/ql/lib/experimental/buildless/CompiledAST.qll
Normal file
@@ -0,0 +1,304 @@
|
||||
import cpp
|
||||
import ASTSig
|
||||
|
||||
module CompiledAST implements BuildlessASTSig {
|
||||
private class SourceLocation extends Location {
|
||||
SourceLocation() { not this.hasLocationInfo(_, 0, 0, 0, 0) }
|
||||
}
|
||||
|
||||
private Type reachableType(Type type) {
|
||||
result = type or
|
||||
result = reachableType(type).stripTopLevelSpecifiers() or
|
||||
result = reachableType(type).(PointerType).getBaseType() or
|
||||
result = reachableType(type).(ReferenceType).getBaseType()
|
||||
}
|
||||
|
||||
private class SourceDeclEntry extends DeclarationEntry {
|
||||
SourceDeclEntry() {
|
||||
not this.isAffectedByMacro() and
|
||||
not this.isFromTemplateInstantiation(_) and
|
||||
not this.isInMacroExpansion() and
|
||||
not this.getDeclaration().isInMacroExpansion() and
|
||||
this.getLocation() instanceof SourceLocation and
|
||||
not this.(FunctionDeclarationEntry).getDeclaration().isCompilerGenerated()
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TNode =
|
||||
// TFunction(SourceLocation loc) { exists(Function f | f.getLocation() = loc) } or
|
||||
TStatement(SourceLocation loc) { exists(Stmt s | s.getLocation() = loc) } or
|
||||
TDeclaration(SourceDeclEntry decl) or
|
||||
TExpression(SourceLocation loc) { exists(Expr e | e.getLocation() = loc) } or
|
||||
TFunctionCallName(SourceLocation loc) { exists(FunctionCall c | c.getLocation() = loc) } or
|
||||
TDeclarationType(SourceDeclEntry decl, Type type) { type = reachableType(decl.getType()) } or
|
||||
TNamespaceDeclaration(NamespaceDeclarationEntry ns) { any() } or
|
||||
TInclude(Include i)
|
||||
|
||||
class Node extends TNode {
|
||||
string toString() { result = "node" }
|
||||
|
||||
SourceLocation getLocation() {
|
||||
this = TStatement(result) or
|
||||
result = this.getDeclaration().getLocation() or
|
||||
this = TExpression(result) or
|
||||
this = TFunctionCallName(result) or
|
||||
result = this.getVariableDeclaration().getLocation() or
|
||||
result = this.getNamespaceDeclaration().getLocation() or
|
||||
result = this.getInclude().getLocation()
|
||||
}
|
||||
|
||||
Include getInclude() { this = TInclude(result) }
|
||||
|
||||
Stmt getStmt() { this = TStatement(result.getLocation()) }
|
||||
|
||||
Function getFunction() {
|
||||
result = this.getDeclaration().getDeclaration() and
|
||||
not result.isFromTemplateInstantiation(_) and
|
||||
not result.isCompilerGenerated()
|
||||
}
|
||||
|
||||
SourceDeclEntry getDeclaration() { this = TDeclaration(result) }
|
||||
|
||||
NamespaceDeclarationEntry getNamespaceDeclaration() { this = TNamespaceDeclaration(result) }
|
||||
|
||||
Type getType() { this = TDeclarationType(_, result) }
|
||||
|
||||
SourceDeclEntry getVariableDeclaration() { this = TDeclarationType(result, _) }
|
||||
|
||||
Expr getExpr() { this = TExpression(result.getLocation()) }
|
||||
|
||||
FunctionCall getFunctionCallName() { this = TFunctionCallName(result.getLocation()) }
|
||||
}
|
||||
|
||||
predicate nodeLocation(Node node, Location location) { location = node.getLocation() }
|
||||
|
||||
// Include graph
|
||||
predicate userInclude(Node include, string path) {
|
||||
exists(string head | head = include.getInclude().getHead() |
|
||||
path = head.substring(1, head.length() - 1) and head.charAt(0) = "\""
|
||||
)
|
||||
}
|
||||
|
||||
predicate systemInclude(Node include, string path) {
|
||||
exists(string head | head = include.getInclude().getHead() |
|
||||
path = head.substring(1, head.length() - 1) and head.charAt(0) = "<"
|
||||
)
|
||||
}
|
||||
|
||||
// Functions
|
||||
predicate function(Node fn) { exists(fn.getFunction()) }
|
||||
|
||||
predicate functionBody(Node fn, Node body) { body.getStmt() = fn.getFunction().getBlock() }
|
||||
|
||||
predicate functionReturn(Node fn, Node returnType) {
|
||||
returnType.getVariableDeclaration() = fn.getDeclaration() and
|
||||
fn.getDeclaration().(FunctionDeclarationEntry).getDeclaration().getType() = returnType.getType()
|
||||
}
|
||||
|
||||
predicate functionName(Node fn, string name) { name = fn.getFunction().getName() }
|
||||
|
||||
predicate functionParameter(Node fn, int i, Node parameterDecl) {
|
||||
functionParameter0(fn, i, parameterDecl) and
|
||||
not exists(Node param2 | functionParameter0(fn, i, param2) |
|
||||
param2.getLocation().getStartLine() < parameterDecl.getLocation().getStartLine()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate functionParameter0(Node fn, int i, Node parameterDecl) {
|
||||
fn.getFunction().getParameter(i).getADeclarationEntry() = parameterDecl.getDeclaration() and
|
||||
fn.getLocation().getFile() = parameterDecl.getLocation().getFile() and
|
||||
fn.getLocation().getStartLine() <= parameterDecl.getLocation().getStartLine()
|
||||
}
|
||||
|
||||
// Statements
|
||||
predicate stmt(Node node) { exists(node.getStmt()) }
|
||||
|
||||
predicate blockStmt(Node stmt) { stmt.getStmt() instanceof BlockStmt }
|
||||
|
||||
predicate blockMember(Node stmt, int index, Node child) {
|
||||
child.getStmt() = stmt.getStmt().(BlockStmt).getChild(index)
|
||||
}
|
||||
|
||||
predicate ifStmt(Node stmt, Node condition, Node thenBranch) { none() }
|
||||
|
||||
predicate ifStmt(Node tmt, Node condition, Node thenBranch, Node elseBranch) { none() }
|
||||
|
||||
predicate whileStmt(Node stmt, Node condition, Node body) { none() }
|
||||
|
||||
predicate doWhileStmt(Node stmt, Node condition, Node body) { none() }
|
||||
|
||||
predicate forStmt(Node stmt, Node init, Node condition, Node update, Node body) { none() }
|
||||
|
||||
predicate exprStmt(Node stmt, Node expr) { none() }
|
||||
|
||||
predicate returnStmt(Node stmt, Node expr) { none() }
|
||||
|
||||
predicate returnVoidStmt(Node stmt) { none() }
|
||||
|
||||
// etc
|
||||
// Types
|
||||
predicate ptrType(Node node, Node element) {
|
||||
exists(PointerType type, SourceDeclEntry e |
|
||||
node = TDeclarationType(e, type) and
|
||||
element = TDeclarationType(e, type.getBaseType())
|
||||
)
|
||||
}
|
||||
|
||||
predicate refType(Node node, Node element) {
|
||||
exists(ReferenceType type, SourceDeclEntry e |
|
||||
node = TDeclarationType(e, type) and
|
||||
element = TDeclarationType(e, type.getBaseType())
|
||||
)
|
||||
}
|
||||
|
||||
predicate rvalueRefType(Node type, Node element) { none() }
|
||||
|
||||
predicate arrayType(Node type, Node element, Node size) { none() }
|
||||
|
||||
predicate arrayType(Node type, Node element) { none() }
|
||||
|
||||
predicate typename(Node node, string name) {
|
||||
exists(Class c | c = node.getDeclaration().getDeclaration() |
|
||||
not c.isAnonymous() and c.getName() = name
|
||||
)
|
||||
or
|
||||
name = node.getType().getName()
|
||||
}
|
||||
|
||||
predicate templated(Node node) { none() }
|
||||
|
||||
predicate classOrStructDefinition(Node node) {
|
||||
node.getDeclaration().getDeclaration() instanceof Class
|
||||
}
|
||||
|
||||
predicate classMember(Node classOrStruct, int child, Node member) {
|
||||
classOrStruct.getDeclaration().getDeclaration().(Class).getAMember() =
|
||||
member.getDeclaration().getDeclaration() and
|
||||
child = 0 and
|
||||
classOrStruct.getLocation().getFile() = member.getLocation().getFile() // TODO: Disambiguate
|
||||
// and not member.getDeclaration().getDeclaration() instanceof FriendDecl
|
||||
}
|
||||
|
||||
// Templates
|
||||
predicate templateParameter(Node node, int i, Node parameter) { none() }
|
||||
|
||||
predicate typeParameter(Node templateParameter, Node type, Node parameter) { none() }
|
||||
|
||||
predicate typeParameterDefault(Node templateParameter, Node defaultTypeOrValue) { none() }
|
||||
|
||||
// Declarations
|
||||
predicate variableDeclaration(Node decl) {
|
||||
decl.getDeclaration() instanceof VariableDeclarationEntry
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate variableDeclarationType2(Node decl, Node type) {
|
||||
decl.getDeclaration() = type.getVariableDeclaration()
|
||||
}
|
||||
|
||||
predicate variableDeclarationType(Node decl, Node type) {
|
||||
variableDeclarationType2(decl, type) and
|
||||
type.getType() = decl.getDeclaration().getType()
|
||||
}
|
||||
|
||||
predicate variableDeclarationEntry(Node decl, int index, Node entry) { none() }
|
||||
|
||||
predicate variableDeclarationEntryInitializer(Node entry, Node initializer) { none() }
|
||||
|
||||
predicate variableName(Node decl, string name) {
|
||||
decl.getDeclaration().(VariableDeclarationEntry).getName() = name
|
||||
}
|
||||
|
||||
predicate ptrEntry(Node entry, Node element) { none() }
|
||||
|
||||
predicate refEntry(Node entry, Node element) { none() }
|
||||
|
||||
predicate rvalueRefEntry(Node entry, Node element) { none() }
|
||||
|
||||
predicate arrayEntry(Node entry, Node element) { none() }
|
||||
|
||||
// Expressions
|
||||
predicate expression(Node node) { exists(node.getExpr()) or exists(node.getFunctionCallName()) }
|
||||
|
||||
predicate prefixExpr(Node expr, string operator, Node operand) { none() }
|
||||
|
||||
predicate postfixExpr(Node expr, Node operand, string operator) { none() }
|
||||
|
||||
predicate binaryExpr(Node expr, Node lhs, string operator, Node rhs) { none() }
|
||||
|
||||
predicate castExpr(Node expr, Node type, Node operand) { none() }
|
||||
|
||||
predicate callExpr(Node call) { call.getExpr() instanceof Call }
|
||||
|
||||
predicate callArgument(Node call, int i, Node arg) {
|
||||
arg.getExpr() = call.getExpr().(Call).getArgument(i)
|
||||
}
|
||||
|
||||
predicate callReceiver(Node call, Node receiver) {
|
||||
receiver.getFunctionCallName() = call.getExpr()
|
||||
}
|
||||
|
||||
predicate accessExpr(Node expr, string name) {
|
||||
expr.getExpr().(VariableAccess).getTarget().getName() = name or
|
||||
expr.getFunctionCallName().getTarget().getName() = name
|
||||
}
|
||||
|
||||
predicate literal(Node expr, string value) { expr.getExpr().(Literal).toString() = value }
|
||||
|
||||
predicate stringLiteral(Node expr, string value) {
|
||||
expr.getExpr().(StringLiteral).getValue() = value
|
||||
}
|
||||
|
||||
predicate type(Node node) { node = TDeclarationType(_, _) }
|
||||
|
||||
predicate constType(Node node, Node element) {
|
||||
exists(SpecifiedType type, SourceDeclEntry e |
|
||||
node = TDeclarationType(e, type) and
|
||||
element = TDeclarationType(e, type.getBaseType()) and
|
||||
type.isConst()
|
||||
)
|
||||
}
|
||||
|
||||
predicate namespace(Node ns) { exists(ns.getNamespaceDeclaration()) }
|
||||
|
||||
predicate namespaceName(Node ns, string name) {
|
||||
ns.getNamespaceDeclaration().getNamespace().getName() = name
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate namespaceNamespace(Node ns, Node child) {
|
||||
ns.getNamespaceDeclaration().getNamespace().getAChildNamespace() =
|
||||
child.getNamespaceDeclaration().getNamespace() and
|
||||
ns.getLocation().getFile() = child.getLocation().getFile()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate namespaceDecl(Node ns, Node child) {
|
||||
child.getDeclaration().getDeclaration() =
|
||||
ns.getNamespaceDeclaration().getNamespace().getADeclaration() and
|
||||
ns.getLocation().getFile() = child.getLocation().getFile() and
|
||||
ns.getLocation().getStartLine() <= child.getLocation().getStartLine()
|
||||
}
|
||||
|
||||
predicate namespaceMember(Node ns, Node member) {
|
||||
namespaceNamespace(ns, member) or
|
||||
namespaceDecl(ns, member)
|
||||
}
|
||||
|
||||
predicate edge(Node parent, int index, Node child) {
|
||||
namespaceMember(parent, child) and index = 0
|
||||
or
|
||||
classMember(parent, index, child)
|
||||
or
|
||||
blockMember(parent, index, child)
|
||||
}
|
||||
|
||||
predicate typeDefinition(Node node) {
|
||||
node.getDeclaration().(TypeDeclarationEntry).isDefinition()
|
||||
}
|
||||
|
||||
predicate functionDefinition(Node fn) {
|
||||
fn.getDeclaration().(FunctionDeclarationEntry).isDefinition()
|
||||
}
|
||||
}
|
||||
282
cpp/ql/lib/experimental/buildless/Model.qll
Normal file
282
cpp/ql/lib/experimental/buildless/Model.qll
Normal file
@@ -0,0 +1,282 @@
|
||||
import AST
|
||||
|
||||
module BuildlessModel<BuildlessASTSig Sig> {
|
||||
module AST = BuildlessAST<Sig>;
|
||||
|
||||
private string getQualifiedName(AST::SourceNamespace ns) {
|
||||
not exists(AST::SourceNamespace p | ns = p.getAChild()) and result = ns.getName()
|
||||
or
|
||||
exists(AST::SourceNamespace p | ns = p.getAChild() and ns != p |
|
||||
result = getQualifiedName(p) + "::" + ns.getName()
|
||||
)
|
||||
}
|
||||
|
||||
private newtype TElement =
|
||||
TNamespace(string fqn) { fqn = getQualifiedName(_) } or
|
||||
TASTNode(AST::SourceElement node) { any() }
|
||||
|
||||
/*
|
||||
Any compile-time concept that can be named.
|
||||
*/
|
||||
class Entity extends string
|
||||
{
|
||||
bindingset[this] Entity() { any() }
|
||||
}
|
||||
|
||||
/*
|
||||
An entity that contains named members.
|
||||
*/
|
||||
class Scope extends Entity
|
||||
{
|
||||
bindingset[this] Scope() { any() }
|
||||
|
||||
Member getAMember() { result = this.getAMember(_) }
|
||||
|
||||
abstract Member getAMember(string name);
|
||||
}
|
||||
|
||||
/*
|
||||
An entity that is a member of a scope.
|
||||
*/
|
||||
class Member extends Entity
|
||||
{
|
||||
bindingset[this] Member() { any() }
|
||||
|
||||
abstract string getName();
|
||||
abstract Scope getParent();
|
||||
}
|
||||
|
||||
class Namespace2 extends Member, Scope
|
||||
{
|
||||
AST::SourceNamespace ns;
|
||||
|
||||
Namespace2() { this = "::" + getQualifiedName(ns) }
|
||||
|
||||
AST::SourceNamespace getAstNode() { result = ns }
|
||||
|
||||
override Namespace2 getParent() { result.getAstNode() = ns.getParent() }
|
||||
|
||||
override string getName() { result = ns.getName() }
|
||||
|
||||
override Member getAMember(string name) {
|
||||
result = this.getMemberNamespace(name)
|
||||
// !! Types
|
||||
}
|
||||
|
||||
Namespace2 getMemberNamespace(string name) {
|
||||
result.getParent() = this and result.getName() = name
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Type extends Member, Scope {
|
||||
Type() { exists(SourceTypeDeclaration t | t.getMangledName() = this) }
|
||||
|
||||
AST::SourceType getAstNode() { result = this.getADeclaration().getSourceNode() }
|
||||
|
||||
// string toString() { result = "i am a type" }
|
||||
override string getName() { result = this.getADeclaration().getName() }
|
||||
|
||||
Location getLocation() { result = this.getADefinition().getLocation() }
|
||||
|
||||
SourceTypeDeclaration getADeclaration() { result.getMangledName() = this }
|
||||
|
||||
SourceTypeDefinition getADefinition() { result.getMangledName() = this }
|
||||
|
||||
override Member getAMember(string name)
|
||||
{
|
||||
result = getMemberType(name)
|
||||
}
|
||||
|
||||
Type getMemberType(string name)
|
||||
{
|
||||
none()
|
||||
}
|
||||
|
||||
Namespace2 getParentNamespace() {
|
||||
result.getAstNode() = this.getADeclaration().getParentNamespace()
|
||||
}
|
||||
|
||||
Type getParentType() { result.getADeclaration() = this.getADeclaration().getParentType() }
|
||||
|
||||
override Scope getParent() { result = this.getParentNamespace() or result = this.getParentType() }
|
||||
|
||||
string getFullyQualifiedName() { result = this.getADeclaration().getFullyQualifiedName() }
|
||||
|
||||
Field getAField() { result.getParentType() = this }
|
||||
}
|
||||
|
||||
private Type lookupNameInType(Type type, string name)
|
||||
{
|
||||
// Is the name a member of this type?
|
||||
|
||||
// Is the name in the same scope as the type?
|
||||
|
||||
// Is the name in global scope?
|
||||
|
||||
// TODO!
|
||||
none()
|
||||
}
|
||||
|
||||
class Field extends string {
|
||||
Type containingType;
|
||||
SourceTypeDefinition containingTypeDef;
|
||||
AST::SourceVariableDeclaration fieldDef;
|
||||
|
||||
Field() {
|
||||
containingType.getADefinition() = containingTypeDef and
|
||||
fieldDef = containingTypeDef.getAField() and
|
||||
this = containingTypeDef.getMangledName() + "::" + fieldDef.getName()
|
||||
}
|
||||
|
||||
Location getLocation() { result = fieldDef.getLocation() }
|
||||
|
||||
Type getParentType() { result = containingType }
|
||||
|
||||
string getName() { result = fieldDef.getName() }
|
||||
|
||||
// TODO: The type of the field
|
||||
|
||||
}
|
||||
|
||||
class Element extends TElement {
|
||||
string toString() { result = "element" }
|
||||
}
|
||||
|
||||
class Namespace extends Element, TNamespace {
|
||||
string getFullyQualifiedName() { this = TNamespace(result) }
|
||||
|
||||
override string toString() { result = "namespace " + this.getFullyQualifiedName() }
|
||||
|
||||
NamespaceDeclaration getADeclaration() { result.getNamespace() = this }
|
||||
}
|
||||
|
||||
class SourceElement extends Element, TASTNode {
|
||||
AST::SourceElement node;
|
||||
|
||||
SourceElement() { this = TASTNode(node) }
|
||||
|
||||
Location getLocation() { result = node.getLocation() }
|
||||
|
||||
AST::SourceElement getSourceNode() { result = node }
|
||||
}
|
||||
|
||||
class SourceDeclaration extends SourceElement, TASTNode {
|
||||
abstract SourceDeclaration getParent();
|
||||
|
||||
abstract string getName();
|
||||
|
||||
abstract string getMangledName();
|
||||
|
||||
abstract predicate isDefinition();
|
||||
}
|
||||
|
||||
abstract class SourceDefinition extends SourceDeclaration { }
|
||||
|
||||
class NamespaceDeclaration extends SourceDeclaration {
|
||||
AST::SourceNamespace ns;
|
||||
|
||||
NamespaceDeclaration() { ns = node }
|
||||
|
||||
override string getName() { result = ns.getName() }
|
||||
|
||||
Namespace getNamespace() { result.getFullyQualifiedName() = this.getFullyQualifiedName() }
|
||||
|
||||
override string toString() { result = "namespace " + this.getName() + " { ... }" }
|
||||
|
||||
override NamespaceDeclaration getParent() { result.getSourceNode() = node.getParent() }
|
||||
|
||||
string getFullyQualifiedName() {
|
||||
if exists(this.getParent())
|
||||
then result = this.getParent().getFullyQualifiedName() + "::" + this.getName()
|
||||
else result = this.getName()
|
||||
}
|
||||
|
||||
override string getMangledName() { result = "::" + this.getFullyQualifiedName() }
|
||||
|
||||
override predicate isDefinition() { any() }
|
||||
}
|
||||
|
||||
class SourceTypeDeclaration extends SourceDeclaration {
|
||||
AST::SourceTypeDefinition def;
|
||||
|
||||
SourceTypeDeclaration() { def = node }
|
||||
|
||||
override Location getLocation() { result = def.getLocation() }
|
||||
|
||||
override string toString() { result = "typename " + def.getName() }
|
||||
|
||||
string getFullyQualifiedName() {
|
||||
if exists(this.getParentNamespace())
|
||||
then result = this.getParentNamespace().getFullyQualifiedName() + "::" + this.getName()
|
||||
else
|
||||
if exists(this.getParentType())
|
||||
then result = this.getParentType() + "::" + this.getName()
|
||||
else result = this.getName()
|
||||
}
|
||||
|
||||
NamespaceDeclaration getParentNamespace() { result.getSourceNode() = def.getParent() }
|
||||
|
||||
SourceTypeDeclaration getParentType() { result.getSourceNode() = def.getParent() }
|
||||
|
||||
override SourceDeclaration getParent() {
|
||||
result = this.getParentNamespace() or result = this.getParentType()
|
||||
}
|
||||
|
||||
override string getName() { result = def.getName() }
|
||||
|
||||
// Mangled name
|
||||
override string getMangledName() {
|
||||
if exists(this.getParent())
|
||||
then result = this.getParent().getMangledName() + "::" + this.getName()
|
||||
else result = "::" + this.getName()
|
||||
}
|
||||
|
||||
override predicate isDefinition() { def.isDefinition() }
|
||||
|
||||
AST::SourceVariableDeclaration getAField() {
|
||||
result = def.getAMember()
|
||||
}
|
||||
}
|
||||
|
||||
class SourceTypeDefinition extends SourceTypeDeclaration, SourceDefinition {
|
||||
SourceTypeDefinition() { this.isDefinition() }
|
||||
}
|
||||
|
||||
class SourceFunctionDeclaration extends SourceDeclaration {
|
||||
AST::SourceFunction fn;
|
||||
|
||||
SourceFunctionDeclaration() { fn = node }
|
||||
|
||||
SourceTypeDeclaration getParentType() { result.getSourceNode() = fn.getParent() }
|
||||
|
||||
NamespaceDeclaration getParentNamespace() { result.getSourceNode() = fn.getParent() }
|
||||
|
||||
override SourceDeclaration getParent() {
|
||||
result = this.getParentType() or result = this.getParentNamespace()
|
||||
}
|
||||
|
||||
override string toString() { result = fn.getName() + "()" }
|
||||
|
||||
override Location getLocation() { result = fn.getLocation() }
|
||||
|
||||
override string getName() { result = fn.getName() }
|
||||
|
||||
override string getMangledName() {
|
||||
if exists(this.getParent())
|
||||
then result = this.getParent().getMangledName() + "::" + this.getName() + "()"
|
||||
else result = "::" + this.getName() + "()"
|
||||
}
|
||||
|
||||
override predicate isDefinition() { fn.isDefinition() }
|
||||
}
|
||||
|
||||
class SourceFunctionDefinition extends SourceFunctionDeclaration, SourceDefinition {
|
||||
SourceFunctionDefinition() { this.isDefinition() }
|
||||
}
|
||||
|
||||
predicate invalidParent(SourceDeclaration decl) { decl.getParent+() = decl }
|
||||
}
|
||||
|
||||
// For debugging in context
|
||||
module TestModel = BuildlessModel<CompiledAST>;
|
||||
46
cpp/ql/lib/experimental/buildless/TODO.md
Normal file
46
cpp/ql/lib/experimental/buildless/TODO.md
Normal file
@@ -0,0 +1,46 @@
|
||||
Next:
|
||||
- [x] Namespaces
|
||||
- [ ] Unnamed class/struct/union and name mangling
|
||||
- [ ] Linker awareness is creating duplicates
|
||||
|
||||
|
||||
|
||||
- Resolve the type of a local variable
|
||||
|
||||
|
||||
- [ ] Parent scopes - where are things declared
|
||||
Parent class
|
||||
Parent namespace
|
||||
Parent function (for variable declarations and parameters)
|
||||
Parent block (for blocks and statements)
|
||||
|
||||
|
||||
|
||||
- [ ] Return type nodes
|
||||
- [ ] Construction of types
|
||||
- [ ] Construction of functions
|
||||
- [ ] Construction of Variables
|
||||
|
||||
|
||||
|
||||
|
||||
Names:
|
||||
- [x] Identify all function names
|
||||
- [x] Identify all parameter names
|
||||
- [x] Identify all variable declaration names
|
||||
- [x] Identify variable accesses
|
||||
|
||||
Types:
|
||||
- [x] Locate user type definitions and typedefs
|
||||
- [x] Get the type of the parameter
|
||||
- [ ] Assign types to variable accesses
|
||||
|
||||
Calls:
|
||||
- [x] Identify function call expressions
|
||||
- [x] Identify the "target" of a call in a trivial case.
|
||||
|
||||
Overloads:
|
||||
|
||||
Types:
|
||||
- [ ] Identify return types
|
||||
- [x] Identify parameter types and other declarations
|
||||
196
cpp/ql/lib/experimental/buildless/ast.qll
Normal file
196
cpp/ql/lib/experimental/buildless/ast.qll
Normal file
@@ -0,0 +1,196 @@
|
||||
import CompiledAST
|
||||
import ASTSig
|
||||
|
||||
module BuildlessAST<BuildlessASTSig AST> {
|
||||
final class Node = AST::Node;
|
||||
|
||||
// Any node in the abstract syntax tree
|
||||
class SourceElement extends Node {
|
||||
Location getLocation() { AST::nodeLocation(this, result) }
|
||||
|
||||
string toString() { result = "element" }
|
||||
|
||||
SourceElement getParent() { AST::edge(result, _, this) }
|
||||
|
||||
SourceElement getChild(int i) { AST::edge(this, i, result) }
|
||||
|
||||
SourceElement getAChild() { result = this.getChild(_) }
|
||||
}
|
||||
|
||||
bindingset[path]
|
||||
private File getAnIncludeTarget(string path) {
|
||||
exists(string p | p = result.toString() | path = p.suffix(p.length() - path.length()))
|
||||
}
|
||||
|
||||
class Include extends SourceElement {
|
||||
string path;
|
||||
|
||||
Include() { AST::userInclude(this, path) or AST::systemInclude(this, path) }
|
||||
|
||||
File getATarget() {
|
||||
result = getAnIncludeTarget(path)
|
||||
or
|
||||
path.prefix(3) = "../" and result = getAnIncludeTarget(path.suffix(3))
|
||||
or
|
||||
path.prefix(2) = "./" and result = getAnIncludeTarget(path.suffix(2))
|
||||
}
|
||||
|
||||
predicate isSystemInclude() { AST::systemInclude(this, _) }
|
||||
|
||||
predicate isUserInclude() { AST::userInclude(this, _) }
|
||||
|
||||
override string toString() {
|
||||
this.isSystemInclude() and result = "#include <" + path + ">"
|
||||
or
|
||||
this.isUserInclude() and result = "#include \"" + path + "\""
|
||||
}
|
||||
}
|
||||
|
||||
abstract class SourceScope extends SourceElement { }
|
||||
|
||||
class SourceNamespace extends SourceScope, SourceDeclaration {
|
||||
SourceNamespace() { AST::namespace(this) }
|
||||
|
||||
override string getName() { AST::namespaceName(this, result) }
|
||||
|
||||
override string toString() { result = "namespace " + this.getName() }
|
||||
}
|
||||
|
||||
// Any syntax node that is a declaration
|
||||
abstract class SourceDeclaration extends SourceElement {
|
||||
abstract string getName();
|
||||
}
|
||||
|
||||
// A syntax node that declares or defines a function
|
||||
class SourceFunction extends SourceDeclaration {
|
||||
SourceFunction() { AST::function(this) }
|
||||
|
||||
override string getName() { AST::functionName(this, result) }
|
||||
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
BlockStmt getBody() { AST::functionBody(this, result) }
|
||||
|
||||
SourceParameter getParameter(int i) { AST::functionParameter(this, i, result) }
|
||||
|
||||
SourceType getReturnType() { AST::functionReturn(this, result) }
|
||||
|
||||
predicate isDefinition() { AST::functionDefinition(this) }
|
||||
}
|
||||
|
||||
// A syntax node that declares a variable (including fields and parameters)
|
||||
class SourceVariableDeclaration extends SourceDeclaration {
|
||||
SourceVariableDeclaration() { AST::variableDeclaration(this) }
|
||||
|
||||
override string getName() { AST::variableName(this, result) }
|
||||
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
SourceType getType() { AST::variableDeclarationType(this, result) }
|
||||
}
|
||||
|
||||
// A syntax node that declares a parameter
|
||||
class SourceParameter extends SourceVariableDeclaration {
|
||||
SourceFunction fn;
|
||||
int index;
|
||||
|
||||
SourceParameter() { AST::functionParameter(fn, index, this) }
|
||||
}
|
||||
|
||||
class Stmt extends SourceElement {
|
||||
Stmt() { AST::stmt(this) }
|
||||
|
||||
override string toString() { result = "stmt" }
|
||||
}
|
||||
|
||||
class BlockStmt extends Stmt {
|
||||
BlockStmt() { AST::blockStmt(this) }
|
||||
|
||||
override string toString() { result = "{ ... }" }
|
||||
}
|
||||
|
||||
class Expr extends SourceElement {
|
||||
Expr() { AST::expression(this) }
|
||||
}
|
||||
|
||||
class AccessExpr extends Expr {
|
||||
string identifier;
|
||||
|
||||
AccessExpr() { AST::accessExpr(this, identifier) }
|
||||
|
||||
string getName() { result = identifier }
|
||||
|
||||
override string toString() { result = this.getName() }
|
||||
}
|
||||
|
||||
class CallExpr extends Expr {
|
||||
CallExpr() { AST::callExpr(this) }
|
||||
|
||||
Expr getReceiver() { AST::callReceiver(this, result) }
|
||||
|
||||
Expr getArgument(int i) { AST::callArgument(this, i, result) }
|
||||
|
||||
override string toString() { result = "...(...)" }
|
||||
}
|
||||
|
||||
class Literal extends Expr {
|
||||
string value;
|
||||
|
||||
Literal() { AST::literal(this, value) }
|
||||
|
||||
override string toString() { result = value }
|
||||
|
||||
string getValue() { result = value }
|
||||
}
|
||||
|
||||
class StringLiteral extends Literal {
|
||||
StringLiteral() { AST::stringLiteral(this, _) }
|
||||
}
|
||||
|
||||
abstract class SourceDefinition extends SourceDeclaration { }
|
||||
|
||||
class SourceTypeDefinition extends SourceDefinition {
|
||||
SourceTypeDefinition() { AST::classOrStructDefinition(this) }
|
||||
|
||||
override string getName() { AST::typename(this, result) }
|
||||
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
SourceElement getAMember() { AST::classMember(this, _, result) }
|
||||
|
||||
predicate isDefinition() { AST::typeDefinition(this) }
|
||||
}
|
||||
|
||||
// A node that contains a type of some kind
|
||||
class SourceType extends SourceElement {
|
||||
SourceType() { AST::type(this) }
|
||||
|
||||
override string toString() { AST::typename(this, result) }
|
||||
}
|
||||
|
||||
class SourcePointer extends SourceType {
|
||||
SourceType pointee;
|
||||
|
||||
SourcePointer() { AST::ptrType(this, pointee) }
|
||||
|
||||
SourceType getType() { result = pointee }
|
||||
}
|
||||
|
||||
class SourceConst extends SourceType {
|
||||
SourceType type;
|
||||
|
||||
SourceConst() { AST::constType(this, type) }
|
||||
|
||||
SourceType getType() { result = type }
|
||||
}
|
||||
|
||||
class SourceReference extends SourceType {
|
||||
SourceType type;
|
||||
|
||||
SourceReference() { AST::refType(this, type) }
|
||||
|
||||
SourceType getType() { result = type }
|
||||
}
|
||||
}
|
||||
|
||||
module TestAST = BuildlessAST<CompiledAST>;
|
||||
3
cpp/ql/lib/experimental/buildless/checks.ql
Normal file
3
cpp/ql/lib/experimental/buildless/checks.ql
Normal file
@@ -0,0 +1,3 @@
|
||||
import Model
|
||||
|
||||
select 1
|
||||
31
cpp/ql/lib/experimental/buildless/identifiers.qll
Normal file
31
cpp/ql/lib/experimental/buildless/identifiers.qll
Normal file
@@ -0,0 +1,31 @@
|
||||
import ast_sig
|
||||
import ast
|
||||
import compiled_ast // For debugging in context
|
||||
|
||||
module BuildlessIdentifiers<BuildlessASTSig A> {
|
||||
module AST = Buildless<A>;
|
||||
|
||||
string getQualifiedName(AST::SourceNamespace ns) {
|
||||
not exists(AST::SourceNamespace p | ns = p.getAChild()) and result = ns.getName()
|
||||
or
|
||||
exists(AST::SourceNamespace p | ns = p.getAChild() and ns !=p|
|
||||
result = getQualifiedName(p) + "::" + ns.getName()
|
||||
)
|
||||
}
|
||||
|
||||
predicate namespace(string ns) {
|
||||
ns = ["", getQualifiedName(_)]
|
||||
}
|
||||
|
||||
// What are the identifiers in scope at a given point in the program?
|
||||
// Give a potential object that the identifier refers to
|
||||
AST::SourceDeclaration nameLookup(AST::SourceScope scope) {
|
||||
result = scope
|
||||
or
|
||||
result = scope.(AST::SourceNamespace).getAChild()
|
||||
or
|
||||
result = scope.(AST::SourceTypeDefinition).getAMember()
|
||||
}
|
||||
}
|
||||
|
||||
module TestIdentifiers = BuildlessIdentifiers<CompiledAST>;
|
||||
26
cpp/ql/lib/experimental/buildless/test_ast.ql
Normal file
26
cpp/ql/lib/experimental/buildless/test_ast.ql
Normal file
@@ -0,0 +1,26 @@
|
||||
import AST
|
||||
import types
|
||||
|
||||
query TestAST::SourceFunction lua_copy() { result.getName() = "lua_copy" }
|
||||
|
||||
query int lua_copy_count() { result = count(lua_copy()) }
|
||||
|
||||
query predicate variables(TestAST::SourceVariableDeclaration decl, TestAST::SourceType sourceType) {
|
||||
sourceType = decl.getType()
|
||||
}
|
||||
|
||||
query predicate naiveCallTargets(TestAST::CallExpr call, TestAST::SourceFunction target) {
|
||||
call.getReceiver().(TestAST::AccessExpr).getName() = target.getName() and
|
||||
target.getName() = "max"
|
||||
}
|
||||
|
||||
query predicate fnParents(TestAST::SourceFunction fn, TestAST::SourceNamespace parent) {
|
||||
parent = fn.getParent()
|
||||
}
|
||||
|
||||
query predicate includes(TestAST::Include include, File target) { target = include.getATarget() }
|
||||
|
||||
query predicate unresolvedIncludes(TestAST::Include include) { not exists(include.getATarget()) }
|
||||
|
||||
from TestAST::SourceFunction fn
|
||||
select fn, fn.getReturnType(), count(fn.getReturnType()), fn.getReturnType().getAQlClass()
|
||||
13
cpp/ql/lib/experimental/buildless/test_model.ql
Normal file
13
cpp/ql/lib/experimental/buildless/test_model.ql
Normal file
@@ -0,0 +1,13 @@
|
||||
import Model
|
||||
|
||||
query predicate multipleDefinitions(TestModel::Type type, TestModel::SourceTypeDefinition def1, TestModel::SourceTypeDefinition def2)
|
||||
{
|
||||
def1 = type.getADefinition() and
|
||||
def2 = type.getADefinition() and
|
||||
def1.getLocation() != def2.getLocation() and
|
||||
def1 != def2
|
||||
}
|
||||
|
||||
from TestModel::SourceDeclaration decl
|
||||
where decl.getParent+()=decl
|
||||
select decl, "This has an invalid parent $@", decl.getParent()
|
||||
34
cpp/ql/lib/experimental/buildless/test_types.ql
Normal file
34
cpp/ql/lib/experimental/buildless/test_types.ql
Normal file
@@ -0,0 +1,34 @@
|
||||
import types
|
||||
|
||||
query predicate constPointers(TestAST::SourceType t, TestAST::SourceConst c, TestAST::SourcePointer p)
|
||||
{
|
||||
p.getType() = c and
|
||||
t = c.getType()
|
||||
}
|
||||
|
||||
query predicate constRefs(TestAST::SourceType t, TestAST::SourceConst c, TestAST::SourceReference p)
|
||||
{
|
||||
p.getType() = c and
|
||||
t = c.getType()
|
||||
}
|
||||
|
||||
query predicate nestedNamespaces(TestAST::SourceNamespace parent, TestAST::SourceNamespace child)
|
||||
{
|
||||
child = parent.getAChild()
|
||||
}
|
||||
|
||||
query predicate recursiveNamespace(TestAST::SourceNamespace ns, TestAST::SourceNamespace descendents)
|
||||
{
|
||||
ns = ns.getAChild+() and
|
||||
descendents = ns.getAChild+()
|
||||
}
|
||||
|
||||
query predicate usertypes(TestAST::SourceNamespace ns, TestAST::SourceTypeDefinition td)
|
||||
{
|
||||
td = ns.getAChild()
|
||||
}
|
||||
|
||||
// Let's try to resolve the type of a local variable
|
||||
|
||||
from TestTypes::Type t
|
||||
select t
|
||||
34
cpp/ql/lib/experimental/buildless/types.qll
Normal file
34
cpp/ql/lib/experimental/buildless/types.qll
Normal file
@@ -0,0 +1,34 @@
|
||||
import AST
|
||||
|
||||
module BuildlessTypes<BuildlessASTSig Sig> {
|
||||
module AST = BuildlessAST<Sig>;
|
||||
|
||||
private newtype TType =
|
||||
TBuiltinType(string name) { name = ["int", "char"] }
|
||||
or
|
||||
TUserType(string fqn) { exists(AST::SourceTypeDefinition d | d.getName() = fqn) }
|
||||
//or
|
||||
//TPointerType(Type type) { exists(A::SourcePointer p | p.getType() = type) }
|
||||
//or
|
||||
//TConstType(Type type) { exists(A::SourceConst c | c.getType() = type) }
|
||||
|
||||
class Type extends TType {
|
||||
string toString() { result = this.getName() }
|
||||
|
||||
abstract string getName();
|
||||
Location getLocation() { none() }
|
||||
}
|
||||
|
||||
class BuiltinType extends Type, TBuiltinType {
|
||||
override string getName() { this = TBuiltinType(result) }
|
||||
}
|
||||
|
||||
class UserType extends Type, TUserType
|
||||
{
|
||||
override string getName() { this = TUserType(result) }
|
||||
|
||||
override Location getLocation() { exists(AST::SourceTypeDefinition d | this.getName() = d.getName() | result = d.getLocation()) }
|
||||
}
|
||||
}
|
||||
|
||||
module TestTypes = BuildlessTypes<CompiledAST>;
|
||||
@@ -1,25 +0,0 @@
|
||||
# partial model of the Boost::Asio network library
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: sourceModel
|
||||
data: # namespace, type, subtypes, name, signature, ext, output, kind, provenance
|
||||
- ["boost::asio", "", False, "read", "", "", "Argument[*1]", "remote", "manual"]
|
||||
- ["boost::asio", "", False, "read_at", "", "", "Argument[*2]", "remote", "manual"]
|
||||
- ["boost::asio", "", False, "read_until", "", "", "Argument[*1]", "remote", "manual"]
|
||||
- ["boost::asio", "", False, "async_read", "", "", "Argument[*1]", "remote", "manual"]
|
||||
- ["boost::asio", "", False, "async_read_at", "", "", "Argument[*2]", "remote", "manual"]
|
||||
- ["boost::asio", "", False, "async_read_until", "", "", "Argument[*1]", "remote", "manual"]
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: sinkModel
|
||||
data: # namespace, type, subtypes, name, signature, ext, input, kind, provenance
|
||||
- ["boost::asio", "", False, "write", "", "", "Argument[*1]", "remote-sink", "manual"]
|
||||
- ["boost::asio", "", False, "write_at", "", "", "Argument[*2]", "remote-sink", "manual"]
|
||||
- ["boost::asio", "", False, "async_write", "", "", "Argument[*1]", "remote-sink", "manual"]
|
||||
- ["boost::asio", "", False, "async_write_at", "", "", "Argument[*2]", "remote-sink", "manual"]
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: summaryModel
|
||||
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
|
||||
- ["boost::asio", "", False, "buffer", "", "", "Argument[*0]", "ReturnValue", "taint", "manual"]
|
||||
@@ -1,7 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: allocationFunctionModel
|
||||
data:
|
||||
- ["", "", False, "kmem_alloc", "0", "", "", True]
|
||||
- ["", "", False, "kmem_zalloc", "0", "", "", True]
|
||||
@@ -1,7 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: allocationFunctionModel
|
||||
data:
|
||||
- ["", "", False, "g_malloc", "0", "", "", True]
|
||||
- ["", "", False, "g_try_malloc", "0", "", "", True]
|
||||
@@ -1,10 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: allocationFunctionModel
|
||||
data:
|
||||
- ["", "", False, "CRYPTO_malloc", "0", "", "", True]
|
||||
- ["", "", False, "CRYPTO_zalloc", "0", "", "", True]
|
||||
- ["", "", False, "CRYPTO_secure_malloc", "0", "", "", True]
|
||||
- ["", "", False, "CRYPTO_secure_zalloc", "0", "", "", True]
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: allocationFunctionModel
|
||||
data:
|
||||
- ["", "", False, "malloc", "0", "", "", True]
|
||||
- ["std", "", False, "malloc", "0", "", "", True]
|
||||
- ["bsl", "", False, "malloc", "0", "", "", True]
|
||||
- ["", "", False, "alloca", "0", "", "", False]
|
||||
- ["", "", False, "__builtin_alloca", "0", "", "", False]
|
||||
- ["", "", False, "_alloca", "0", "", "", False]
|
||||
- ["", "", False, "_malloca", "0", "", "", False]
|
||||
- ["", "", False, "calloc", "1", "0", "", True]
|
||||
- ["std", "", False, "calloc", "1", "0", "", True]
|
||||
- ["bsl", "", False, "calloc", "1", "0", "", True]
|
||||
@@ -1,29 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: allocationFunctionModel
|
||||
data:
|
||||
- ["", "", False, "MmAllocateContiguousMemory", "0", "", "", True]
|
||||
- ["", "", False, "MmAllocateContiguousNodeMemory", "0", "", "", True]
|
||||
- ["", "", False, "MmAllocateContiguousMemorySpecifyCache", "0", "", "", True]
|
||||
- ["", "", False, "MmAllocateContiguousMemorySpecifyCacheNode", "0", "", "", True]
|
||||
- ["", "", False, "MmAllocateNonCachedMemory", "0", "", "", True]
|
||||
- ["", "", False, "MmAllocateMappingAddress", "0", "", "", True]
|
||||
- ["", "", False, "CoTaskMemAlloc", "0", "", "", True]
|
||||
- ["", "", False, "ExAllocatePool", "1", "", "", True]
|
||||
- ["", "", False, "ExAllocatePool2", "1", "", "", True]
|
||||
- ["", "", False, "ExAllocatePool3", "1", "", "", True]
|
||||
- ["", "", False, "ExAllocatePoolWithTag", "1", "", "", True]
|
||||
- ["", "", False, "ExAllocatePoolWithTagPriority", "1", "", "", True]
|
||||
- ["", "", False, "ExAllocatePoolWithQuota", "1", "", "", True]
|
||||
- ["", "", False, "ExAllocatePoolWithQuotaTag", "1", "", "", True]
|
||||
- ["", "", False, "ExAllocatePoolZero", "1", "", "", True]
|
||||
- ["", "", False, "IoAllocateMdl", "1", "", "", True]
|
||||
- ["", "", False, "IoAllocateErrorLogEntry", "1", "", "", True]
|
||||
- ["", "", False, "LocalAlloc", "1", "", "", True]
|
||||
- ["", "", False, "GlobalAlloc", "1", "", "", True]
|
||||
- ["", "", False, "VirtualAlloc", "1", "", "", True]
|
||||
- ["", "", False, "HeapAlloc", "2", "", "", True]
|
||||
- ["", "", False, "MmAllocatePagesForMdl", "3", "", "", True]
|
||||
- ["", "", False, "MmAllocatePagesForMdlEx", "3", "", "", True]
|
||||
- ["", "", False, "MmAllocateNodePagesForMdlEx", "3", "", "", True]
|
||||
@@ -1,5 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: allocationFunctionModel
|
||||
data: []
|
||||
@@ -1,14 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: summaryModel
|
||||
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
|
||||
- ["bsl", "array", True, "at", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "array", True, "begin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "array", True, "cbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "array", True, "data", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "array", True, "operator[]", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "array", True, "rbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "array", True, "rcbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "array", True, "front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "array", True, "back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
@@ -1,73 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: summaryModel
|
||||
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
|
||||
- ["bsl", "deque<T,Allocator>", True, "assign", "(size_type,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "assign<InputIt>", "(InputIt,InputIt)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "at", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "begin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "cbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "deque", "(const deque &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "deque", "(deque &&)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace", "", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace", "", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace", "", "", "Argument[*@3]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace", "", "", "Argument[*@4]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace", "", "", "Argument[*@5]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[*@0]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[*@0]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "emplace_front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "operator=", "", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "operator[]", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "push_back", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "push_front", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "rbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque", True, "rcbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque<T,Allocator>", True, "deque", "(const deque &,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque<T,Allocator>", True, "deque", "(deque &&,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque<T,Allocator>", True, "deque", "(size_type,const T &,const Allocator &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque<T,Allocator>", True, "deque<InputIterator>", "(InputIterator,InputIterator,const Allocator &)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "deque<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
@@ -1,56 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: summaryModel
|
||||
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
|
||||
- ["bsl", "forward_list", True, "insert_after<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list<T>", True, "insert_after", "(const_iterator,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list<T>", True, "insert_after", "(const_iterator,size_type,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list<T,Allocator>", True, "assign", "(size_type,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "assign<InputIt>", "(InputIt,InputIt)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "begin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "cbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "emplace_after", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "emplace_after", "", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "emplace_after", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "emplace_after", "", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "emplace_after", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "emplace_after", "", "", "Argument[*@3]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "emplace_after", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "emplace_after", "", "", "Argument[*@4]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "emplace_after", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "emplace_after", "", "", "Argument[*@5]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "emplace_after", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[*@0]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "emplace_front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "forward_list", "(const forward_list &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "forward_list", "(forward_list &&)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "insert_after<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "insert_after<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "operator=", "", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "push_front", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "rbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list", True, "rcbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list<T,Allocator>", True, "forward_list", "(const forward_list &,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list<T,Allocator>", True, "forward_list", "(forward_list &&,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list<T,Allocator>", True, "forward_list", "(InputIterator,InputIterator,const Allocator &)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list<T,Allocator>", True, "forward_list", "(size_type,const T &,const Allocator &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list<T>", True, "insert_after", "(const_iterator,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list<T>", True, "insert_after", "(const_iterator,const T &)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list<T>", True, "insert_after", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list<T>", True, "insert_after", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list<T>", True, "insert_after", "(const_iterator,T &&)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list<T>", True, "insert_after", "(const_iterator,T &&)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "forward_list<T>", True, "insert_after", "(const_iterator,T &&)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
@@ -1,71 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: summaryModel
|
||||
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
|
||||
- ["bsl", "list<T,Allocator>", True, "assign", "(size_type,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "assign<InputIt>", "(InputIt,InputIt)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "begin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "cbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_back", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_back", "", "", "Argument[*@0]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_back", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_back", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_back", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_back", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_back", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_back", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_back", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_back", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_back", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_back", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_front", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_front", "", "", "Argument[*@0]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_front", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_front", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_front", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_front", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_front", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_front", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_front", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_front", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_front", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_front", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "emplace_front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "list", "(const list &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "list", "(list &&)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "operator=", "", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "push_back", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "push_front", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "rbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "list", True, "rcbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "list<T,Allocator>", True, "list", "(const list &,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list<T,Allocator>", True, "list", "(list &&,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list<T,Allocator>", True, "list", "(size_type,const T &,const Allocator &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list<T,Allocator>", True, "list<InputIterator>", "(InputIterator,InputIterator,const Allocator &)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "list<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "list<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "list<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "list<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "list<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "list<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
@@ -1,60 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: summaryModel
|
||||
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
|
||||
- ["bsl", "vector<T,Allocator>", True, "assign", "(size_type,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "assign<InputIt>", "(InputIt,InputIt)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "at", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "begin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "cbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "data", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "emplace", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "emplace", "", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "emplace", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "emplace", "", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "emplace", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "emplace", "", "", "Argument[*@3]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "emplace", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "emplace", "", "", "Argument[*@4]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "emplace", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "emplace", "", "", "Argument[*@5]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "emplace", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[*@0]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "emplace_back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "operator=", "", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "operator[]", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "push_back", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "rbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "rcbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "vector", "(const vector &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector", True, "vector", "(vector &&)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector<T,Allocator>", True, "vector", "(const vector &,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector<T,Allocator>", True, "vector", "(size_type,const T &,const Allocator &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector<T,Allocator>", True, "vector", "(vector &&,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector<T,Allocator>", True, "vector<InputIterator>", "(InputIterator,InputIterator,const Allocator &)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["bsl", "vector<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
@@ -1,8 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: deallocationFunctionModel
|
||||
data:
|
||||
- ["", "", False, "pool_put", "1"]
|
||||
- ["", "", False, "pool_cache_put", "1"]
|
||||
- ["", "", False, "kmem_free", "0"]
|
||||
@@ -1,42 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: deallocationFunctionModel
|
||||
data:
|
||||
- ["", "", False, "free", "0"]
|
||||
- ["std", "", False, "free", "0"]
|
||||
- ["bsl", "", False, "free", "0"]
|
||||
- ["", "", False, "realloc", "0"]
|
||||
- ["std", "", False, "realloc", "0"]
|
||||
- ["bsl", "", False, "realloc", "0"]
|
||||
- ["", "", False, "CRYPTO_free", "0"]
|
||||
- ["", "", False, "CRYPTO_secure_free", "0"]
|
||||
- ["", "", False, "g_free", "0"]
|
||||
- ["", "", False, "ExFreePool", "0"]
|
||||
- ["", "", False, "ExFreePoolWithTag", "0"]
|
||||
- ["", "", False, "ExDeleteTimer", "0"]
|
||||
- ["", "", False, "IoFreeIrp", "0"]
|
||||
- ["", "", False, "IoFreeMdl", "0"]
|
||||
- ["", "", False, "IoFreeErrorLogEntry", "0"]
|
||||
- ["", "", False, "IoFreeWorkItem", "0"]
|
||||
- ["", "", False, "MmFreeContiguousMemory", "0"]
|
||||
- ["", "", False, "MmFreeContiguousMemorySpecifyCache", "0"]
|
||||
- ["", "", False, "MmFreeNonCachedMemory", "0"]
|
||||
- ["", "", False, "MmFreeMappingAddress", "0"]
|
||||
- ["", "", False, "MmFreePagesFromMdl", "0"]
|
||||
- ["", "", False, "MmUnmapReservedMapping", "0"]
|
||||
- ["", "", False, "MmUnmapLockedPages", "0"]
|
||||
- ["", "", False, "NdisFreeGenericObject", "0"]
|
||||
- ["", "", False, "NdisFreeMemory", "0"]
|
||||
- ["", "", False, "NdisFreeMemoryWithTag", "0"]
|
||||
- ["", "", False, "NdisFreeMdl", "0"]
|
||||
- ["", "", False, "NdisFreeNetBufferListPool", "0"]
|
||||
- ["", "", False, "NdisFreeNetBufferPool", "0"]
|
||||
- ["", "", False, "LocalFree", "0"]
|
||||
- ["", "", False, "GlobalFree", "0"]
|
||||
- ["", "", False, "LocalReAlloc", "0"]
|
||||
- ["", "", False, "GlobalReAlloc", "0"]
|
||||
- ["", "", False, "VirtualFree", "0"]
|
||||
- ["", "", False, "CoTaskMemFree", "0"]
|
||||
- ["", "", False, "CoTaskMemRealloc", "0"]
|
||||
- ["", "", False, "SysFreeString", "0"]
|
||||
@@ -1,41 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: deallocationFunctionModel
|
||||
data:
|
||||
- ["", "", False, "ExFreePool", "0"]
|
||||
- ["", "", False, "ExFreePoolWithTag", "0"]
|
||||
- ["", "", False, "ExDeleteTimer", "0"]
|
||||
- ["", "", False, "IoFreeIrp", "0"]
|
||||
- ["", "", False, "IoFreeMdl", "0"]
|
||||
- ["", "", False, "IoFreeErrorLogEntry", "0"]
|
||||
- ["", "", False, "IoFreeWorkItem", "0"]
|
||||
- ["", "", False, "MmFreeContiguousMemory", "0"]
|
||||
- ["", "", False, "MmFreeContiguousMemorySpecifyCache", "0"]
|
||||
- ["", "", False, "MmFreeNonCachedMemory", "0"]
|
||||
- ["", "", False, "MmFreeMappingAddress", "0"]
|
||||
- ["", "", False, "MmFreePagesFromMdl", "0"]
|
||||
- ["", "", False, "MmUnmapReservedMapping", "0"]
|
||||
- ["", "", False, "MmUnmapLockedPages", "0"]
|
||||
- ["", "", False, "NdisFreeGenericObject", "0"]
|
||||
- ["", "", False, "NdisFreeMemory", "0"]
|
||||
- ["", "", False, "NdisFreeMemoryWithTag", "0"]
|
||||
- ["", "", False, "NdisFreeMdl", "0"]
|
||||
- ["", "", False, "NdisFreeNetBufferListPool", "0"]
|
||||
- ["", "", False, "NdisFreeNetBufferPool", "0"]
|
||||
- ["", "", False, "LocalFree", "0"]
|
||||
- ["", "", False, "GlobalFree", "0"]
|
||||
- ["", "", False, "LocalReAlloc", "0"]
|
||||
- ["", "", False, "GlobalReAlloc", "0"]
|
||||
- ["", "", False, "VirtualFree", "0"]
|
||||
- ["", "", False, "CoTaskMemFree", "0"]
|
||||
- ["", "", False, "CoTaskMemRealloc", "0"]
|
||||
- ["", "", False, "SysFreeString", "0"]
|
||||
- ["", "", False, "ExFreeToLookasideListEx", "1"]
|
||||
- ["", "", False, "ExFreeToPagedLookasideList", "1"]
|
||||
- ["", "", False, "ExFreeToNPagedLookasideList", "1"]
|
||||
- ["", "", False, "NdisFreeMemoryWithTagPriority", "1"]
|
||||
- ["", "", False, "StorPortFreeMdl", "1"]
|
||||
- ["", "", False, "StorPortFreePool", "1"]
|
||||
- ["", "", False, "HeapFree", "2"]
|
||||
- ["", "", False, "HeapReAlloc", "2"]
|
||||
@@ -1,5 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: deallocationFunctionModel
|
||||
data: []
|
||||
@@ -1,15 +0,0 @@
|
||||
extensions:
|
||||
# Make sure that the extensible model predicates have at least one definition
|
||||
# to avoid errors about undefined extensionals.
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: sourceModel
|
||||
data: []
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: sinkModel
|
||||
data: []
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: summaryModel
|
||||
data: []
|
||||
@@ -1,14 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: summaryModel
|
||||
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
|
||||
- ["std", "array", True, "at", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "array", True, "begin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "array", True, "cbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "array", True, "data", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "array", True, "operator[]", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "array", True, "rbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "array", True, "rcbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "array", True, "front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "array", True, "back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
@@ -1,73 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: summaryModel
|
||||
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
|
||||
- ["std", "deque<T,Allocator>", True, "assign", "(size_type,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "assign<InputIt>", "(InputIt,InputIt)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "at", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "deque", True, "back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "deque", True, "begin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "cbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "deque", "(const deque &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "deque", "(deque &&)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace", "", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace", "", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace", "", "", "Argument[*@3]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace", "", "", "Argument[*@4]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace", "", "", "Argument[*@5]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_back", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_back", "", "", "Argument[*@0]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_back", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_back", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_back", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_back", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_back", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_back", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_back", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_back", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_back", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_back", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_front", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_front", "", "", "Argument[*@0]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_front", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_front", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_front", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_front", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_front", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_front", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_front", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_front", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_front", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_front", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "deque", True, "emplace_front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "deque", True, "front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "deque", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "operator=", "", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "operator[]", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "deque", True, "push_back", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "push_front", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "rbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "deque", True, "rcbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "deque<T,Allocator>", True, "deque", "(const deque &,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque<T,Allocator>", True, "deque", "(deque &&,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque<T,Allocator>", True, "deque", "(size_type,const T &,const Allocator &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque<T,Allocator>", True, "deque<InputIterator>", "(InputIterator,InputIterator,const Allocator &)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "deque<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "deque<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "deque<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "deque<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "deque<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "deque<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
@@ -1,56 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: summaryModel
|
||||
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
|
||||
- ["std", "forward_list", True, "insert_after<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list<T>", True, "insert_after", "(const_iterator,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list<T>", True, "insert_after", "(const_iterator,size_type,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list<T,Allocator>", True, "assign", "(size_type,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "assign<InputIt>", "(InputIt,InputIt)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "begin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "cbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "emplace_after", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "emplace_after", "", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "emplace_after", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "emplace_after", "", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "emplace_after", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "emplace_after", "", "", "Argument[*@3]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "emplace_after", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "emplace_after", "", "", "Argument[*@4]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "emplace_after", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "emplace_after", "", "", "Argument[*@5]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "emplace_after", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[*@0]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "emplace_front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "forward_list", "(const forward_list &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "forward_list", "(forward_list &&)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "insert_after<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "insert_after<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "operator=", "", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "push_front", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "rbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list", True, "rcbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list<T,Allocator>", True, "forward_list", "(const forward_list &,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list<T,Allocator>", True, "forward_list", "(forward_list &&,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list<T,Allocator>", True, "forward_list", "(InputIterator,InputIterator,const Allocator &)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list<T,Allocator>", True, "forward_list", "(size_type,const T &,const Allocator &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list<T>", True, "insert_after", "(const_iterator,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list<T>", True, "insert_after", "(const_iterator,const T &)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list<T>", True, "insert_after", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list<T>", True, "insert_after", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list<T>", True, "insert_after", "(const_iterator,T &&)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list<T>", True, "insert_after", "(const_iterator,T &&)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "forward_list<T>", True, "insert_after", "(const_iterator,T &&)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
@@ -1,11 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: summaryModel
|
||||
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
|
||||
- ["std", "iterator", True, "operator*", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "iterator", True, "operator->", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "iterator", True, "iterator", "", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["__gnu_cxx", "__normal_iterator", True, "operator*", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["__gnu_cxx", "__normal_iterator", True, "operator->", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["__gnu_cxx", "__normal_iterator", True, "__normal_iterator", "", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
@@ -1,71 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: summaryModel
|
||||
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
|
||||
- ["std", "list<T,Allocator>", True, "assign", "(size_type,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "assign<InputIt>", "(InputIt,InputIt)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "list", True, "begin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "cbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace", "", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace", "", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace", "", "", "Argument[*@3]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace", "", "", "Argument[*@4]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace", "", "", "Argument[*@5]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_back", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_back", "", "", "Argument[*@0]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_back", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_back", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_back", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_back", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_back", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_back", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_back", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_back", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_back", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_back", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_front", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_front", "", "", "Argument[*@0]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_front", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_front", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_front", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_front", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_front", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_front", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_front", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_front", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_front", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_front", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "list", True, "emplace_front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "list", True, "front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "list", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "list", "(const list &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "list", "(list &&)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "operator=", "", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "push_back", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "push_front", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "rbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "list", True, "rcbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "list<T,Allocator>", True, "list", "(const list &,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list<T,Allocator>", True, "list", "(list &&,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list<T,Allocator>", True, "list", "(size_type,const T &,const Allocator &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list<T,Allocator>", True, "list<InputIterator>", "(InputIterator,InputIterator,const Allocator &)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "list<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "list<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "list<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "list<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "list<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "list<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
@@ -1,60 +0,0 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: summaryModel
|
||||
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
|
||||
- ["std", "vector<T,Allocator>", True, "assign", "(size_type,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "assign<InputIt>", "(InputIt,InputIt)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "at", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "vector", True, "back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "vector", True, "begin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "cbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "data", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "vector", True, "emplace", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "emplace", "", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "emplace", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "emplace", "", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "emplace", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "emplace", "", "", "Argument[*@3]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "emplace", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "emplace", "", "", "Argument[*@4]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "emplace", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "emplace", "", "", "Argument[*@5]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "emplace", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "emplace_back", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "emplace_back", "", "", "Argument[*@0]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "vector", True, "emplace_back", "", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "emplace_back", "", "", "Argument[*@1]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "vector", True, "emplace_back", "", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "emplace_back", "", "", "Argument[*@2]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "vector", True, "emplace_back", "", "", "Argument[*@3]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "emplace_back", "", "", "Argument[*@3]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "vector", True, "emplace_back", "", "", "Argument[*@4]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "emplace_back", "", "", "Argument[*@4]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "vector", True, "emplace_back", "", "", "Argument[*@5]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "emplace_back", "", "", "Argument[*@5]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "vector", True, "emplace_back", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "vector", True, "front", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "vector", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "insert<InputIt>", "(const_iterator,InputIt,InputIt)", "", "Argument[1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "operator=", "", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "operator[]", "", "", "Argument[-1].Element[@]", "ReturnValue[*@]", "value", "manual"]
|
||||
- ["std", "vector", True, "push_back", "", "", "Argument[*@0]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "rbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "rcbegin", "", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "vector", "(const vector &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "vector", True, "vector", "(vector &&)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "vector<T,Allocator>", True, "vector", "(const vector &,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "vector<T,Allocator>", True, "vector", "(size_type,const T &,const Allocator &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "vector<T,Allocator>", True, "vector", "(vector &&,const Allocator &)", "", "Argument[*0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "vector<T,Allocator>", True, "vector<InputIterator>", "(InputIterator,InputIterator,const Allocator &)", "", "Argument[0].Element[@]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "vector<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "vector<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "vector<T>", True, "insert", "(const_iterator,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "vector<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "vector<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[*@2]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "vector<T>", True, "insert", "(const_iterator,size_type,const T &)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "vector<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[*@1]", "Argument[-1].Element[@]", "value", "manual"]
|
||||
- ["std", "vector<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[*@1]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
- ["std", "vector<T>", True, "insert", "(const_iterator,T &&)", "", "Argument[-1].Element[@]", "ReturnValue.Element[@]", "value", "manual"]
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 1.3.1-dev
|
||||
version: 1.0.0-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
@@ -14,8 +14,4 @@ dependencies:
|
||||
codeql/tutorial: ${workspace}
|
||||
codeql/util: ${workspace}
|
||||
codeql/xml: ${workspace}
|
||||
dataExtensions:
|
||||
- ext/*.model.yml
|
||||
- ext/deallocation/*.model.yml
|
||||
- ext/allocation/*.model.yml
|
||||
warnOnImplicitThis: true
|
||||
|
||||
@@ -156,7 +156,7 @@ class NamespaceDeclarationEntry extends Locatable, @namespace_decl {
|
||||
* A C++ `using` directive or `using` declaration.
|
||||
*/
|
||||
class UsingEntry extends Locatable, @using {
|
||||
override Location getLocation() { usings(underlyingElement(this), _, result, _) }
|
||||
override Location getLocation() { usings(underlyingElement(this), _, result) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -166,13 +166,15 @@ class UsingEntry extends Locatable, @using {
|
||||
* ```
|
||||
*/
|
||||
class UsingDeclarationEntry extends UsingEntry {
|
||||
UsingDeclarationEntry() { usings(underlyingElement(this), _, _, 1) }
|
||||
UsingDeclarationEntry() {
|
||||
not exists(Namespace n | usings(underlyingElement(this), unresolveElement(n), _))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the declaration that is referenced by this using declaration. For
|
||||
* example, `std::string` in `using std::string`.
|
||||
*/
|
||||
Declaration getDeclaration() { usings(underlyingElement(this), unresolveElement(result), _, _) }
|
||||
Declaration getDeclaration() { usings(underlyingElement(this), unresolveElement(result), _) }
|
||||
|
||||
override string toString() { result = "using " + this.getDeclaration().getDescription() }
|
||||
}
|
||||
@@ -184,36 +186,19 @@ class UsingDeclarationEntry extends UsingEntry {
|
||||
* ```
|
||||
*/
|
||||
class UsingDirectiveEntry extends UsingEntry {
|
||||
UsingDirectiveEntry() { usings(underlyingElement(this), _, _, 2) }
|
||||
UsingDirectiveEntry() {
|
||||
exists(Namespace n | usings(underlyingElement(this), unresolveElement(n), _))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the namespace that is referenced by this using directive. For
|
||||
* example, `std` in `using namespace std`.
|
||||
*/
|
||||
Namespace getNamespace() { usings(underlyingElement(this), unresolveElement(result), _, _) }
|
||||
Namespace getNamespace() { usings(underlyingElement(this), unresolveElement(result), _) }
|
||||
|
||||
override string toString() { result = "using namespace " + this.getNamespace().getFriendlyName() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `using enum` declaration. For example:
|
||||
* ```
|
||||
* enum class Foo { a, b };
|
||||
* using enum Foo;
|
||||
* ```
|
||||
*/
|
||||
class UsingEnumDeclarationEntry extends UsingEntry {
|
||||
UsingEnumDeclarationEntry() { usings(underlyingElement(this), _, _, 3) }
|
||||
|
||||
/**
|
||||
* Gets the enumeration that is referenced by this using directive. For
|
||||
* example, `Foo` in `using enum Foo`.
|
||||
*/
|
||||
Enum getEnum() { usings(underlyingElement(this), unresolveElement(result), _, _) }
|
||||
|
||||
override string toString() { result = "using enum " + this.getEnum().getQualifiedName() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `g` is an instance of `GlobalNamespace`. This predicate
|
||||
* is used suppress a warning in `GlobalNamespace.getADeclaration()`
|
||||
|
||||
@@ -410,10 +410,6 @@ class LocalVariable extends LocalScopeVariable, @localvariable {
|
||||
or
|
||||
orphaned_variables(underlyingElement(this), unresolveElement(result))
|
||||
}
|
||||
|
||||
override predicate isStatic() {
|
||||
super.isStatic() or orphaned_variables(underlyingElement(this), _)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -59,7 +59,8 @@ class MatchValue extends AbstractValue, TMatchValue {
|
||||
}
|
||||
|
||||
/**
|
||||
* A Boolean condition in the AST that guards one or more basic blocks.
|
||||
* A Boolean condition in the AST that guards one or more basic blocks. This includes
|
||||
* operands of logical operators but not switch statements.
|
||||
*/
|
||||
cached
|
||||
class GuardCondition extends Expr {
|
||||
@@ -365,42 +366,15 @@ private predicate nonExcludedIRAndBasicBlock(IRBlock irb, BasicBlock controlled)
|
||||
}
|
||||
|
||||
/**
|
||||
* A Boolean condition in the IR that guards one or more basic blocks.
|
||||
*
|
||||
* Note that `&&` and `||` don't have an explicit representation in the IR,
|
||||
* and therefore will not appear as IRGuardConditions.
|
||||
* A Boolean condition in the IR that guards one or more basic blocks. This includes
|
||||
* operands of logical operators but not switch statements. Note that `&&` and `||`
|
||||
* don't have an explicit representation in the IR, and therefore will not appear as
|
||||
* IRGuardConditions.
|
||||
*/
|
||||
cached
|
||||
class IRGuardCondition extends Instruction {
|
||||
Instruction branch;
|
||||
|
||||
/*
|
||||
* An `IRGuardCondition` supports reasoning about four different kinds of
|
||||
* relations:
|
||||
* 1. A unary equality relation of the form `e == k`
|
||||
* 2. A binary equality relation of the form `e1 == e2 + k`
|
||||
* 3. A unary inequality relation of the form `e < k`
|
||||
* 4. A binary inequality relation of the form `e1 < e2 + k`
|
||||
*
|
||||
* where `k` is a constant.
|
||||
*
|
||||
* Furthermore, the unary relations (i.e., case 1 and case 3) are also
|
||||
* inferred from `switch` statement guards: equality relations are inferred
|
||||
* from the unique `case` statement, if any, and inequality relations are
|
||||
* inferred from the [case range](https://gcc.gnu.org/onlinedocs/gcc/Case-Ranges.html)
|
||||
* gcc extension.
|
||||
*
|
||||
* The implementation of all four follows the same structure: Each relation
|
||||
* has a cached user-facing predicate that. For example,
|
||||
* `GuardCondition::comparesEq` calls `compares_eq`. This predicate has
|
||||
* several cases that recursively decompose the relation to bring it to a
|
||||
* canonical form (i.e., a relation of the form `e1 == e2 + k`). The base
|
||||
* case for this relation (i.e., `simple_comparison_eq`) handles
|
||||
* `CompareEQInstruction`s and `CompareNEInstruction`, and recursive
|
||||
* predicates (e.g., `complex_eq`) rewrites larger expressions such as
|
||||
* `e1 + k1 == e2 + k2` into canonical the form `e1 == e2 + (k2 - k1)`.
|
||||
*/
|
||||
|
||||
cached
|
||||
IRGuardCondition() { branch = getBranchForCondition(this) }
|
||||
|
||||
@@ -761,8 +735,6 @@ private predicate compares_eq(
|
||||
exists(AbstractValue dual | value = dual.getDualValue() |
|
||||
compares_eq(test.(LogicalNotInstruction).getUnary(), left, right, k, areEqual, dual)
|
||||
)
|
||||
or
|
||||
compares_eq(test.(BuiltinExpectCallInstruction).getCondition(), left, right, k, areEqual, value)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -804,9 +776,7 @@ private predicate unary_compares_eq(
|
||||
Instruction test, Operand op, int k, boolean areEqual, boolean inNonZeroCase, AbstractValue value
|
||||
) {
|
||||
/* The simple case where the test *is* the comparison so areEqual = testIsTrue xor eq. */
|
||||
exists(AbstractValue v |
|
||||
unary_simple_comparison_eq(test, k, inNonZeroCase, v) and op.getDef() = test
|
||||
|
|
||||
exists(AbstractValue v | unary_simple_comparison_eq(test, op, k, inNonZeroCase, v) |
|
||||
areEqual = true and value = v
|
||||
or
|
||||
areEqual = false and value = v.getDualValue()
|
||||
@@ -832,9 +802,6 @@ private predicate unary_compares_eq(
|
||||
int_value(const) = k1 and
|
||||
k = k1 + k2
|
||||
)
|
||||
or
|
||||
unary_compares_eq(test.(BuiltinExpectCallInstruction).getCondition(), op, k, areEqual,
|
||||
inNonZeroCase, value)
|
||||
}
|
||||
|
||||
/** Rearrange various simple comparisons into `left == right + k` form. */
|
||||
@@ -854,55 +821,45 @@ private predicate simple_comparison_eq(
|
||||
value.(BooleanValue).getValue() = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `test` is an instruction that is part of test that eventually is
|
||||
* used in a conditional branch.
|
||||
*/
|
||||
private predicate relevantUnaryComparison(Instruction test) {
|
||||
not test instanceof CompareInstruction and
|
||||
exists(IRType type, ConditionalBranchInstruction branch |
|
||||
type instanceof IRAddressType or type instanceof IRIntegerType
|
||||
|
|
||||
type = test.getResultIRType() and
|
||||
branch.getCondition() = test
|
||||
)
|
||||
or
|
||||
exists(LogicalNotInstruction logicalNot |
|
||||
relevantUnaryComparison(logicalNot) and
|
||||
test = logicalNot.getUnary()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Rearrange various simple comparisons into `op == k` form.
|
||||
*/
|
||||
private predicate unary_simple_comparison_eq(
|
||||
Instruction test, int k, boolean inNonZeroCase, AbstractValue value
|
||||
Instruction test, Operand op, int k, boolean inNonZeroCase, AbstractValue value
|
||||
) {
|
||||
exists(SwitchInstruction switch, CaseEdge case |
|
||||
test = switch.getExpression() and
|
||||
op.getDef() = test and
|
||||
case = value.(MatchValue).getCase() and
|
||||
exists(switch.getSuccessor(case)) and
|
||||
case.getValue().toInt() = k and
|
||||
inNonZeroCase = false
|
||||
)
|
||||
or
|
||||
// Any instruction with an integral type could potentially be part of a
|
||||
// check for nullness when used in a guard. So we include all integral
|
||||
// typed instructions here. However, since some of these instructions are
|
||||
// already included as guards in other cases, we exclude those here.
|
||||
// These are instructions that compute a binary equality or inequality
|
||||
// relation. For example, the following:
|
||||
// ```cpp
|
||||
// if(a == b + 42) { ... }
|
||||
// ```
|
||||
// generates the following IR:
|
||||
// ```
|
||||
// r1(glval<int>) = VariableAddress[a] :
|
||||
// r2(int) = Load[a] : &:r1, m1
|
||||
// r3(glval<int>) = VariableAddress[b] :
|
||||
// r4(int) = Load[b] : &:r3, m2
|
||||
// r5(int) = Constant[42] :
|
||||
// r6(int) = Add : r4, r5
|
||||
// r7(bool) = CompareEQ : r2, r6
|
||||
// v1(void) = ConditionalBranch : r7
|
||||
// ```
|
||||
// and since `r7` is an integral typed instruction this predicate could
|
||||
// include a case for when `r7` evaluates to true (in which case we would
|
||||
// infer that `r6` was non-zero, and a case for when `r7` evaluates to false
|
||||
// (in which case we would infer that `r6` was zero).
|
||||
// However, since `a == b + 42` is already supported when reasoning about
|
||||
// binary equalities we exclude those cases here.
|
||||
not test.isGLValue() and
|
||||
not simple_comparison_eq(test, _, _, _, _) and
|
||||
not simple_comparison_lt(test, _, _, _) and
|
||||
not test = any(SwitchInstruction switch).getExpression() and
|
||||
(
|
||||
test.getResultIRType() instanceof IRAddressType or
|
||||
test.getResultIRType() instanceof IRIntegerType or
|
||||
test.getResultIRType() instanceof IRBooleanType
|
||||
) and
|
||||
// There's no implicit CompareInstruction in files compiled as C since C
|
||||
// doesn't have implicit boolean conversions. So instead we check whether
|
||||
// there's a branch on a value of pointer or integer type.
|
||||
relevantUnaryComparison(test) and
|
||||
op.getDef() = test and
|
||||
(
|
||||
k = 1 and
|
||||
value.(BooleanValue).getValue() = true and
|
||||
@@ -914,68 +871,12 @@ private predicate unary_simple_comparison_eq(
|
||||
)
|
||||
}
|
||||
|
||||
/** A call to the builtin operation `__builtin_expect`. */
|
||||
private class BuiltinExpectCallInstruction extends CallInstruction {
|
||||
BuiltinExpectCallInstruction() { this.getStaticCallTarget().hasName("__builtin_expect") }
|
||||
|
||||
/** Gets the condition of this call. */
|
||||
Instruction getCondition() {
|
||||
// The first parameter of `__builtin_expect` has type `long`. So we skip
|
||||
// the conversion when inferring guards.
|
||||
result = this.getArgument(0).(ConvertInstruction).getUnary()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `left == right + k` is `areEqual` if `cmp` evaluates to `value`,
|
||||
* and `cmp` is an instruction that compares the value of
|
||||
* `__builtin_expect(left == right + k, _)` to `0`.
|
||||
*/
|
||||
private predicate builtin_expect_eq(
|
||||
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, AbstractValue value
|
||||
) {
|
||||
exists(BuiltinExpectCallInstruction call, Instruction const, AbstractValue innerValue |
|
||||
int_value(const) = 0 and
|
||||
cmp.hasOperands(call.getAUse(), const.getAUse()) and
|
||||
compares_eq(call.getCondition(), left, right, k, areEqual, innerValue)
|
||||
|
|
||||
cmp instanceof CompareNEInstruction and
|
||||
value = innerValue
|
||||
or
|
||||
cmp instanceof CompareEQInstruction and
|
||||
value.getDualValue() = innerValue
|
||||
)
|
||||
}
|
||||
|
||||
private predicate complex_eq(
|
||||
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, AbstractValue value
|
||||
) {
|
||||
sub_eq(cmp, left, right, k, areEqual, value)
|
||||
or
|
||||
add_eq(cmp, left, right, k, areEqual, value)
|
||||
or
|
||||
builtin_expect_eq(cmp, left, right, k, areEqual, value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `op == k` is `areEqual` if `cmp` evaluates to `value`, and `cmp` is
|
||||
* an instruction that compares the value of `__builtin_expect(op == k, _)` to `0`.
|
||||
*/
|
||||
private predicate unary_builtin_expect_eq(
|
||||
CompareInstruction cmp, Operand op, int k, boolean areEqual, boolean inNonZeroCase,
|
||||
AbstractValue value
|
||||
) {
|
||||
exists(BuiltinExpectCallInstruction call, Instruction const, AbstractValue innerValue |
|
||||
int_value(const) = 0 and
|
||||
cmp.hasOperands(call.getAUse(), const.getAUse()) and
|
||||
unary_compares_eq(call.getCondition(), op, k, areEqual, inNonZeroCase, innerValue)
|
||||
|
|
||||
cmp instanceof CompareNEInstruction and
|
||||
value = innerValue
|
||||
or
|
||||
cmp instanceof CompareEQInstruction and
|
||||
value.getDualValue() = innerValue
|
||||
)
|
||||
}
|
||||
|
||||
private predicate unary_complex_eq(
|
||||
@@ -984,8 +885,6 @@ private predicate unary_complex_eq(
|
||||
unary_sub_eq(test, op, k, areEqual, inNonZeroCase, value)
|
||||
or
|
||||
unary_add_eq(test, op, k, areEqual, inNonZeroCase, value)
|
||||
or
|
||||
unary_builtin_expect_eq(test, op, k, areEqual, inNonZeroCase, value)
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1014,8 +913,7 @@ private predicate compares_lt(
|
||||
|
||||
/** Holds if `op < k` evaluates to `isLt` given that `test` evaluates to `value`. */
|
||||
private predicate compares_lt(Instruction test, Operand op, int k, boolean isLt, AbstractValue value) {
|
||||
unary_simple_comparison_lt(test, k, isLt, value) and
|
||||
op.getDef() = test
|
||||
simple_comparison_lt(test, op, k, isLt, value)
|
||||
or
|
||||
complex_lt(test, op, k, isLt, value)
|
||||
or
|
||||
@@ -1062,11 +960,12 @@ private predicate simple_comparison_lt(CompareInstruction cmp, Operand left, Ope
|
||||
}
|
||||
|
||||
/** Rearrange various simple comparisons into `op < k` form. */
|
||||
private predicate unary_simple_comparison_lt(
|
||||
Instruction test, int k, boolean isLt, AbstractValue value
|
||||
private predicate simple_comparison_lt(
|
||||
Instruction test, Operand op, int k, boolean isLt, AbstractValue value
|
||||
) {
|
||||
exists(SwitchInstruction switch, CaseEdge case |
|
||||
test = switch.getExpression() and
|
||||
op.getDef() = test and
|
||||
case = value.(MatchValue).getCase() and
|
||||
exists(switch.getSuccessor(case)) and
|
||||
case.getMaxValue() > case.getMinValue()
|
||||
|
||||
@@ -14,22 +14,16 @@
|
||||
* The interpretation of a row is similar to API-graphs with a left-to-right
|
||||
* reading.
|
||||
* 1. The `namespace` column selects a namespace.
|
||||
* 2. The `type` column selects a type within that namespace. This column can
|
||||
* introduce template names that can be mentioned in the `signature` column.
|
||||
* For example, `vector<T,Allocator>` introduces the template names `T` and
|
||||
* `Allocator`.
|
||||
* 2. The `type` column selects a type within that namespace.
|
||||
* 3. The `subtypes` is a boolean that indicates whether to jump to an
|
||||
* arbitrary subtype of that type. Set this to `false` if leaving the `type`
|
||||
* blank (for example, a free function).
|
||||
* 4. The `name` column optionally selects a specific named member of the type.
|
||||
* Like the `type` column, this column can introduce template names that can
|
||||
* be mentioned in the `signature` column. For example, `insert<InputIt>`
|
||||
* introduces the template name `InputIt`.
|
||||
* 5. The `signature` column optionally restricts the named member. If
|
||||
* `signature` is blank then no such filtering is done. The format of the
|
||||
* signature is a comma-separated list of types enclosed in parentheses. The
|
||||
* types must be stripped of template names. That is, write `const vector &`
|
||||
* instead of `const vector<T> &`.
|
||||
* types can be short names or fully qualified names (mixing these two options
|
||||
* is not allowed within a single signature).
|
||||
* 6. The `ext` column specifies additional API-graph-like edges. Currently
|
||||
* there is only one valid value: "".
|
||||
* 7. The `input` column specifies how data enters the element selected by the
|
||||
@@ -50,9 +44,6 @@
|
||||
* One or more "*" can be added as an argument to indicate indirection, for
|
||||
* example, "ReturnValue[*]" indicates the first indirection of the return
|
||||
* value.
|
||||
* The special symbol `@` can be used to specify an arbitrary (but fixed)
|
||||
* number of indirections. For example, the `input` column `Argument[*@0]`
|
||||
* indicates one or more indirections of the 0th argument.
|
||||
*
|
||||
* An `output` can be either:
|
||||
* - "": Selects a read of a selected field.
|
||||
@@ -74,17 +65,6 @@
|
||||
* One or more "*" can be added as an argument to indicate indirection, for
|
||||
* example, "ReturnValue[*]" indicates the first indirection of the return
|
||||
* value.
|
||||
* The special symbol `@` can be used to specify an arbitrary (but fixed)
|
||||
* number of indirections. For example, the `output` column
|
||||
* `ReturnValue[*@0]` indicates one or more indirections of the return
|
||||
* value.
|
||||
* Note: The symbol `@` only ever takes a single value across a row. Thus,
|
||||
* the (`input`, `output`) pair `("Argument[*@0]", "ReturnValue[@]")`
|
||||
* represents:
|
||||
* - flow from the _first_ indirection of the 0th argument to the return
|
||||
* value, and
|
||||
* - flow from the _second_ indirection of the 0th argument to the first
|
||||
* indirection of the return value, etc.
|
||||
* 8. The `kind` column is a tag that can be referenced from QL to determine to
|
||||
* which classes the interpreted elements should be added. For example, for
|
||||
* sources "remote" indicates a default remote flow source, and for summaries
|
||||
@@ -94,13 +74,10 @@
|
||||
|
||||
import cpp
|
||||
private import new.DataFlow
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate as Private
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
|
||||
private import internal.FlowSummaryImpl
|
||||
private import internal.FlowSummaryImpl::Public
|
||||
private import internal.FlowSummaryImpl::Private
|
||||
private import internal.FlowSummaryImpl::Private::External
|
||||
private import internal.ExternalFlowExtensions as Extensions
|
||||
private import codeql.mad.ModelValidation as SharedModelVal
|
||||
private import codeql.util.Unit
|
||||
|
||||
@@ -146,7 +123,7 @@ predicate summaryModel(string row) { any(SummaryModelCsv s).row(row) }
|
||||
/** Holds if a source model exists for the given parameters. */
|
||||
predicate sourceModel(
|
||||
string namespace, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string output, string kind, string provenance, string model
|
||||
string output, string kind, string provenance
|
||||
) {
|
||||
exists(string row |
|
||||
sourceModel(row) and
|
||||
@@ -160,20 +137,13 @@ predicate sourceModel(
|
||||
row.splitAt(";", 6) = output and
|
||||
row.splitAt(";", 7) = kind
|
||||
) and
|
||||
provenance = "manual" and
|
||||
model = ""
|
||||
or
|
||||
exists(QlBuiltins::ExtensionId madId |
|
||||
Extensions::sourceModel(namespace, type, subtypes, name, signature, ext, output, kind,
|
||||
provenance, madId) and
|
||||
model = "MaD:" + madId.toString()
|
||||
)
|
||||
provenance = "manual"
|
||||
}
|
||||
|
||||
/** Holds if a sink model exists for the given parameters. */
|
||||
predicate sinkModel(
|
||||
string namespace, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string input, string kind, string provenance, string model
|
||||
string input, string kind, string provenance
|
||||
) {
|
||||
exists(string row |
|
||||
sinkModel(row) and
|
||||
@@ -187,24 +157,13 @@ predicate sinkModel(
|
||||
row.splitAt(";", 6) = input and
|
||||
row.splitAt(";", 7) = kind
|
||||
) and
|
||||
provenance = "manual" and
|
||||
model = ""
|
||||
or
|
||||
exists(QlBuiltins::ExtensionId madId |
|
||||
Extensions::sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, provenance,
|
||||
madId) and
|
||||
model = "MaD:" + madId.toString()
|
||||
)
|
||||
provenance = "manual"
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a summary model exists for the given parameters.
|
||||
*
|
||||
* This predicate does not expand `@` to `*`s.
|
||||
*/
|
||||
private predicate summaryModel0(
|
||||
/** Holds if a summary model exists for the given parameters. */
|
||||
predicate summaryModel(
|
||||
string namespace, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string input, string output, string kind, string provenance, string model
|
||||
string input, string output, string kind, string provenance
|
||||
) {
|
||||
exists(string row |
|
||||
summaryModel(row) and
|
||||
@@ -219,48 +178,13 @@ private predicate summaryModel0(
|
||||
row.splitAt(";", 7) = output and
|
||||
row.splitAt(";", 8) = kind
|
||||
) and
|
||||
provenance = "manual" and
|
||||
model = ""
|
||||
or
|
||||
exists(QlBuiltins::ExtensionId madId |
|
||||
Extensions::summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind,
|
||||
provenance, madId) and
|
||||
model = "MaD:" + madId.toString()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `input` is `input0`, but with all occurrences of `@` replaced
|
||||
* by `n` repetitions of `*` (and similarly for `output` and `output0`).
|
||||
*/
|
||||
bindingset[input0, output0, n]
|
||||
pragma[inline_late]
|
||||
private predicate expandInputAndOutput(
|
||||
string input0, string input, string output0, string output, int n
|
||||
) {
|
||||
input = input0.replaceAll("@", repeatStars(n)) and
|
||||
output = output0.replaceAll("@", repeatStars(n))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a summary model exists for the given parameters.
|
||||
*/
|
||||
predicate summaryModel(
|
||||
string namespace, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string input, string output, string kind, string provenance, string model
|
||||
) {
|
||||
exists(string input0, string output0 |
|
||||
summaryModel0(namespace, type, subtypes, name, signature, ext, input0, output0, kind,
|
||||
provenance, model) and
|
||||
expandInputAndOutput(input0, input, output0, output,
|
||||
[0 .. Private::getMaxElementContentIndirectionIndex() - 1])
|
||||
)
|
||||
provenance = "manual"
|
||||
}
|
||||
|
||||
private predicate relevantNamespace(string namespace) {
|
||||
sourceModel(namespace, _, _, _, _, _, _, _, _, _) or
|
||||
sinkModel(namespace, _, _, _, _, _, _, _, _, _) or
|
||||
summaryModel(namespace, _, _, _, _, _, _, _, _, _, _)
|
||||
sourceModel(namespace, _, _, _, _, _, _, _, _) or
|
||||
sinkModel(namespace, _, _, _, _, _, _, _, _) or
|
||||
summaryModel(namespace, _, _, _, _, _, _, _, _, _)
|
||||
}
|
||||
|
||||
private predicate namespaceLink(string shortns, string longns) {
|
||||
@@ -279,10 +203,8 @@ private predicate canonicalNamespaceLink(string namespace, string subns) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if MaD framework coverage of `namespace` is `n` api endpoints of the
|
||||
* kind `(kind, part)`, and `namespaces` is the number of subnamespaces of
|
||||
* `namespace` which have MaD framework coverage (including `namespace`
|
||||
* itself).
|
||||
* Holds if CSV framework coverage of `namespace` is `n` api endpoints of the
|
||||
* kind `(kind, part)`.
|
||||
*/
|
||||
predicate modelCoverage(string namespace, int namespaces, string kind, string part, int n) {
|
||||
namespaces = strictcount(string subns | canonicalNamespaceLink(namespace, subns)) and
|
||||
@@ -290,17 +212,17 @@ predicate modelCoverage(string namespace, int namespaces, string kind, string pa
|
||||
part = "source" and
|
||||
n =
|
||||
strictcount(string subns, string type, boolean subtypes, string name, string signature,
|
||||
string ext, string output, string provenance, string model |
|
||||
string ext, string output, string provenance |
|
||||
canonicalNamespaceLink(namespace, subns) and
|
||||
sourceModel(subns, type, subtypes, name, signature, ext, output, kind, provenance, model)
|
||||
sourceModel(subns, type, subtypes, name, signature, ext, output, kind, provenance)
|
||||
)
|
||||
or
|
||||
part = "sink" and
|
||||
n =
|
||||
strictcount(string subns, string type, boolean subtypes, string name, string signature,
|
||||
string ext, string input, string provenance, string model |
|
||||
string ext, string input, string provenance |
|
||||
canonicalNamespaceLink(namespace, subns) and
|
||||
sinkModel(subns, type, subtypes, name, signature, ext, input, kind, provenance, model)
|
||||
sinkModel(subns, type, subtypes, name, signature, ext, input, kind, provenance)
|
||||
)
|
||||
or
|
||||
part = "summary" and
|
||||
@@ -308,7 +230,7 @@ predicate modelCoverage(string namespace, int namespaces, string kind, string pa
|
||||
strictcount(string subns, string type, boolean subtypes, string name, string signature,
|
||||
string ext, string input, string output, string provenance |
|
||||
canonicalNamespaceLink(namespace, subns) and
|
||||
summaryModel(subns, type, subtypes, name, signature, ext, input, output, kind, provenance, _)
|
||||
summaryModel(subns, type, subtypes, name, signature, ext, input, output, kind, provenance)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -317,9 +239,9 @@ predicate modelCoverage(string namespace, int namespaces, string kind, string pa
|
||||
module CsvValidation {
|
||||
private string getInvalidModelInput() {
|
||||
exists(string pred, AccessPath input, string part |
|
||||
sinkModel(_, _, _, _, _, _, input, _, _, _) and pred = "sink"
|
||||
sinkModel(_, _, _, _, _, _, input, _, _) and pred = "sink"
|
||||
or
|
||||
summaryModel(_, _, _, _, _, _, input, _, _, _, _) and pred = "summary"
|
||||
summaryModel(_, _, _, _, _, _, input, _, _, _) and pred = "summary"
|
||||
|
|
||||
(
|
||||
invalidSpecComponent(input, part) and
|
||||
@@ -336,9 +258,9 @@ module CsvValidation {
|
||||
|
||||
private string getInvalidModelOutput() {
|
||||
exists(string pred, string output, string part |
|
||||
sourceModel(_, _, _, _, _, _, output, _, _, _) and pred = "source"
|
||||
sourceModel(_, _, _, _, _, _, output, _, _) and pred = "source"
|
||||
or
|
||||
summaryModel(_, _, _, _, _, _, _, output, _, _, _) and pred = "summary"
|
||||
summaryModel(_, _, _, _, _, _, _, output, _, _) and pred = "summary"
|
||||
|
|
||||
invalidSpecComponent(output, part) and
|
||||
not part = "" and
|
||||
@@ -348,11 +270,11 @@ module CsvValidation {
|
||||
}
|
||||
|
||||
private module KindValConfig implements SharedModelVal::KindValidationConfigSig {
|
||||
predicate summaryKind(string kind) { summaryModel(_, _, _, _, _, _, _, _, kind, _, _) }
|
||||
predicate summaryKind(string kind) { summaryModel(_, _, _, _, _, _, _, _, kind, _) }
|
||||
|
||||
predicate sinkKind(string kind) { sinkModel(_, _, _, _, _, _, _, kind, _, _) }
|
||||
predicate sinkKind(string kind) { sinkModel(_, _, _, _, _, _, _, kind, _) }
|
||||
|
||||
predicate sourceKind(string kind) { sourceModel(_, _, _, _, _, _, _, kind, _, _) }
|
||||
predicate sourceKind(string kind) { sourceModel(_, _, _, _, _, _, _, kind, _) }
|
||||
}
|
||||
|
||||
private module KindVal = SharedModelVal::KindValidation<KindValConfig>;
|
||||
@@ -393,16 +315,16 @@ module CsvValidation {
|
||||
|
||||
private string getInvalidModelSignature() {
|
||||
exists(string pred, string namespace, string type, string name, string signature, string ext |
|
||||
sourceModel(namespace, type, _, name, signature, ext, _, _, _, _) and pred = "source"
|
||||
sourceModel(namespace, type, _, name, signature, ext, _, _, _) and pred = "source"
|
||||
or
|
||||
sinkModel(namespace, type, _, name, signature, ext, _, _, _, _) and pred = "sink"
|
||||
sinkModel(namespace, type, _, name, signature, ext, _, _, _) and pred = "sink"
|
||||
or
|
||||
summaryModel(namespace, type, _, name, signature, ext, _, _, _, _, _) and pred = "summary"
|
||||
summaryModel(namespace, type, _, name, signature, ext, _, _, _, _) and pred = "summary"
|
||||
|
|
||||
not namespace.regexpMatch("[a-zA-Z0-9_\\.:]*") and
|
||||
not namespace.regexpMatch("[a-zA-Z0-9_\\.]+") and
|
||||
result = "Dubious namespace \"" + namespace + "\" in " + pred + " model."
|
||||
or
|
||||
not type.regexpMatch("[a-zA-Z0-9_<>,\\+]*") and
|
||||
not type.regexpMatch("[a-zA-Z0-9_<>,\\+]+") and
|
||||
result = "Dubious type \"" + type + "\" in " + pred + " model."
|
||||
or
|
||||
not name.regexpMatch("[a-zA-Z0-9_<>,]*") and
|
||||
@@ -429,160 +351,21 @@ module CsvValidation {
|
||||
private predicate elementSpec(
|
||||
string namespace, string type, boolean subtypes, string name, string signature, string ext
|
||||
) {
|
||||
sourceModel(namespace, type, subtypes, name, signature, ext, _, _, _, _) or
|
||||
sinkModel(namespace, type, subtypes, name, signature, ext, _, _, _, _) or
|
||||
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _, _, _)
|
||||
}
|
||||
|
||||
/** Gets the fully templated version of `f`. */
|
||||
private Function getFullyTemplatedMemberFunction(Function f) {
|
||||
not f.isFromUninstantiatedTemplate(_) and
|
||||
exists(Class c, Class templateClass, int i |
|
||||
c.isConstructedFrom(templateClass) and
|
||||
f = c.getAMember(i) and
|
||||
result = templateClass.getCanonicalMember(i)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type name of the `n`'th parameter of `f` without any template
|
||||
* arguments.
|
||||
*/
|
||||
bindingset[f]
|
||||
pragma[inline_late]
|
||||
string getParameterTypeWithoutTemplateArguments(Function f, int n) {
|
||||
exists(string s, string base, string specifiers |
|
||||
s = f.getParameter(n).getType().getName() and
|
||||
parseAngles(s, base, _, specifiers) and
|
||||
result = base + specifiers
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize the `n`'th parameter of `f` by replacing template names
|
||||
* with `func:N` (where `N` is the index of the template).
|
||||
*/
|
||||
private string getTypeNameWithoutFunctionTemplates(Function f, int n, int remaining) {
|
||||
exists(Function templateFunction |
|
||||
templateFunction = getFullyTemplatedMemberFunction(f) and
|
||||
remaining = templateFunction.getNumberOfTemplateArguments() and
|
||||
result = getParameterTypeWithoutTemplateArguments(templateFunction, n)
|
||||
)
|
||||
or
|
||||
exists(string mid, TemplateParameter tp, Function templateFunction |
|
||||
mid = getTypeNameWithoutFunctionTemplates(f, n, remaining + 1) and
|
||||
templateFunction = getFullyTemplatedMemberFunction(f) and
|
||||
tp = templateFunction.getTemplateArgument(remaining) and
|
||||
result = mid.replaceAll(tp.getName(), "func:" + remaining.toString())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize the `n`'th parameter of `f` by replacing template names
|
||||
* with `class:N` (where `N` is the index of the template).
|
||||
*/
|
||||
private string getTypeNameWithoutClassTemplates(Function f, int n, int remaining) {
|
||||
exists(Class template |
|
||||
f.getDeclaringType().isConstructedFrom(template) and
|
||||
remaining = template.getNumberOfTemplateArguments() and
|
||||
result = getTypeNameWithoutFunctionTemplates(f, n, 0)
|
||||
)
|
||||
or
|
||||
exists(string mid, TemplateParameter tp, Class template |
|
||||
mid = getTypeNameWithoutClassTemplates(f, n, remaining + 1) and
|
||||
f.getDeclaringType().isConstructedFrom(template) and
|
||||
tp = template.getTemplateArgument(remaining) and
|
||||
result = mid.replaceAll(tp.getName(), "class:" + remaining.toString())
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the string representation of the `i`'th parameter of `c`. */
|
||||
private string getParameterTypeName(Function c, int i) {
|
||||
result = getTypeNameWithoutClassTemplates(c, i, 0)
|
||||
}
|
||||
|
||||
/** Splits `s` by `,` and gets the `i`'th element. */
|
||||
bindingset[s]
|
||||
pragma[inline_late]
|
||||
private string getAtIndex(string s, int i) {
|
||||
result = s.splitAt(",", i) and
|
||||
// when `s` is `""` and `i` is `0` we get `result = ""` which we don't want.
|
||||
not (s = "" and i = 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes `partiallyNormalizedSignature` by replacing the `remaining`
|
||||
* number of template arguments in `partiallyNormalizedSignature` with their
|
||||
* index in `typeArgs`.
|
||||
*/
|
||||
private string getSignatureWithoutClassTemplateNames(
|
||||
string partiallyNormalizedSignature, string typeArgs, string nameArgs, int remaining
|
||||
) {
|
||||
elementSpecWithArguments0(_, _, _, partiallyNormalizedSignature, typeArgs, nameArgs) and
|
||||
remaining = count(partiallyNormalizedSignature.indexOf(",")) + 1 and
|
||||
result = partiallyNormalizedSignature
|
||||
or
|
||||
exists(string mid |
|
||||
mid =
|
||||
getSignatureWithoutClassTemplateNames(partiallyNormalizedSignature, typeArgs, nameArgs,
|
||||
remaining + 1)
|
||||
|
|
||||
exists(string typeArg |
|
||||
typeArg = getAtIndex(typeArgs, remaining) and
|
||||
result = mid.replaceAll(typeArg, "class:" + remaining.toString())
|
||||
)
|
||||
or
|
||||
// Make sure `remaining` is properly bound
|
||||
remaining = [0 .. count(partiallyNormalizedSignature.indexOf(",")) + 1] and
|
||||
not exists(getAtIndex(typeArgs, remaining)) and
|
||||
result = mid
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes `partiallyNormalizedSignature` by replacing:
|
||||
* - _All_ the template arguments in `partiallyNormalizedSignature` that refer to
|
||||
* template parameters in `typeArgs` with their index in `typeArgs`, and
|
||||
* - The `remaining` number of template arguments in `partiallyNormalizedSignature`
|
||||
* with their index in `nameArgs`.
|
||||
*/
|
||||
private string getSignatureWithoutFunctionTemplateNames(
|
||||
string partiallyNormalizedSignature, string typeArgs, string nameArgs, int remaining
|
||||
) {
|
||||
remaining = count(partiallyNormalizedSignature.indexOf(",")) + 1 and
|
||||
result =
|
||||
getSignatureWithoutClassTemplateNames(partiallyNormalizedSignature, typeArgs, nameArgs, 0)
|
||||
or
|
||||
exists(string mid |
|
||||
mid =
|
||||
getSignatureWithoutFunctionTemplateNames(partiallyNormalizedSignature, typeArgs, nameArgs,
|
||||
remaining + 1)
|
||||
|
|
||||
exists(string nameArg |
|
||||
nameArg = getAtIndex(nameArgs, remaining) and
|
||||
result = mid.replaceAll(nameArg, "func:" + remaining.toString())
|
||||
)
|
||||
or
|
||||
// Make sure `remaining` is properly bound
|
||||
remaining = [0 .. count(partiallyNormalizedSignature.indexOf(",")) + 1] and
|
||||
not exists(getAtIndex(nameArgs, remaining)) and
|
||||
result = mid
|
||||
)
|
||||
sourceModel(namespace, type, subtypes, name, signature, ext, _, _, _) or
|
||||
sinkModel(namespace, type, subtypes, name, signature, ext, _, _, _) or
|
||||
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _, _)
|
||||
}
|
||||
|
||||
private string paramsStringPart(Function c, int i) {
|
||||
not c.isFromUninstantiatedTemplate(_) and
|
||||
(
|
||||
i = -1 and result = "(" and exists(c)
|
||||
i = -1 and result = "(" and exists(c)
|
||||
or
|
||||
exists(int n, string p | c.getParameter(n).getType().toString() = p |
|
||||
i = 2 * n and result = p
|
||||
or
|
||||
exists(int n, string p | getParameterTypeName(c, n) = p |
|
||||
i = 2 * n and result = p
|
||||
or
|
||||
i = 2 * n - 1 and result = "," and n != 0
|
||||
)
|
||||
or
|
||||
i = 2 * c.getNumberOfParameters() and result = ")"
|
||||
i = 2 * n - 1 and result = "," and n != 0
|
||||
)
|
||||
or
|
||||
i = 2 * c.getNumberOfParameters() and result = ")"
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -602,193 +385,6 @@ private predicate matchesSignature(Function func, string signature) {
|
||||
paramsString(func) = signature
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `elementSpec(_, type, _, name, signature, _)` holds and
|
||||
* - `typeArgs` represents the named template parameters supplied to `type`, and
|
||||
* - `nameArgs` represents the named template parameters supplied to `name`, and
|
||||
* - `normalizedSignature` is `signature`, except with
|
||||
* - template parameter names replaced by `func:i` if the template name is
|
||||
* the `i`'th entry in `nameArgs`, and
|
||||
* - template parameter names replaced by `class:i` if the template name is
|
||||
* the `i`'th entry in `typeArgs`.
|
||||
*
|
||||
* In other words, the string `normalizedSignature` represents a "normalized"
|
||||
* signature with no mention of any free template parameters.
|
||||
*
|
||||
* For example, consider a summary row such as:
|
||||
* ```
|
||||
* elementSpec(_, "MyClass<B, C>", _, myFunc<A>, "(const A &,int,C,B *)", _)
|
||||
* ```
|
||||
* In this case, `normalizedSignature` will be `"(const func:0 &,int,class:1,class:0 *)"`.
|
||||
*/
|
||||
private predicate elementSpecWithArguments(
|
||||
string signature, string type, string name, string normalizedSignature, string typeArgs,
|
||||
string nameArgs
|
||||
) {
|
||||
exists(string signatureWithoutParens |
|
||||
elementSpecWithArguments0(signature, type, name, signatureWithoutParens, typeArgs, nameArgs) and
|
||||
normalizedSignature =
|
||||
getSignatureWithoutFunctionTemplateNames(signatureWithoutParens, typeArgs, nameArgs, 0)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the `n`'th normalized signature parameter for the function `name` in class `type`. */
|
||||
private string getSignatureParameterName(string signature, string type, string name, int n) {
|
||||
exists(string normalizedSignature |
|
||||
elementSpecWithArguments(signature, type, name, normalizedSignature, _, _) and
|
||||
result = getAtIndex(normalizedSignature, n)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the suffix containing the entries in `signature` starting at entry
|
||||
* `i` matches the suffix containing the parameters of `func` starting at entry `i`.
|
||||
*
|
||||
* For example, consider the signature `(int,bool,char)` and a function:
|
||||
* ```
|
||||
* void f(int a, bool b, char c);
|
||||
* ```
|
||||
* 1. The predicate holds for `i = 2` because the suffix containing all the entries
|
||||
* in `signature` starting at `2` is `char`, and suffix containing all the parameters
|
||||
* of `func` starting at `2` is `char`.
|
||||
* 2. The predicate holds for `i = 1` because the suffix containing all the entries
|
||||
* in `signature` starting at `1` is `bool,char`, and the suffix containing all the
|
||||
* parameters of `func` starting at `1` is `bool, char`.
|
||||
* 3. The predicate holds for `i = 0` because the suffix containing all the entries
|
||||
* in `signature` starting at `0` is `int,bool,char` and the suffix containing all
|
||||
* the parameters of `func` starting at `0` is `int, bool, char`.
|
||||
*
|
||||
* When `paramsString(func)[i]` is `class:n` then the signature name is
|
||||
* compared with the `n`'th name in `type`, and when `paramsString(func)[i]`
|
||||
* is `func:n` then the signature name is compared with the `n`'th name
|
||||
* in `name`.
|
||||
*/
|
||||
private predicate signatureMatches(Function func, string signature, string type, string name, int i) {
|
||||
exists(string s |
|
||||
s = getSignatureParameterName(signature, type, name, i) and
|
||||
s = getParameterTypeName(func, i)
|
||||
) and
|
||||
if exists(getParameterTypeName(func, i + 1))
|
||||
then signatureMatches(func, signature, type, name, i + 1)
|
||||
else i = count(signature.indexOf(","))
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal: Do not use.
|
||||
*
|
||||
* This module only exists to expose internal predicates for testing purposes.
|
||||
*/
|
||||
module ExternalFlowDebug {
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*
|
||||
* Exposed for testing purposes.
|
||||
*/
|
||||
predicate signatureMatches_debug = signatureMatches/5;
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*
|
||||
* Exposed for testing purposes.
|
||||
*/
|
||||
predicate getSignatureParameterName_debug = getSignatureParameterName/4;
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*
|
||||
* Exposed for testing purposes.
|
||||
*/
|
||||
predicate getParameterTypeName_debug = getParameterTypeName/2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `s` can be broken into a string of the form
|
||||
* `beforeAngles<betweenAngles>`,
|
||||
* or `s = beforeAngles` where `beforeAngles` does not have any brackets.
|
||||
*/
|
||||
bindingset[s]
|
||||
pragma[inline_late]
|
||||
private predicate parseAngles(
|
||||
string s, string beforeAngles, string betweenAngles, string afterAngles
|
||||
) {
|
||||
beforeAngles = s.regexpCapture("([^<]+)(?:<([^>]+)>(.*))?", 1) and
|
||||
(
|
||||
betweenAngles = s.regexpCapture("([^<]+)(?:<([^>]+)>(.*))?", 2) and
|
||||
afterAngles = s.regexpCapture("([^<]+)(?:<([^>]+)>(.*))?", 3)
|
||||
or
|
||||
not exists(s.regexpCapture("([^<]+)(?:<([^>]+)>(.*))?", 2)) and
|
||||
betweenAngles = "" and
|
||||
afterAngles = ""
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `s` can be broken into a string of the form `(betweenParens)`. */
|
||||
bindingset[s]
|
||||
pragma[inline_late]
|
||||
private predicate parseParens(string s, string betweenParens) { s = "(" + betweenParens + ")" }
|
||||
|
||||
/**
|
||||
* Holds if `elementSpec(_, type, _, name, signature, _)` and:
|
||||
* - `type` introduces template parameters `typeArgs`, and
|
||||
* - `name` introduces template parameters `nameArgs`, and
|
||||
* - `signatureWithoutParens` equals `signature`, but with the surrounding
|
||||
* parentheses removed.
|
||||
*/
|
||||
private predicate elementSpecWithArguments0(
|
||||
string signature, string type, string name, string signatureWithoutParens, string typeArgs,
|
||||
string nameArgs
|
||||
) {
|
||||
elementSpec(_, type, _, name, signature, _) and
|
||||
parseAngles(name, _, nameArgs, "") and
|
||||
(
|
||||
type = "" and typeArgs = ""
|
||||
or
|
||||
parseAngles(type, _, typeArgs, "")
|
||||
) and
|
||||
parseParens(signature, signatureWithoutParens)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `elementSpec(namespace, type, subtypes, name, signature, _)` and
|
||||
* `method`'s signature matches `signature`.
|
||||
*
|
||||
* `signature` may contain template parameter names that are bound by `type` and `name`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate elementSpecMatchesSignature(
|
||||
Function method, string namespace, string type, boolean subtypes, string name, string signature
|
||||
) {
|
||||
elementSpec(namespace, pragma[only_bind_into](type), subtypes, pragma[only_bind_into](name),
|
||||
pragma[only_bind_into](signature), _) and
|
||||
signatureMatches(method, signature, type, name, 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `classWithMethod` has `method` named `name` (excluding any
|
||||
* template parameters).
|
||||
*/
|
||||
bindingset[name]
|
||||
pragma[inline_late]
|
||||
private predicate hasClassAndName(Class classWithMethod, Function method, string name) {
|
||||
exists(string nameWithoutArgs |
|
||||
parseAngles(name, nameWithoutArgs, _, "") and
|
||||
classWithMethod = method.getClassAndName(nameWithoutArgs)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `namedClass` is in namespace `namespace` and has
|
||||
* name `type` (excluding any template parameters).
|
||||
*/
|
||||
bindingset[type, namespace]
|
||||
pragma[inline_late]
|
||||
private predicate hasQualifiedName(Class namedClass, string namespace, string type) {
|
||||
exists(string typeWithoutArgs |
|
||||
parseAngles(type, typeWithoutArgs, _, "") and
|
||||
namedClass.hasQualifiedName(namespace, typeWithoutArgs)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the element in module `namespace` that satisfies the following properties:
|
||||
* 1. If the element is a member of a class-like type, then the class-like type has name `type`
|
||||
@@ -803,8 +399,8 @@ pragma[nomagic]
|
||||
private Element interpretElement0(
|
||||
string namespace, string type, boolean subtypes, string name, string signature
|
||||
) {
|
||||
elementSpec(namespace, type, subtypes, name, signature, _) and
|
||||
(
|
||||
elementSpec(namespace, type, subtypes, name, signature, _) and
|
||||
// Non-member functions
|
||||
exists(Function func |
|
||||
func.hasQualifiedName(namespace, name) and
|
||||
@@ -816,28 +412,21 @@ private Element interpretElement0(
|
||||
)
|
||||
or
|
||||
// Member functions
|
||||
exists(Class namedClass, Class classWithMethod |
|
||||
(
|
||||
elementSpecMatchesSignature(result, namespace, type, subtypes, name, signature) and
|
||||
hasClassAndName(classWithMethod, result, name)
|
||||
or
|
||||
signature = "" and
|
||||
elementSpec(namespace, type, subtypes, name, "", _) and
|
||||
hasClassAndName(classWithMethod, result, name)
|
||||
) and
|
||||
hasQualifiedName(namedClass, namespace, type) and
|
||||
(
|
||||
// member declared in the named type or a subtype of it
|
||||
subtypes = true and
|
||||
classWithMethod = namedClass.getADerivedClass*()
|
||||
or
|
||||
// member declared directly in the named type
|
||||
subtypes = false and
|
||||
classWithMethod = namedClass
|
||||
)
|
||||
exists(Class namedClass, Class classWithMethod, Function method |
|
||||
classWithMethod = method.getClassAndName(name) and
|
||||
namedClass.hasQualifiedName(namespace, type) and
|
||||
matchesSignature(method, signature) and
|
||||
result = method
|
||||
|
|
||||
// member declared in the named type or a subtype of it
|
||||
subtypes = true and
|
||||
classWithMethod = namedClass.getADerivedClass*()
|
||||
or
|
||||
// member declared directly in the named type
|
||||
subtypes = false and
|
||||
classWithMethod = namedClass
|
||||
)
|
||||
or
|
||||
elementSpec(namespace, type, subtypes, name, signature, _) and
|
||||
// Member variables
|
||||
signature = "" and
|
||||
exists(Class namedClass, Class classWithMember, MemberVariable member |
|
||||
@@ -856,7 +445,6 @@ private Element interpretElement0(
|
||||
)
|
||||
or
|
||||
// Global or namespace variables
|
||||
elementSpec(namespace, type, subtypes, name, signature, _) and
|
||||
signature = "" and
|
||||
type = "" and
|
||||
subtypes = false and
|
||||
@@ -881,9 +469,9 @@ private module Cached {
|
||||
* model.
|
||||
*/
|
||||
cached
|
||||
predicate sourceNode(DataFlow::Node node, string kind, string model) {
|
||||
predicate sourceNode(DataFlow::Node node, string kind) {
|
||||
exists(SourceSinkInterpretationInput::InterpretNode n |
|
||||
isSourceNode(n, kind, model) and n.asNode() = node
|
||||
isSourceNode(n, kind, _) and n.asNode() = node // TODO
|
||||
)
|
||||
}
|
||||
|
||||
@@ -892,57 +480,40 @@ private module Cached {
|
||||
* model.
|
||||
*/
|
||||
cached
|
||||
predicate sinkNode(DataFlow::Node node, string kind, string model) {
|
||||
predicate sinkNode(DataFlow::Node node, string kind) {
|
||||
exists(SourceSinkInterpretationInput::InterpretNode n |
|
||||
isSinkNode(n, kind, model) and n.asNode() = node
|
||||
isSinkNode(n, kind, _) and n.asNode() = node // TODO
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import Cached
|
||||
|
||||
/**
|
||||
* Holds if `node` is specified as a source with the given kind in a MaD flow
|
||||
* model.
|
||||
*/
|
||||
predicate sourceNode(DataFlow::Node node, string kind) { sourceNode(node, kind, _) }
|
||||
|
||||
/**
|
||||
* Holds if `node` is specified as a sink with the given kind in a MaD flow
|
||||
* model.
|
||||
*/
|
||||
predicate sinkNode(DataFlow::Node node, string kind) { sinkNode(node, kind, _) }
|
||||
|
||||
private predicate interpretSummary(
|
||||
Function f, string input, string output, string kind, string provenance, string model
|
||||
Function f, string input, string output, string kind, string provenance
|
||||
) {
|
||||
exists(
|
||||
string namespace, string type, boolean subtypes, string name, string signature, string ext
|
||||
|
|
||||
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, provenance,
|
||||
model) and
|
||||
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, provenance) and
|
||||
f = interpretElement(namespace, type, subtypes, name, signature, ext)
|
||||
)
|
||||
}
|
||||
|
||||
// adapter class for converting Mad summaries to `SummarizedCallable`s
|
||||
private class SummarizedCallableAdapter extends SummarizedCallable {
|
||||
SummarizedCallableAdapter() { interpretSummary(this, _, _, _, _, _) }
|
||||
SummarizedCallableAdapter() { interpretSummary(this, _, _, _, _) }
|
||||
|
||||
private predicate relevantSummaryElementManual(
|
||||
string input, string output, string kind, string model
|
||||
) {
|
||||
private predicate relevantSummaryElementManual(string input, string output, string kind) {
|
||||
exists(Provenance provenance |
|
||||
interpretSummary(this, input, output, kind, provenance, model) and
|
||||
interpretSummary(this, input, output, kind, provenance) and
|
||||
provenance.isManual()
|
||||
)
|
||||
}
|
||||
|
||||
private predicate relevantSummaryElementGenerated(
|
||||
string input, string output, string kind, string model
|
||||
) {
|
||||
private predicate relevantSummaryElementGenerated(string input, string output, string kind) {
|
||||
exists(Provenance provenance |
|
||||
interpretSummary(this, input, output, kind, provenance, model) and
|
||||
interpretSummary(this, input, output, kind, provenance) and
|
||||
provenance.isGenerated()
|
||||
)
|
||||
}
|
||||
@@ -951,17 +522,18 @@ private class SummarizedCallableAdapter extends SummarizedCallable {
|
||||
string input, string output, boolean preservesValue, string model
|
||||
) {
|
||||
exists(string kind |
|
||||
this.relevantSummaryElementManual(input, output, kind, model)
|
||||
this.relevantSummaryElementManual(input, output, kind)
|
||||
or
|
||||
not this.relevantSummaryElementManual(_, _, _, _) and
|
||||
this.relevantSummaryElementGenerated(input, output, kind, model)
|
||||
not this.relevantSummaryElementManual(_, _, _) and
|
||||
this.relevantSummaryElementGenerated(input, output, kind)
|
||||
|
|
||||
if kind = "value" then preservesValue = true else preservesValue = false
|
||||
)
|
||||
) and
|
||||
model = "" // TODO
|
||||
}
|
||||
|
||||
override predicate hasProvenance(Provenance provenance) {
|
||||
interpretSummary(this, _, _, _, provenance, _)
|
||||
interpretSummary(this, _, _, _, provenance)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ private import DataFlowUtil
|
||||
/**
|
||||
* Gets a function that might be called by `call`.
|
||||
*/
|
||||
DataFlowCallable viableCallable(DataFlowCall call) {
|
||||
Function viableCallable(DataFlowCall call) {
|
||||
result = call.(Call).getTarget()
|
||||
or
|
||||
// If the target of the call does not have a body in the snapshot, it might
|
||||
|
||||
@@ -215,19 +215,25 @@ predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() }
|
||||
predicate localMustFlowStep(Node node1, Node node2) { none() }
|
||||
|
||||
/** Gets the type of `n` used for type pruning. */
|
||||
DataFlowType getNodeType(Node n) {
|
||||
exists(n) and
|
||||
Type getNodeType(Node n) {
|
||||
suppressUnusedNode(n) and
|
||||
result instanceof VoidType // stub implementation
|
||||
}
|
||||
|
||||
/** Gets a string representation of a type returned by `getNodeType`. */
|
||||
string ppReprType(Type t) { none() } // stub implementation
|
||||
|
||||
/**
|
||||
* Holds if `t1` and `t2` are compatible, that is, whether data can flow from
|
||||
* a node of type `t1` to a node of type `t2`.
|
||||
*/
|
||||
predicate compatibleTypes(DataFlowType t1, DataFlowType t2) {
|
||||
t1 instanceof VoidType and t2 instanceof VoidType // stub implementation
|
||||
pragma[inline]
|
||||
predicate compatibleTypes(Type t1, Type t2) {
|
||||
any() // stub implementation
|
||||
}
|
||||
|
||||
private predicate suppressUnusedNode(Node n) { any() }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Java QL library compatibility wrappers
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -236,15 +242,11 @@ class CastNode extends Node {
|
||||
CastNode() { none() } // stub implementation
|
||||
}
|
||||
|
||||
class DataFlowCallable extends Function { }
|
||||
class DataFlowCallable = Function;
|
||||
|
||||
class DataFlowExpr = Expr;
|
||||
|
||||
final private class TypeFinal = Type;
|
||||
|
||||
class DataFlowType extends TypeFinal {
|
||||
string toString() { result = "" }
|
||||
}
|
||||
class DataFlowType = Type;
|
||||
|
||||
/** A function call relevant for data flow. */
|
||||
class DataFlowCall extends Expr instanceof Call {
|
||||
@@ -259,16 +261,10 @@ class DataFlowCall extends Expr instanceof Call {
|
||||
ExprNode getNode() { result.getExpr() = this }
|
||||
|
||||
/** Gets the enclosing callable of this call. */
|
||||
DataFlowCallable getEnclosingCallable() { result = this.getEnclosingFunction() }
|
||||
Function getEnclosingCallable() { result = this.getEnclosingFunction() }
|
||||
}
|
||||
|
||||
class NodeRegion instanceof Unit {
|
||||
string toString() { result = "NodeRegion" }
|
||||
|
||||
predicate contains(Node n) { none() }
|
||||
}
|
||||
|
||||
predicate isUnreachableInCall(NodeRegion nr, DataFlowCall call) { none() } // stub implementation
|
||||
predicate isUnreachableInCall(Node n, DataFlowCall call) { none() } // stub implementation
|
||||
|
||||
/**
|
||||
* Holds if access paths with `c` at their head always should be tracked at high
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* This module provides extensible predicates for defining MaD models.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Holds if an external source model exists for the given parameters.
|
||||
*/
|
||||
extensible predicate sourceModel(
|
||||
string namespace, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string output, string kind, string provenance, QlBuiltins::ExtensionId madId
|
||||
);
|
||||
|
||||
/**
|
||||
* Holds if an external sink model exists for the given parameters.
|
||||
*/
|
||||
extensible predicate sinkModel(
|
||||
string namespace, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string input, string kind, string provenance, QlBuiltins::ExtensionId madId
|
||||
);
|
||||
|
||||
/**
|
||||
* Holds if an external summary model exists for the given parameters.
|
||||
*/
|
||||
extensible predicate summaryModel(
|
||||
string namespace, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string input, string output, string kind, string provenance, QlBuiltins::ExtensionId madId
|
||||
);
|
||||
@@ -35,22 +35,16 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CppDataFlow> {
|
||||
result = "Field" and
|
||||
arg = repeatStars(c.getIndirectionIndex() - 1) + c.getField().getName()
|
||||
)
|
||||
or
|
||||
exists(ElementContent ec |
|
||||
cs.isSingleton(ec) and
|
||||
result = "Element" and
|
||||
arg = repeatStars(ec.getIndirectionIndex() - 1)
|
||||
)
|
||||
}
|
||||
|
||||
string encodeWithoutContent(ContentSet c, string arg) {
|
||||
// used for type tracking, not currently used in C/C++.
|
||||
none()
|
||||
result = "WithoutContent" + c and arg = ""
|
||||
}
|
||||
|
||||
string encodeWithContent(ContentSet c, string arg) {
|
||||
// used for type tracking, not currently used in C/C++.
|
||||
none()
|
||||
result = "WithContent" + c and arg = ""
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,6 +79,25 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CppDataFlow> {
|
||||
token.getName() = "Parameter" and
|
||||
result = decodePosition(token.getAnArgument())
|
||||
}
|
||||
|
||||
bindingset[token]
|
||||
ContentSet decodeUnknownContent(AccessPath::AccessPathTokenBase token) {
|
||||
// field content (no indirection support)
|
||||
exists(FieldContent c |
|
||||
result.isSingleton(c) and
|
||||
token.getName() = c.getField().getName() and
|
||||
not exists(token.getArgumentList()) and
|
||||
c.getIndirectionIndex() = 1
|
||||
)
|
||||
or
|
||||
// field content (with indirection support)
|
||||
exists(FieldContent c |
|
||||
result.isSingleton(c) and
|
||||
token.getName() = c.getField().getName() and
|
||||
// FieldContent indices have 0 for the address, 1 for content, so we need to subtract one.
|
||||
token.getAnArgument() = repeatStars(c.getIndirectionIndex() - 1)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private import Make<Location, DataFlowImplSpecific::CppDataFlow, Input> as Impl
|
||||
@@ -112,8 +125,9 @@ module SourceSinkInterpretationInput implements
|
||||
exists(
|
||||
string namespace, string type, boolean subtypes, string name, string signature, string ext
|
||||
|
|
||||
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance, model) and
|
||||
e = interpretElement(namespace, type, subtypes, name, signature, ext)
|
||||
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance) and
|
||||
e = interpretElement(namespace, type, subtypes, name, signature, ext) and
|
||||
model = "" // TODO
|
||||
)
|
||||
}
|
||||
|
||||
@@ -127,8 +141,9 @@ module SourceSinkInterpretationInput implements
|
||||
exists(
|
||||
string package, string type, boolean subtypes, string name, string signature, string ext
|
||||
|
|
||||
sinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance, model) and
|
||||
e = interpretElement(package, type, subtypes, name, signature, ext)
|
||||
sinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance) and
|
||||
e = interpretElement(package, type, subtypes, name, signature, ext) and
|
||||
model = "" // TODO
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -383,37 +383,6 @@ class BuiltInOperationIsConvertibleTo extends BuiltInOperation, @isconvtoexpr {
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsConvertibleTo" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__is_convertible` built-in operation (used by some implementations
|
||||
* of the `<type_traits>` header).
|
||||
*
|
||||
* Returns `true` if the first type can be converted to the second type.
|
||||
* ```
|
||||
* bool v = __is_convertible(MyType, OtherType);
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationIsConvertible extends BuiltInOperation, @isconvertible {
|
||||
override string toString() { result = "__is_convertible" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsConvertible" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__is_nothrow_convertible` built-in operation (used by some implementations
|
||||
* of the `<type_traits>` header).
|
||||
*
|
||||
* Returns `true` if the first type can be converted to the second type and the
|
||||
* conversion operator has an empty exception specification.
|
||||
* ```
|
||||
* bool v = __is_nothrow_convertible(MyType, OtherType);
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationIsNothrowConvertible extends BuiltInOperation, @isnothrowconvertible {
|
||||
override string toString() { result = "__is_nothrow_convertible" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsNothrowConvertible" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__is_empty` built-in operation (used by some implementations of the
|
||||
* `<type_traits>` header).
|
||||
@@ -678,7 +647,8 @@ class BuiltInOperationIsTriviallyAssignable extends BuiltInOperation, @istrivial
|
||||
* The `__is_nothrow_assignable` built-in operation (used by some
|
||||
* implementations of the `<type_traits>` header).
|
||||
*
|
||||
* Returns true if there exists an assignment operator with an empty exception specification.
|
||||
* Returns true if there exists a `C::operator =(const D& d) nothrow`
|
||||
* assignment operator (i.e, with an empty exception specification).
|
||||
* ```
|
||||
* bool v = __is_nothrow_assignable(MyType1, MyType2);
|
||||
* ```
|
||||
@@ -693,7 +663,8 @@ class BuiltInOperationIsNothrowAssignable extends BuiltInOperation, @isnothrowas
|
||||
* The `__is_assignable` built-in operation (used by some implementations
|
||||
* of the `<type_traits>` header).
|
||||
*
|
||||
* Returns true if there exists an assignment operator.
|
||||
* Returns true if there exists a `C::operator =(const D& d)` assignment
|
||||
* operator.
|
||||
* ```
|
||||
* bool v = __is_assignable(MyType1, MyType2);
|
||||
* ```
|
||||
@@ -704,25 +675,6 @@ class BuiltInOperationIsAssignable extends BuiltInOperation, @isassignable {
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsAssignable" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `__is_assignable_no_precondition_check` built-in operation (used by some
|
||||
* implementations of the `<type_traits>` header).
|
||||
*
|
||||
* Returns true if there exists an assignment operator.
|
||||
* ```
|
||||
* bool v = __is_assignable_no_precondition_check(MyType1, MyType2);
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationIsAssignableNoPreconditionCheck extends BuiltInOperation,
|
||||
@isassignablenopreconditioncheck
|
||||
{
|
||||
override string toString() { result = "__is_assignable_no_precondition_check" }
|
||||
|
||||
override string getAPrimaryQlClass() {
|
||||
result = "BuiltInOperationIsAssignableNoPreconditionCheck"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `__is_standard_layout` built-in operation (used by some implementations
|
||||
* of the `<type_traits>` header).
|
||||
@@ -756,20 +708,6 @@ class BuiltInOperationIsTriviallyCopyable extends BuiltInOperation, @istrivially
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyCopyable" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `__is_trivially_copy_assignable` built-in operation (used by some
|
||||
* implementations of the `<type_traits>` header).
|
||||
*
|
||||
* Returns `true` if instances of this type can be copied using a trivial
|
||||
* copy operator.
|
||||
*/
|
||||
class BuiltInOperationIsTriviallyCopyAssignable extends BuiltInOperation, @istriviallycopyassignable
|
||||
{
|
||||
override string toString() { result = "__is_trivially_copy_assignable" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyCopyAssignable" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `__is_literal_type` built-in operation (used by some implementations of
|
||||
* the `<type_traits>` header).
|
||||
@@ -1124,24 +1062,6 @@ class BuiltInOperationIsSame extends BuiltInOperation, @issame {
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsSame" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__is_same_as` built-in operation (used by some implementations of the
|
||||
* `<type_traits>` header).
|
||||
*
|
||||
* Returns `true` if two types are the same.
|
||||
* ```
|
||||
* template<typename _Tp, typename _Up>
|
||||
* struct is_same
|
||||
* : public integral_constant<bool, __is_same_as(_Tp, _Up)>
|
||||
* { };
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationIsSameAs extends BuiltInOperation, @issameas {
|
||||
override string toString() { result = "__is_same_as" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsSameAs" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__is_function` built-in operation (used by some implementations of the
|
||||
* `<type_traits>` header).
|
||||
@@ -1200,87 +1120,6 @@ class BuiltInOperationIsPointerInterconvertibleBaseOf extends BuiltInOperation,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__is_pointer_interconvertible_with_class` built-in operation (used
|
||||
* by some implementations of the `<type_traits>` header).
|
||||
*
|
||||
* Returns `true` if a member pointer is pointer-interconvertible with a
|
||||
* class type.
|
||||
* ```
|
||||
* template<typename _Tp, typename _Up>
|
||||
* constexpr bool is_pointer_interconvertible_with_class(_Up _Tp::*mp) noexcept
|
||||
* = __is_pointer_interconvertible_with_class(_Tp, mp);
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationIsPointerInterconvertibleWithClass extends BuiltInOperation,
|
||||
@ispointerinterconvertiblewithclass
|
||||
{
|
||||
override string toString() { result = "__is_pointer_interconvertible_with_class" }
|
||||
|
||||
override string getAPrimaryQlClass() {
|
||||
result = "BuiltInOperationIsPointerInterconvertibleWithClass"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__builtin_is_pointer_interconvertible_with_class` built-in operation (used
|
||||
* by some implementations of the `<type_traits>` header).
|
||||
*
|
||||
* Returns `true` if a member pointer is pointer-interconvertible with a class type.
|
||||
* ```
|
||||
* template<typename _Tp, typename _Up>
|
||||
* constexpr bool is_pointer_interconvertible_with_class(_Up _Tp::*mp) noexcept
|
||||
* = __builtin_is_pointer_interconvertible_with_class(mp);
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationBuiltInIsPointerInterconvertible extends BuiltInOperation,
|
||||
@builtinispointerinterconvertiblewithclass
|
||||
{
|
||||
override string toString() { result = "__builtin_is_pointer_interconvertible_with_class" }
|
||||
|
||||
override string getAPrimaryQlClass() {
|
||||
result = "BuiltInOperationBuiltInIsPointerInterconvertible"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__is_corresponding_member` built-in operation (used
|
||||
* by some implementations of the `<type_traits>` header).
|
||||
*
|
||||
* Returns `true` if two member pointers refer to corresponding
|
||||
* members in the initial sequences of two class types.
|
||||
* ```
|
||||
* template<typename _Tp1, typename _Tp2, typename _Up1, typename _Up2>
|
||||
* constexpr bool is_corresponding_member(_Up1 _Tp1::*mp1, _Up2 _Tp2::*mp2 ) noexcept
|
||||
* = __is_corresponding_member(_Tp1, _Tp2, mp1, mp2);
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationIsCorrespondingMember extends BuiltInOperation, @iscorrespondingmember {
|
||||
override string toString() { result = "__is_corresponding_member" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsCorrespondingMember" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__builtin_is_corresponding_member` built-in operation (used
|
||||
* by some implementations of the `<type_traits>` header).
|
||||
*
|
||||
* Returns `true` if two member pointers refer to corresponding
|
||||
* members in the initial sequences of two class types.
|
||||
* ```
|
||||
* template<typename _Tp1, typename _Tp2, typename _Up1, typename _Up2>
|
||||
* constexpr bool is_corresponding_member(_Up1 _Tp1::*mp1, _Up2 _Tp2::*mp2 ) noexcept
|
||||
* = __builtin_is_corresponding_member(mp1, mp2);
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationBuiltInIsCorrespondingMember extends BuiltInOperation,
|
||||
@builtiniscorrespondingmember
|
||||
{
|
||||
override string toString() { result = "__builtin_is_corresponding_member" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationBuiltInIsCorrespondingMember" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__is_array` built-in operation (used by some implementations of the
|
||||
* `<type_traits>` header).
|
||||
@@ -1299,42 +1138,6 @@ class BuiltInOperationIsArray extends BuiltInOperation, @isarray {
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsArray" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__is_bounded_array` built-in operation (used by some implementations
|
||||
* of the `<type_traits>` header).
|
||||
*
|
||||
* Returns `true` if a type is a bounded array type.
|
||||
* ```
|
||||
* template<typename _Tp>
|
||||
* struct is_bounded_array
|
||||
* : public integral_constant<bool, __is_bounded_array(_Tp)>
|
||||
* { };
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationIsBoundedArray extends BuiltInOperation, @isboundedarray {
|
||||
override string toString() { result = "__is_bounded_array" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsBoundedArray" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__is_unbounded_array` built-in operation (used by some implementations
|
||||
* of the `<type_traits>` header).
|
||||
*
|
||||
* Returns `true` if a type is an unbounded array type.
|
||||
* ```
|
||||
* template<typename _Tp>
|
||||
* struct is_bounded_array
|
||||
* : public integral_constant<bool, __is_unbounded_array(_Tp)>
|
||||
* { };
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationIsUnboundedArray extends BuiltInOperation, @isunboundedarray {
|
||||
override string toString() { result = "__is_unbounded_array" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsUnboundedArray" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__array_rank` built-in operation (used by some implementations of the
|
||||
* `<type_traits>` header).
|
||||
@@ -1751,10 +1554,10 @@ class BuiltInBitCast extends BuiltInOperation, @builtinbitcast {
|
||||
*
|
||||
* Returns `true` if a type is a trivial type.
|
||||
* ```
|
||||
* template<typename _Tp>
|
||||
* struct is_trivial
|
||||
* : public integral_constant<bool, __is_trivial(_Tp)>
|
||||
* {};
|
||||
* template<typename _Tp>
|
||||
* struct is_trivial
|
||||
* : public integral_constant<bool, __is_trivial(_Tp)>
|
||||
* {};
|
||||
* ```
|
||||
*/
|
||||
class BuiltInIsTrivial extends BuiltInOperation, @istrivialexpr {
|
||||
@@ -1762,126 +1565,3 @@ class BuiltInIsTrivial extends BuiltInOperation, @istrivialexpr {
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BuiltInIsTrivial" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__reference_constructs_from_temporary` built-in operation
|
||||
* (used by some implementations of the `<type_traits>` header).
|
||||
*
|
||||
* Returns `true` if a reference type `_Tp` is bound to an expression of
|
||||
* type `_Up` in direct-initialization, and a temporary object is bound.
|
||||
* ```
|
||||
* template<typename _Tp, typename _Up>
|
||||
* struct reference_constructs_from_temporary
|
||||
* : public integral_constant<bool, __reference_constructs_from_temporary(_Tp, _Up)>
|
||||
* {};
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationReferenceConstructsFromTemporary extends BuiltInOperation,
|
||||
@referenceconstructsfromtemporary
|
||||
{
|
||||
override string toString() { result = "__reference_constructs_from_temporary" }
|
||||
|
||||
override string getAPrimaryQlClass() {
|
||||
result = "BuiltInOperationReferenceConstructsFromTemporary"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__reference_converts_from_temporary` built-in operation
|
||||
* (used by some implementations of the `<type_traits>` header).
|
||||
*
|
||||
* Returns `true` if a reference type `_Tp` is bound to an expression of
|
||||
* type `_Up` in copy-initialization, and a temporary object is bound.
|
||||
* ```
|
||||
* template<typename _Tp, typename _Up>
|
||||
* struct reference_converts_from_temporary
|
||||
* : public integral_constant<bool, __reference_converts_from_temporary(_Tp, _Up)>
|
||||
* {};
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationReferenceCovertsFromTemporary extends BuiltInOperation,
|
||||
@referenceconvertsfromtemporary
|
||||
{
|
||||
override string toString() { result = "__reference_converts_from_temporary" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationReferenceCovertsFromTemporary" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__reference_binds_to_temporary` built-in operation (used by some
|
||||
* implementations of the `<tuple>` header).
|
||||
*
|
||||
* Returns `true` if a reference of type `Type1` is bound to an expression of
|
||||
* type `Type1`, and a temporary object is bound.
|
||||
* ```
|
||||
* __reference_binds_to_temporary(Type1, Type2)
|
||||
*/
|
||||
class BuiltInOperationReferenceBindsToTemporary extends BuiltInOperation, @referencebindstotemporary
|
||||
{
|
||||
override string toString() { result = "__reference_binds_to_temporary" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationReferenceBindsToTemporary" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__builtin_has_attribute` built-in operation.
|
||||
*
|
||||
* Returns `true` if a type or expression has been declared with the
|
||||
* specified attribute.
|
||||
* ```
|
||||
* __attribute__ ((aligned(8))) int v;
|
||||
* bool has_attribute = __builtin_has_attribute(v, aligned);
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationHasAttribute extends BuiltInOperation, @builtinhasattribute {
|
||||
override string toString() { result = "__builtin_has_attribute" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationHasAttribute" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__is_referenceable` built-in operation.
|
||||
*
|
||||
* Returns `true` if a type can be referenced.
|
||||
* ```
|
||||
* bool is_referenceable = __is_referenceable(int);
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationIsReferenceable extends BuiltInOperation, @isreferenceable {
|
||||
override string toString() { result = "__is_referenceable" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsReferenceable" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `__is_valid_winrt_type` built-in operation. This is a Microsoft extension.
|
||||
*
|
||||
* Returns `true` if the type is a valid WinRT type.
|
||||
*/
|
||||
class BuiltInOperationIsValidWinRtType extends BuiltInOperation, @isvalidwinrttype {
|
||||
override string toString() { result = "__is_valid_winrt_type" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsValidWinRtType" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `__is_win_class` built-in operation. This is a Microsoft extension.
|
||||
*
|
||||
* Returns `true` if the class is a ref class.
|
||||
*/
|
||||
class BuiltInOperationIsWinClass extends BuiltInOperation, @iswinclass {
|
||||
override string toString() { result = "__is_win_class" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsWinClass" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `__is_win_class` built-in operation. This is a Microsoft extension.
|
||||
*
|
||||
* Returns `true` if the class is an interface class.
|
||||
*/
|
||||
class BuiltInOperationIsWinInterface extends BuiltInOperation, @iswininterface {
|
||||
override string toString() { result = "__is_win_interface" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsWinInterface" }
|
||||
}
|
||||
|
||||
@@ -855,16 +855,6 @@ class NewOrNewArrayExpr extends Expr, @any_new_expr {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the deallocation function is a destroying delete.
|
||||
*/
|
||||
predicate isDestroyingDeleteDeallocation() {
|
||||
exists(int form |
|
||||
expr_deallocator(underlyingElement(this), _, form) and
|
||||
form.bitAnd(4) != 0 // Bit two is the "destroying delete" bit
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type that is being allocated.
|
||||
*
|
||||
@@ -959,16 +949,6 @@ class NewArrayExpr extends NewOrNewArrayExpr, @new_array_expr {
|
||||
* gives nothing, as the 10 is considered part of the type.
|
||||
*/
|
||||
Expr getExtent() { result = this.getChild(2) }
|
||||
|
||||
/**
|
||||
* Gets the number of elements in the array, if available.
|
||||
*
|
||||
* For example, `new int[]{1,2,3}` has an array size of 3.
|
||||
*/
|
||||
int getArraySize() {
|
||||
result = this.getAllocatedType().(ArrayType).getArraySize() or
|
||||
result = this.getInitializer().(ArrayAggregateLiteral).getArraySize()
|
||||
}
|
||||
}
|
||||
|
||||
private class TDeleteOrDeleteArrayExpr = @delete_expr or @delete_array_expr;
|
||||
@@ -1035,16 +1015,6 @@ class DeleteOrDeleteArrayExpr extends Expr, TDeleteOrDeleteArrayExpr {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the deallocation function is a destroying delete.
|
||||
*/
|
||||
predicate isDestroyingDeleteDeallocation() {
|
||||
exists(int form |
|
||||
expr_deallocator(underlyingElement(this), _, form) and
|
||||
form.bitAnd(4) != 0 // Bit two is the "destroying delete" bit
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the object or array being deleted.
|
||||
*/
|
||||
|
||||
@@ -11,7 +11,6 @@ private import Node0ToString
|
||||
private import ModelUtil
|
||||
private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs as IO
|
||||
private import semmle.code.cpp.models.interfaces.DataFlow as DF
|
||||
private import semmle.code.cpp.dataflow.ExternalFlow as External
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
@@ -413,8 +412,6 @@ class ArgumentPosition = Position;
|
||||
|
||||
abstract class Position extends TPosition {
|
||||
abstract string toString();
|
||||
|
||||
abstract int getIndirectionIndex();
|
||||
}
|
||||
|
||||
class DirectPosition extends Position, TDirectPosition {
|
||||
@@ -424,15 +421,13 @@ class DirectPosition extends Position, TDirectPosition {
|
||||
|
||||
override string toString() {
|
||||
index = -1 and
|
||||
result = "this pointer"
|
||||
result = "this"
|
||||
or
|
||||
index != -1 and
|
||||
result = index.toString()
|
||||
}
|
||||
|
||||
int getIndex() { result = index }
|
||||
|
||||
final override int getIndirectionIndex() { result = 0 }
|
||||
}
|
||||
|
||||
class IndirectionPosition extends Position, TIndirectionPosition {
|
||||
@@ -443,13 +438,16 @@ class IndirectionPosition extends Position, TIndirectionPosition {
|
||||
|
||||
override string toString() {
|
||||
if argumentIndex = -1
|
||||
then result = repeatStars(indirectionIndex - 1) + "this"
|
||||
else result = repeatStars(indirectionIndex) + argumentIndex.toString()
|
||||
then if indirectionIndex > 0 then result = "this indirection" else result = "this"
|
||||
else
|
||||
if indirectionIndex > 0
|
||||
then result = argumentIndex.toString() + " indirection"
|
||||
else result = argumentIndex.toString()
|
||||
}
|
||||
|
||||
int getArgumentIndex() { result = argumentIndex }
|
||||
|
||||
final override int getIndirectionIndex() { result = indirectionIndex }
|
||||
int getIndirectionIndex() { result = indirectionIndex }
|
||||
}
|
||||
|
||||
newtype TPosition =
|
||||
@@ -990,18 +988,24 @@ predicate localMustFlowStep(Node node1, Node node2) { none() }
|
||||
|
||||
/** Gets the type of `n` used for type pruning. */
|
||||
DataFlowType getNodeType(Node n) {
|
||||
exists(n) and
|
||||
suppressUnusedNode(n) and
|
||||
result instanceof VoidType // stub implementation
|
||||
}
|
||||
|
||||
/** Gets a string representation of a type returned by `getNodeType`. */
|
||||
string ppReprType(DataFlowType t) { none() } // stub implementation
|
||||
|
||||
/**
|
||||
* Holds if `t1` and `t2` are compatible, that is, whether data can flow from
|
||||
* a node of type `t1` to a node of type `t2`.
|
||||
*/
|
||||
pragma[inline]
|
||||
predicate compatibleTypes(DataFlowType t1, DataFlowType t2) {
|
||||
t1 instanceof VoidType and t2 instanceof VoidType // stub implementation
|
||||
any() // stub implementation
|
||||
}
|
||||
|
||||
private predicate suppressUnusedNode(Node n) { any() }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Java QL library compatibility wrappers
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1094,11 +1098,7 @@ class SummarizedCallable extends DataFlowCallable, TSummarizedCallable {
|
||||
|
||||
class DataFlowExpr = Expr;
|
||||
|
||||
final private class TypeFinal = Type;
|
||||
|
||||
class DataFlowType extends TypeFinal {
|
||||
string toString() { result = "" }
|
||||
}
|
||||
class DataFlowType = Type;
|
||||
|
||||
cached
|
||||
private newtype TDataFlowCall =
|
||||
@@ -1247,44 +1247,43 @@ module IsUnreachableInCall {
|
||||
any(G::IRGuardCondition guard).ensuresLt(left, right, k, block, areEqual)
|
||||
}
|
||||
|
||||
class NodeRegion instanceof IRBlock {
|
||||
string toString() { result = "NodeRegion" }
|
||||
|
||||
predicate contains(Node n) { this = n.getBasicBlock() }
|
||||
}
|
||||
|
||||
predicate isUnreachableInCall(NodeRegion block, DataFlowCall call) {
|
||||
predicate isUnreachableInCall(Node n, DataFlowCall call) {
|
||||
exists(
|
||||
InstructionDirectParameterNode paramNode, ConstantIntegralTypeArgumentNode arg,
|
||||
IntegerConstantInstruction constant, int k, Operand left, Operand right, int argval
|
||||
IntegerConstantInstruction constant, int k, Operand left, Operand right, IRBlock block
|
||||
|
|
||||
// arg flows into `paramNode`
|
||||
DataFlowImplCommon::viableParamArg(call, pragma[only_bind_into](paramNode),
|
||||
pragma[only_bind_into](arg)) and
|
||||
DataFlowImplCommon::viableParamArg(call, paramNode, arg) and
|
||||
left = constant.getAUse() and
|
||||
right = valueNumber(paramNode.getInstruction()).getAUse() and
|
||||
argval = arg.getValue()
|
||||
block = n.getBasicBlock()
|
||||
|
|
||||
// and there's a guard condition which ensures that the result of `left == right + k` is `areEqual`
|
||||
exists(boolean areEqual | ensuresEq(left, right, k, block, areEqual) |
|
||||
exists(boolean areEqual |
|
||||
ensuresEq(pragma[only_bind_into](left), pragma[only_bind_into](right),
|
||||
pragma[only_bind_into](k), pragma[only_bind_into](block), areEqual)
|
||||
|
|
||||
// this block ensures that left = right + k, but it holds that `left != right + k`
|
||||
areEqual = true and
|
||||
constant.getValue().toInt() != argval + k
|
||||
constant.getValue().toInt() != arg.getValue() + k
|
||||
or
|
||||
// this block ensures that or `left != right + k`, but it holds that `left = right + k`
|
||||
areEqual = false and
|
||||
constant.getValue().toInt() = argval + k
|
||||
constant.getValue().toInt() = arg.getValue() + k
|
||||
)
|
||||
or
|
||||
// or there's a guard condition which ensures that the result of `left < right + k` is `isLessThan`
|
||||
exists(boolean isLessThan | ensuresLt(left, right, k, block, isLessThan) |
|
||||
exists(boolean isLessThan |
|
||||
ensuresLt(pragma[only_bind_into](left), pragma[only_bind_into](right),
|
||||
pragma[only_bind_into](k), pragma[only_bind_into](block), isLessThan)
|
||||
|
|
||||
isLessThan = true and
|
||||
// this block ensures that `left < right + k`, but it holds that `left >= right + k`
|
||||
constant.getValue().toInt() >= argval + k
|
||||
constant.getValue().toInt() >= arg.getValue() + k
|
||||
or
|
||||
// this block ensures that `left >= right + k`, but it holds that `left < right + k`
|
||||
isLessThan = false and
|
||||
constant.getValue().toInt() < argval + k
|
||||
constant.getValue().toInt() < arg.getValue() + k
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -1296,7 +1295,7 @@ import IsUnreachableInCall
|
||||
* Holds if access paths with `c` at their head always should be tracked at high
|
||||
* precision. This disables adaptive access path precision for such access paths.
|
||||
*/
|
||||
predicate forceHighPrecision(Content c) { c instanceof ElementContent }
|
||||
predicate forceHighPrecision(Content c) { none() }
|
||||
|
||||
/** Holds if `n` should be hidden from path explanations. */
|
||||
predicate nodeIsHidden(Node n) {
|
||||
@@ -1307,8 +1306,6 @@ predicate nodeIsHidden(Node n) {
|
||||
n instanceof FinalGlobalValue
|
||||
or
|
||||
n instanceof InitialGlobalValue
|
||||
or
|
||||
n instanceof SsaPhiInputNode
|
||||
}
|
||||
|
||||
predicate neverSkipInPathGraph(Node n) {
|
||||
@@ -1335,9 +1332,9 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
|
||||
/** Extra data-flow steps needed for lambda flow analysis. */
|
||||
predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() }
|
||||
|
||||
predicate knownSourceModel(Node source, string model) { External::sourceNode(source, _, model) }
|
||||
predicate knownSourceModel(Node source, string model) { none() }
|
||||
|
||||
predicate knownSinkModel(Node sink, string model) { External::sinkNode(sink, _, model) }
|
||||
predicate knownSinkModel(Node sink, string model) { none() }
|
||||
|
||||
/**
|
||||
* Holds if flow is allowed to pass from parameter `p` and back to itself as a
|
||||
@@ -1367,8 +1364,7 @@ private predicate unionHasApproxName(Cpp::Union u, string s) { s = u.getName().c
|
||||
cached
|
||||
private newtype TContentApprox =
|
||||
TFieldApproxContent(string s) { fieldHasApproxName(_, s) } or
|
||||
TUnionApproxContent(string s) { unionHasApproxName(_, s) } or
|
||||
TElementApproxContent()
|
||||
TUnionApproxContent(string s) { unionHasApproxName(_, s) }
|
||||
|
||||
/** An approximated `Content`. */
|
||||
class ContentApprox extends TContentApprox {
|
||||
@@ -1399,10 +1395,6 @@ private class UnionApproxContent extends ContentApprox, TUnionApproxContent {
|
||||
final override string toString() { result = s }
|
||||
}
|
||||
|
||||
private class ElementApproxContent extends ContentApprox, TElementApproxContent {
|
||||
final override string toString() { result = "ElementApprox" }
|
||||
}
|
||||
|
||||
/** Gets an approximated value for content `c`. */
|
||||
pragma[inline]
|
||||
ContentApprox getContentApprox(Content c) {
|
||||
@@ -1417,9 +1409,6 @@ ContentApprox getContentApprox(Content c) {
|
||||
u = c.(UnionContent).getUnion() and
|
||||
unionHasApproxName(u, prefix)
|
||||
)
|
||||
or
|
||||
c instanceof ElementContent and
|
||||
result instanceof ElementApproxContent
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1615,8 +1604,6 @@ private Instruction getAnInstruction(Node n) {
|
||||
or
|
||||
result = n.(SsaPhiNode).getPhiNode().getBasicBlock().getFirstInstruction()
|
||||
or
|
||||
result = n.(SsaPhiInputNode).getBasicBlock().getFirstInstruction()
|
||||
or
|
||||
n.(IndirectInstruction).hasInstructionAndIndirectionIndex(result, _)
|
||||
or
|
||||
not n instanceof IndirectInstruction and
|
||||
@@ -1679,14 +1666,6 @@ class DataFlowSecondLevelScope extends TDataFlowSecondLevelScope {
|
||||
/** Gets the second-level scope containing the node `n`, if any. */
|
||||
DataFlowSecondLevelScope getSecondLevelScope(Node n) { result.getANode() = n }
|
||||
|
||||
/**
|
||||
* Gets the maximum number of indirections to use for `ElementContent`.
|
||||
*
|
||||
* This should be equal to the largest number of stars (i.e., `*`s) in any
|
||||
* `Element` content across all of our MaD summaries, sources, and sinks.
|
||||
*/
|
||||
int getMaxElementContentIndirectionIndex() { result = 5 }
|
||||
|
||||
/**
|
||||
* Module that defines flow through iterators.
|
||||
* For example,
|
||||
@@ -1754,7 +1733,7 @@ module IteratorFlow {
|
||||
crementCall = def.getValue().asInstruction().(StoreInstruction).getSourceValue() and
|
||||
sv = def.getSourceVariable() and
|
||||
bb.getInstruction(i) = crementCall and
|
||||
Ssa::ssaDefReachesReadExt(sv, result.asDef(), bb, i)
|
||||
Ssa::ssaDefReachesRead(sv, result.asDef(), bb, i)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1788,7 +1767,7 @@ module IteratorFlow {
|
||||
isIteratorWrite(writeToDeref, address) and
|
||||
operandForFullyConvertedCall(address, starCall) and
|
||||
bbStar.getInstruction(iStar) = starCall and
|
||||
Ssa::ssaDefReachesReadExt(_, def.asDef(), bbStar, iStar) and
|
||||
Ssa::ssaDefReachesRead(_, def.asDef(), bbStar, iStar) and
|
||||
ultimate = getAnUltimateDefinition*(def) and
|
||||
beginStore = ultimate.getValue().asInstruction() and
|
||||
operandForFullyConvertedCall(beginStore.getSourceValueOperand(), beginCall)
|
||||
@@ -1799,7 +1778,7 @@ module IteratorFlow {
|
||||
* Holds if `(bb, i)` contains a write to an iterator that may have been obtained
|
||||
* by calling `begin` (or related functions) on the variable `v`.
|
||||
*/
|
||||
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
|
||||
predicate variableWrite(IRBlock bb, int i, SourceVariable v, boolean certain) {
|
||||
certain = false and
|
||||
exists(GetsIteratorCall beginCall, Instruction writeToDeref, IRBlock bbQual, int iQual |
|
||||
isIteratorStoreInstruction(beginCall, writeToDeref) and
|
||||
@@ -1810,7 +1789,7 @@ module IteratorFlow {
|
||||
}
|
||||
|
||||
/** Holds if `(bb, i)` reads the container variable `v`. */
|
||||
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
|
||||
predicate variableRead(IRBlock bb, int i, SourceVariable v, boolean certain) {
|
||||
Ssa::variableRead(bb, i, v, certain)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ private import SsaInternals as Ssa
|
||||
private import DataFlowImplCommon as DataFlowImplCommon
|
||||
private import codeql.util.Unit
|
||||
private import Node0ToString
|
||||
import ExprNodes
|
||||
|
||||
/**
|
||||
* The IR dataflow graph consists of the following nodes:
|
||||
@@ -46,7 +45,6 @@ private newtype TIRDataFlowNode =
|
||||
or
|
||||
Ssa::isModifiableByCall(operand, indirectionIndex)
|
||||
} or
|
||||
TSsaPhiInputNode(Ssa::PhiNode phi, IRBlock input) { phi.hasInputFromBlock(_, _, _, _, input) } or
|
||||
TSsaPhiNode(Ssa::PhiNode phi) or
|
||||
TSsaIteratorNode(IteratorFlow::IteratorFlowNode n) or
|
||||
TRawIndirectOperand0(Node0Impl node, int indirectionIndex) {
|
||||
@@ -116,13 +114,6 @@ predicate conversionFlow(
|
||||
instrTo.(CheckedConvertOrNullInstruction).getUnaryOperand() = opFrom
|
||||
or
|
||||
instrTo.(InheritanceConversionInstruction).getUnaryOperand() = opFrom
|
||||
or
|
||||
exists(BuiltInInstruction builtIn |
|
||||
builtIn = instrTo and
|
||||
// __builtin_bit_cast
|
||||
builtIn.getBuiltInOperation() instanceof BuiltInBitCast and
|
||||
opFrom = builtIn.getAnOperand()
|
||||
)
|
||||
)
|
||||
or
|
||||
additional = true and
|
||||
@@ -167,12 +158,6 @@ class Node extends TIRDataFlowNode {
|
||||
/** Gets the operands corresponding to this node, if any. */
|
||||
Operand asOperand() { result = this.(OperandNode).getOperand() }
|
||||
|
||||
/**
|
||||
* Gets the operand that is indirectly tracked by this node behind `index`
|
||||
* number of indirections.
|
||||
*/
|
||||
Operand asIndirectOperand(int index) { hasOperandAndIndex(this, result, index) }
|
||||
|
||||
/**
|
||||
* Holds if this node is at index `i` in basic block `block`.
|
||||
*
|
||||
@@ -185,9 +170,6 @@ class Node extends TIRDataFlowNode {
|
||||
or
|
||||
this.(SsaPhiNode).getPhiNode().getBasicBlock() = block and i = -1
|
||||
or
|
||||
this.(SsaPhiInputNode).getBlock() = block and
|
||||
i = block.getInstructionCount()
|
||||
or
|
||||
this.(RawIndirectOperand).getOperand().getUse() = block.getInstruction(i)
|
||||
or
|
||||
this.(RawIndirectInstruction).getInstruction() = block.getInstruction(i)
|
||||
@@ -640,7 +622,7 @@ class SsaPhiNode extends Node, TSsaPhiNode {
|
||||
|
||||
final override Location getLocationImpl() { result = phi.getBasicBlock().getLocation() }
|
||||
|
||||
override string toStringImpl() { result = phi.toString() }
|
||||
override string toStringImpl() { result = "Phi" }
|
||||
|
||||
/**
|
||||
* Gets a node that is used as input to this phi node.
|
||||
@@ -649,7 +631,7 @@ class SsaPhiNode extends Node, TSsaPhiNode {
|
||||
*/
|
||||
cached
|
||||
final Node getAnInput(boolean fromBackEdge) {
|
||||
result.(SsaPhiInputNode).getPhiNode() = phi and
|
||||
localFlowStep(result, this) and
|
||||
exists(IRBlock bPhi, IRBlock bResult |
|
||||
bPhi = phi.getBasicBlock() and bResult = result.getBasicBlock()
|
||||
|
|
||||
@@ -672,58 +654,6 @@ class SsaPhiNode extends Node, TSsaPhiNode {
|
||||
predicate isPhiRead() { phi.isPhiRead() }
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*
|
||||
* A node that is used as an input to a phi node.
|
||||
*
|
||||
* This class exists to allow more powerful barrier guards. Consider this
|
||||
* example:
|
||||
*
|
||||
* ```cpp
|
||||
* int x = source();
|
||||
* if(!safe(x)) {
|
||||
* x = clear();
|
||||
* }
|
||||
* // phi node for x here
|
||||
* sink(x);
|
||||
* ```
|
||||
*
|
||||
* At the phi node for `x` it is neither the case that `x` is dominated by
|
||||
* `safe(x)`, or is the case that the phi is dominated by a clearing of `x`.
|
||||
*
|
||||
* By inserting a "phi input" node as the last entry in the basic block that
|
||||
* defines the inputs to the phi we can conclude that each of those inputs are
|
||||
* safe to pass to `sink`.
|
||||
*/
|
||||
class SsaPhiInputNode extends Node, TSsaPhiInputNode {
|
||||
Ssa::PhiNode phi;
|
||||
IRBlock block;
|
||||
|
||||
SsaPhiInputNode() { this = TSsaPhiInputNode(phi, block) }
|
||||
|
||||
/** Gets the phi node associated with this node. */
|
||||
Ssa::PhiNode getPhiNode() { result = phi }
|
||||
|
||||
/** Gets the basic block in which this input originates. */
|
||||
IRBlock getBlock() { result = block }
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
override Declaration getFunction() { result = phi.getBasicBlock().getEnclosingFunction() }
|
||||
|
||||
override DataFlowType getType() { result = this.getSourceVariable().getType() }
|
||||
|
||||
override predicate isGLValue() { phi.getSourceVariable().isGLValue() }
|
||||
|
||||
final override Location getLocationImpl() { result = block.getLastInstruction().getLocation() }
|
||||
|
||||
override string toStringImpl() { result = "Phi input" }
|
||||
|
||||
/** Gets the source variable underlying this phi node. */
|
||||
Ssa::SourceVariable getSourceVariable() { result = phi.getSourceVariable() }
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: do not use.
|
||||
*
|
||||
@@ -1297,6 +1227,466 @@ class UninitializedNode extends Node {
|
||||
LocalVariable getLocalVariable() { result = v }
|
||||
}
|
||||
|
||||
private module GetConvertedResultExpression {
|
||||
private import semmle.code.cpp.ir.implementation.raw.internal.TranslatedExpr
|
||||
private import semmle.code.cpp.ir.implementation.raw.internal.InstructionTag
|
||||
|
||||
private Operand getAnInitializeDynamicAllocationInstructionAddress() {
|
||||
result = any(InitializeDynamicAllocationInstruction init).getAllocationAddressOperand()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the expression that should be returned as the result expression from `instr`.
|
||||
*
|
||||
* Note that this predicate may return multiple results in cases where a conversion belongs to a
|
||||
* different AST element than its operand.
|
||||
*/
|
||||
Expr getConvertedResultExpression(Instruction instr, int n) {
|
||||
// Only fully converted instructions have a result for `asConvertedExpr`
|
||||
not conversionFlow(unique(Operand op |
|
||||
// The address operand of a `InitializeDynamicAllocationInstruction` is
|
||||
// special: we need to handle it during dataflow (since it's
|
||||
// effectively a store to an indirection), but it doesn't appear in
|
||||
// source syntax, so dataflow node <-> expression conversion shouldn't
|
||||
// care about it.
|
||||
op = getAUse(instr) and not op = getAnInitializeDynamicAllocationInstructionAddress()
|
||||
|
|
||||
op
|
||||
), _, false, false) and
|
||||
result = getConvertedResultExpressionImpl(instr) and
|
||||
n = 0
|
||||
or
|
||||
// If the conversion also has a result then we return multiple results
|
||||
exists(Operand operand | conversionFlow(operand, instr, false, false) |
|
||||
n = 1 and
|
||||
result = getConvertedResultExpressionImpl(operand.getDef())
|
||||
or
|
||||
result = getConvertedResultExpression(operand.getDef(), n - 1)
|
||||
)
|
||||
}
|
||||
|
||||
private Expr getConvertedResultExpressionImpl0(Instruction instr) {
|
||||
// IR construction inserts an additional cast to a `size_t` on the extent
|
||||
// of a `new[]` expression. The resulting `ConvertInstruction` doesn't have
|
||||
// a result for `getConvertedResultExpression`. We remap this here so that
|
||||
// this `ConvertInstruction` maps to the result of the expression that
|
||||
// represents the extent.
|
||||
exists(TranslatedNonConstantAllocationSize tas |
|
||||
result = tas.getExtent().getExpr() and
|
||||
instr = tas.getInstruction(AllocationExtentConvertTag())
|
||||
)
|
||||
or
|
||||
// There's no instruction that returns `ParenthesisExpr`, but some queries
|
||||
// expect this
|
||||
exists(TranslatedTransparentConversion ttc |
|
||||
result = ttc.getExpr().(ParenthesisExpr) and
|
||||
instr = ttc.getResult()
|
||||
)
|
||||
or
|
||||
// Certain expressions generate `CopyValueInstruction`s only when they
|
||||
// are needed. Examples of this include crement operations and compound
|
||||
// assignment operations. For example:
|
||||
// ```cpp
|
||||
// int x = ...
|
||||
// int y = x++;
|
||||
// ```
|
||||
// this generate IR like:
|
||||
// ```
|
||||
// r1(glval<int>) = VariableAddress[x] :
|
||||
// r2(int) = Constant[0] :
|
||||
// m3(int) = Store[x] : &:r1, r2
|
||||
// r4(glval<int>) = VariableAddress[y] :
|
||||
// r5(glval<int>) = VariableAddress[x] :
|
||||
// r6(int) = Load[x] : &:r5, m3
|
||||
// r7(int) = Constant[1] :
|
||||
// r8(int) = Add : r6, r7
|
||||
// m9(int) = Store[x] : &:r5, r8
|
||||
// r11(int) = CopyValue : r6
|
||||
// m12(int) = Store[y] : &:r4, r11
|
||||
// ```
|
||||
// When the `CopyValueInstruction` is not generated there is no instruction
|
||||
// whose `getConvertedResultExpression` maps back to the expression. When
|
||||
// such an instruction doesn't exist it means that the old value is not
|
||||
// needed, and in that case the only value that will propagate forward in
|
||||
// the program is the value that's been updated. So in those cases we just
|
||||
// use the result of `node.asDefinition()` as the result of `node.asExpr()`.
|
||||
exists(TranslatedCoreExpr tco |
|
||||
tco.getInstruction(_) = instr and
|
||||
tco.producesExprResult() and
|
||||
result = asDefinitionImpl0(instr)
|
||||
)
|
||||
}
|
||||
|
||||
private Expr getConvertedResultExpressionImpl(Instruction instr) {
|
||||
result = getConvertedResultExpressionImpl0(instr)
|
||||
or
|
||||
not exists(getConvertedResultExpressionImpl0(instr)) and
|
||||
result = instr.getConvertedResultExpression()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the result for `node.asDefinition()` (when `node` is the instruction
|
||||
* node that wraps `store`) in the cases where `store.getAst()` should not be
|
||||
* used to define the result of `node.asDefinition()`.
|
||||
*/
|
||||
private Expr asDefinitionImpl0(StoreInstruction store) {
|
||||
// For an expression such as `i += 2` we pretend that the generated
|
||||
// `StoreInstruction` contains the result of the expression even though
|
||||
// this isn't totally aligned with the C/C++ standard.
|
||||
exists(TranslatedAssignOperation tao |
|
||||
store = tao.getInstruction(AssignmentStoreTag()) and
|
||||
result = tao.getExpr()
|
||||
)
|
||||
or
|
||||
// Similarly for `i++` and `++i` we pretend that the generated
|
||||
// `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
|
||||
result = tco.getExpr()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the expression returned by `store.getAst()` should not be
|
||||
* returned as the result of `node.asDefinition()` when `node` is the
|
||||
* instruction node that wraps `store`.
|
||||
*/
|
||||
private predicate excludeAsDefinitionResult(StoreInstruction store) {
|
||||
// Exclude the store to the temporary generated by a ternary expression.
|
||||
exists(TranslatedConditionalExpr tce |
|
||||
store = tce.getInstruction(ConditionValueFalseStoreTag())
|
||||
or
|
||||
store = tce.getInstruction(ConditionValueTrueStoreTag())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the expression that represents the result of `StoreInstruction` for
|
||||
* dataflow purposes.
|
||||
*
|
||||
* For example, consider the following example
|
||||
* ```cpp
|
||||
* int x = 42; // 1
|
||||
* x = 34; // 2
|
||||
* ++x; // 3
|
||||
* x++; // 4
|
||||
* x += 1; // 5
|
||||
* int y = x += 2; // 6
|
||||
* ```
|
||||
* For (1) the result is `42`.
|
||||
* For (2) the result is `x = 34`.
|
||||
* For (3) the result is `++x`.
|
||||
* For (4) the result is `x++`.
|
||||
* For (5) the result is `x += 1`.
|
||||
* For (6) there are two results:
|
||||
* - For the `StoreInstruction` generated by `x += 2` the result
|
||||
* is `x += 2`
|
||||
* - For the `StoreInstruction` generated by `int y = ...` the result
|
||||
* is also `x += 2`
|
||||
*/
|
||||
Expr asDefinitionImpl(StoreInstruction store) {
|
||||
not exists(asDefinitionImpl0(store)) and
|
||||
not excludeAsDefinitionResult(store) and
|
||||
result = store.getAst().(Expr).getUnconverted()
|
||||
or
|
||||
result = asDefinitionImpl0(store)
|
||||
}
|
||||
}
|
||||
|
||||
private import GetConvertedResultExpression
|
||||
|
||||
/** Holds if `node` is an `OperandNode` that should map `node.asExpr()` to `e`. */
|
||||
predicate exprNodeShouldBeOperand(OperandNode node, Expr e, int n) {
|
||||
not exprNodeShouldBeIndirectOperand(_, e, n) and
|
||||
exists(Instruction def |
|
||||
unique( | | getAUse(def)) = node.getOperand() and
|
||||
e = getConvertedResultExpression(def, n)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `node` should be an `IndirectOperand` that maps `node.asIndirectExpr()` to `e`. */
|
||||
private predicate indirectExprNodeShouldBeIndirectOperand(
|
||||
IndirectOperand node, Expr e, int n, int indirectionIndex
|
||||
) {
|
||||
exists(Instruction def |
|
||||
node.hasOperandAndIndirectionIndex(unique( | | getAUse(def)), indirectionIndex) and
|
||||
e = getConvertedResultExpression(def, n)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `node` should be an `IndirectOperand` that maps `node.asExpr()` to `e`. */
|
||||
private predicate exprNodeShouldBeIndirectOperand(IndirectOperand node, Expr e, int n) {
|
||||
exists(ArgumentOperand operand |
|
||||
// When an argument (qualifier or positional) is a prvalue and the
|
||||
// parameter (qualifier or positional) is a (const) reference, IR
|
||||
// construction introduces a temporary `IRVariable`. The `VariableAddress`
|
||||
// instruction has the argument as its `getConvertedResultExpression`
|
||||
// result. However, the instruction actually represents the _address_ of
|
||||
// the argument. So to fix this mismatch, we have the indirection of the
|
||||
// `VariableAddressInstruction` map to the expression.
|
||||
node.hasOperandAndIndirectionIndex(operand, 1) and
|
||||
e = getConvertedResultExpression(operand.getDef(), n) and
|
||||
operand.getDef().(VariableAddressInstruction).getIRVariable() instanceof IRTempVariable
|
||||
)
|
||||
}
|
||||
|
||||
private predicate exprNodeShouldBeIndirectOutNode(IndirectArgumentOutNode node, Expr e, int n) {
|
||||
exists(CallInstruction call |
|
||||
call.getStaticCallTarget() instanceof Constructor and
|
||||
e = getConvertedResultExpression(call, n) and
|
||||
call.getThisArgumentOperand() = node.getAddressOperand()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `node` should be an instruction node that maps `node.asExpr()` to `e`. */
|
||||
predicate exprNodeShouldBeInstruction(Node node, Expr e, int n) {
|
||||
not exprNodeShouldBeOperand(_, e, n) and
|
||||
not exprNodeShouldBeIndirectOutNode(_, e, n) and
|
||||
not exprNodeShouldBeIndirectOperand(_, e, n) and
|
||||
e = getConvertedResultExpression(node.asInstruction(), n)
|
||||
}
|
||||
|
||||
/** Holds if `node` should be an `IndirectInstruction` that maps `node.asIndirectExpr()` to `e`. */
|
||||
predicate indirectExprNodeShouldBeIndirectInstruction(
|
||||
IndirectInstruction node, Expr e, int n, int indirectionIndex
|
||||
) {
|
||||
not indirectExprNodeShouldBeIndirectOperand(_, e, n, indirectionIndex) and
|
||||
exists(Instruction instr |
|
||||
node.hasInstructionAndIndirectionIndex(instr, indirectionIndex) and
|
||||
e = getConvertedResultExpression(instr, n)
|
||||
)
|
||||
}
|
||||
|
||||
abstract private class ExprNodeBase extends Node {
|
||||
/**
|
||||
* Gets the expression corresponding to this node, if any. The returned
|
||||
* expression may be a `Conversion`.
|
||||
*/
|
||||
abstract Expr getConvertedExpr(int n);
|
||||
|
||||
/** Gets the non-conversion expression corresponding to this node, if any. */
|
||||
final Expr getExpr(int n) { result = this.getConvertedExpr(n).getUnconverted() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there exists a dataflow node whose `asExpr(n)` should evaluate
|
||||
* to `e`.
|
||||
*/
|
||||
private predicate exprNodeShouldBe(Expr e, int n) {
|
||||
exprNodeShouldBeInstruction(_, e, n) or
|
||||
exprNodeShouldBeOperand(_, e, n) or
|
||||
exprNodeShouldBeIndirectOutNode(_, e, n) or
|
||||
exprNodeShouldBeIndirectOperand(_, e, n)
|
||||
}
|
||||
|
||||
private class InstructionExprNode extends ExprNodeBase, InstructionNode {
|
||||
InstructionExprNode() {
|
||||
exists(Expr e, int n |
|
||||
exprNodeShouldBeInstruction(this, e, n) and
|
||||
not exists(Expr conv |
|
||||
exprNodeShouldBe(conv, n + 1) and
|
||||
conv.getUnconverted() = e.getUnconverted()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
final override Expr getConvertedExpr(int n) { exprNodeShouldBeInstruction(this, result, n) }
|
||||
}
|
||||
|
||||
private class OperandExprNode extends ExprNodeBase, OperandNode {
|
||||
OperandExprNode() {
|
||||
exists(Expr e, int n |
|
||||
exprNodeShouldBeOperand(this, e, n) and
|
||||
not exists(Expr conv |
|
||||
exprNodeShouldBe(conv, n + 1) and
|
||||
conv.getUnconverted() = e.getUnconverted()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
final override Expr getConvertedExpr(int n) { exprNodeShouldBeOperand(this, result, n) }
|
||||
}
|
||||
|
||||
abstract private class IndirectExprNodeBase extends Node {
|
||||
/**
|
||||
* Gets the expression corresponding to this node, if any. The returned
|
||||
* expression may be a `Conversion`.
|
||||
*/
|
||||
abstract Expr getConvertedExpr(int n, int indirectionIndex);
|
||||
|
||||
/** Gets the non-conversion expression corresponding to this node, if any. */
|
||||
final Expr getExpr(int n, int indirectionIndex) {
|
||||
result = this.getConvertedExpr(n, indirectionIndex).getUnconverted()
|
||||
}
|
||||
}
|
||||
|
||||
/** A signature for converting an indirect node to an expression. */
|
||||
private signature module IndirectNodeToIndirectExprSig {
|
||||
/** The indirect node class to be converted to an expression */
|
||||
class IndirectNode;
|
||||
|
||||
/**
|
||||
* Holds if the indirect expression at indirection index `indirectionIndex`
|
||||
* of `node` is `e`. The integer `n` specifies how many conversions has been
|
||||
* applied to `node`.
|
||||
*/
|
||||
predicate indirectNodeHasIndirectExpr(IndirectNode node, Expr e, int n, int indirectionIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* A module that implements the logic for deciding whether an indirect node
|
||||
* should be an `IndirectExprNode`.
|
||||
*/
|
||||
private module IndirectNodeToIndirectExpr<IndirectNodeToIndirectExprSig Sig> {
|
||||
import Sig
|
||||
|
||||
/**
|
||||
* This predicate shifts the indirection index by one when `conv` is a
|
||||
* `ReferenceDereferenceExpr`.
|
||||
*
|
||||
* This is necessary because `ReferenceDereferenceExpr` is a conversion
|
||||
* in the AST, but appears as a `LoadInstruction` in the IR.
|
||||
*/
|
||||
bindingset[e, indirectionIndex]
|
||||
private predicate adjustForReference(
|
||||
Expr e, int indirectionIndex, Expr conv, int adjustedIndirectionIndex
|
||||
) {
|
||||
conv.(ReferenceDereferenceExpr).getExpr() = e and
|
||||
adjustedIndirectionIndex = indirectionIndex - 1
|
||||
or
|
||||
not conv instanceof ReferenceDereferenceExpr and
|
||||
conv = e and
|
||||
adjustedIndirectionIndex = indirectionIndex
|
||||
}
|
||||
|
||||
/** Holds if `node` should be an `IndirectExprNode`. */
|
||||
predicate charpred(IndirectNode node) {
|
||||
exists(Expr e, int n, int indirectionIndex |
|
||||
indirectNodeHasIndirectExpr(node, e, n, indirectionIndex) and
|
||||
not exists(Expr conv, int adjustedIndirectionIndex |
|
||||
adjustForReference(e, indirectionIndex, conv, adjustedIndirectionIndex) and
|
||||
indirectExprNodeShouldBe(conv, n + 1, adjustedIndirectionIndex)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate indirectExprNodeShouldBe(Expr e, int n, int indirectionIndex) {
|
||||
indirectExprNodeShouldBeIndirectOperand(_, e, n, indirectionIndex) or
|
||||
indirectExprNodeShouldBeIndirectInstruction(_, e, n, indirectionIndex)
|
||||
}
|
||||
|
||||
private module IndirectOperandIndirectExprNodeImpl implements IndirectNodeToIndirectExprSig {
|
||||
class IndirectNode = IndirectOperand;
|
||||
|
||||
predicate indirectNodeHasIndirectExpr = indirectExprNodeShouldBeIndirectOperand/4;
|
||||
}
|
||||
|
||||
module IndirectOperandToIndirectExpr =
|
||||
IndirectNodeToIndirectExpr<IndirectOperandIndirectExprNodeImpl>;
|
||||
|
||||
private class IndirectOperandIndirectExprNode extends IndirectExprNodeBase instanceof IndirectOperand
|
||||
{
|
||||
IndirectOperandIndirectExprNode() { IndirectOperandToIndirectExpr::charpred(this) }
|
||||
|
||||
final override Expr getConvertedExpr(int n, int index) {
|
||||
IndirectOperandToIndirectExpr::indirectNodeHasIndirectExpr(this, result, n, index)
|
||||
}
|
||||
}
|
||||
|
||||
private module IndirectInstructionIndirectExprNodeImpl implements IndirectNodeToIndirectExprSig {
|
||||
class IndirectNode = IndirectInstruction;
|
||||
|
||||
predicate indirectNodeHasIndirectExpr = indirectExprNodeShouldBeIndirectInstruction/4;
|
||||
}
|
||||
|
||||
module IndirectInstructionToIndirectExpr =
|
||||
IndirectNodeToIndirectExpr<IndirectInstructionIndirectExprNodeImpl>;
|
||||
|
||||
private class IndirectInstructionIndirectExprNode extends IndirectExprNodeBase instanceof IndirectInstruction
|
||||
{
|
||||
IndirectInstructionIndirectExprNode() { IndirectInstructionToIndirectExpr::charpred(this) }
|
||||
|
||||
final override Expr getConvertedExpr(int n, int index) {
|
||||
IndirectInstructionToIndirectExpr::indirectNodeHasIndirectExpr(this, result, n, index)
|
||||
}
|
||||
}
|
||||
|
||||
private class IndirectArgumentOutExprNode extends ExprNodeBase, IndirectArgumentOutNode {
|
||||
IndirectArgumentOutExprNode() { exprNodeShouldBeIndirectOutNode(this, _, _) }
|
||||
|
||||
final override Expr getConvertedExpr(int n) { exprNodeShouldBeIndirectOutNode(this, result, n) }
|
||||
}
|
||||
|
||||
private class IndirectOperandExprNode extends ExprNodeBase instanceof IndirectOperand {
|
||||
IndirectOperandExprNode() { exprNodeShouldBeIndirectOperand(this, _, _) }
|
||||
|
||||
final override Expr getConvertedExpr(int n) { exprNodeShouldBeIndirectOperand(this, result, n) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression, viewed as a node in a data flow graph.
|
||||
*/
|
||||
class ExprNode extends Node instanceof ExprNodeBase {
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
Expr getExpr(int n) { result = super.getExpr(n) }
|
||||
|
||||
/**
|
||||
* Gets the non-conversion expression corresponding to this node, if any. If
|
||||
* this node strictly (in the sense of `getConvertedExpr`) corresponds to a
|
||||
* `Conversion`, then the result is that `Conversion`'s non-`Conversion` base
|
||||
* expression.
|
||||
*/
|
||||
final Expr getExpr() { result = this.getExpr(_) }
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
Expr getConvertedExpr(int n) { result = super.getConvertedExpr(n) }
|
||||
|
||||
/**
|
||||
* Gets the expression corresponding to this node, if any. The returned
|
||||
* expression may be a `Conversion`.
|
||||
*/
|
||||
final Expr getConvertedExpr() { result = this.getConvertedExpr(_) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An indirect expression, viewed as a node in a data flow graph.
|
||||
*/
|
||||
class IndirectExprNode extends Node instanceof IndirectExprNodeBase {
|
||||
/**
|
||||
* Gets the non-conversion expression corresponding to this node, if any. If
|
||||
* this node strictly (in the sense of `getConvertedExpr`) corresponds to a
|
||||
* `Conversion`, then the result is that `Conversion`'s non-`Conversion` base
|
||||
* expression.
|
||||
*/
|
||||
final Expr getExpr(int indirectionIndex) { result = this.getExpr(_, indirectionIndex) }
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
Expr getExpr(int n, int indirectionIndex) { result = super.getExpr(n, indirectionIndex) }
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
Expr getConvertedExpr(int n, int indirectionIndex) {
|
||||
result = super.getConvertedExpr(n, indirectionIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the expression corresponding to this node, if any. The returned
|
||||
* expression may be a `Conversion`.
|
||||
*/
|
||||
Expr getConvertedExpr(int indirectionIndex) {
|
||||
result = this.getConvertedExpr(_, indirectionIndex)
|
||||
}
|
||||
}
|
||||
|
||||
abstract private class AbstractParameterNode extends Node {
|
||||
/**
|
||||
* Holds if this node is the parameter of `f` at the specified position. The
|
||||
@@ -1786,9 +2176,6 @@ private module Cached {
|
||||
// Def-use/Use-use flow
|
||||
Ssa::ssaFlow(nodeFrom, nodeTo)
|
||||
or
|
||||
// Phi input -> Phi
|
||||
nodeFrom.(SsaPhiInputNode).getPhiNode() = nodeTo.(SsaPhiNode).getPhiNode()
|
||||
or
|
||||
IteratorFlow::localFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
// Operand -> Instruction flow
|
||||
@@ -2083,9 +2470,6 @@ private newtype TContent =
|
||||
indirectionIndex =
|
||||
[1 .. max(Ssa::getMaxIndirectionsForType(getAFieldWithSize(u, bytes).getUnspecifiedType()))]
|
||||
)
|
||||
} or
|
||||
TElementContent(int indirectionIndex) {
|
||||
indirectionIndex = [1 .. getMaxElementContentIndirectionIndex()]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2196,25 +2580,6 @@ class UnionContent extends Content, TUnionContent {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A `Content` that represents one of the elements of a
|
||||
* container (e.g., `std::vector`).
|
||||
*/
|
||||
class ElementContent extends Content, TElementContent {
|
||||
int indirectionIndex;
|
||||
|
||||
ElementContent() { this = TElementContent(indirectionIndex) }
|
||||
|
||||
pragma[inline]
|
||||
override int getIndirectionIndex() {
|
||||
pragma[only_bind_into](result) = pragma[only_bind_out](indirectionIndex)
|
||||
}
|
||||
|
||||
override predicate impliesClearOf(Content c) { none() }
|
||||
|
||||
override string toString() { result = contentStars(this) + "element" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An entity that represents a set of `Content`s.
|
||||
*
|
||||
@@ -2249,22 +2614,6 @@ class ContentSet instanceof Content {
|
||||
}
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate guardControlsPhiInput(
|
||||
IRGuardCondition g, boolean branch, Ssa::Definition def, IRBlock input, Ssa::PhiNode phi
|
||||
) {
|
||||
phi.hasInputFromBlock(def, _, _, _, input) and
|
||||
(
|
||||
g.controls(input, branch)
|
||||
or
|
||||
exists(EdgeKind kind |
|
||||
g.getBlock() = input and
|
||||
kind = getConditionalEdge(branch) and
|
||||
input.getSuccessor(kind) = phi.getBasicBlock()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
|
||||
*
|
||||
@@ -2313,21 +2662,13 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
|
||||
*
|
||||
* NOTE: If an indirect expression is tracked, use `getAnIndirectBarrierNode` instead.
|
||||
*/
|
||||
Node getABarrierNode() {
|
||||
ExprNode getABarrierNode() {
|
||||
exists(IRGuardCondition g, Expr e, ValueNumber value, boolean edge |
|
||||
e = value.getAnInstruction().getConvertedResultExpression() and
|
||||
result.asConvertedExpr() = e and
|
||||
result.getConvertedExpr() = e and
|
||||
guardChecks(g, value.getAnInstruction().getConvertedResultExpression(), edge) and
|
||||
g.controls(result.getBasicBlock(), edge)
|
||||
)
|
||||
or
|
||||
exists(
|
||||
IRGuardCondition g, boolean branch, Ssa::DefinitionExt def, IRBlock input, Ssa::PhiNode phi
|
||||
|
|
||||
guardChecks(g, def.getARead().asOperand().getDef().getConvertedResultExpression(), branch) and
|
||||
guardControlsPhiInput(g, branch, def, input, phi) and
|
||||
result = TSsaPhiInputNode(phi, input)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2363,7 +2704,7 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
|
||||
*
|
||||
* NOTE: If a non-indirect expression is tracked, use `getABarrierNode` instead.
|
||||
*/
|
||||
Node getAnIndirectBarrierNode() { result = getAnIndirectBarrierNode(_) }
|
||||
IndirectExprNode getAnIndirectBarrierNode() { result = getAnIndirectBarrierNode(_) }
|
||||
|
||||
/**
|
||||
* Gets an indirect expression node with indirection index `indirectionIndex` that is
|
||||
@@ -2399,23 +2740,13 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
|
||||
*
|
||||
* NOTE: If a non-indirect expression is tracked, use `getABarrierNode` instead.
|
||||
*/
|
||||
Node getAnIndirectBarrierNode(int indirectionIndex) {
|
||||
IndirectExprNode getAnIndirectBarrierNode(int indirectionIndex) {
|
||||
exists(IRGuardCondition g, Expr e, ValueNumber value, boolean edge |
|
||||
e = value.getAnInstruction().getConvertedResultExpression() and
|
||||
result.asIndirectConvertedExpr(indirectionIndex) = e and
|
||||
result.getConvertedExpr(indirectionIndex) = e and
|
||||
guardChecks(g, value.getAnInstruction().getConvertedResultExpression(), edge) and
|
||||
g.controls(result.getBasicBlock(), edge)
|
||||
)
|
||||
or
|
||||
exists(
|
||||
IRGuardCondition g, boolean branch, Ssa::DefinitionExt def, IRBlock input, Ssa::PhiNode phi
|
||||
|
|
||||
guardChecks(g,
|
||||
def.getARead().asIndirectOperand(indirectionIndex).getDef().getConvertedResultExpression(),
|
||||
branch) and
|
||||
guardControlsPhiInput(g, branch, def, input, phi) and
|
||||
result = TSsaPhiInputNode(phi, input)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2424,14 +2755,6 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
|
||||
*/
|
||||
signature predicate instructionGuardChecksSig(IRGuardCondition g, Instruction instr, boolean branch);
|
||||
|
||||
private EdgeKind getConditionalEdge(boolean branch) {
|
||||
branch = true and
|
||||
result instanceof TrueEdge
|
||||
or
|
||||
branch = false and
|
||||
result instanceof FalseEdge
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a set of barrier nodes for a guard that validates an instruction.
|
||||
*
|
||||
@@ -2440,20 +2763,12 @@ private EdgeKind getConditionalEdge(boolean branch) {
|
||||
*/
|
||||
module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardChecks> {
|
||||
/** Gets a node that is safely guarded by the given guard check. */
|
||||
Node getABarrierNode() {
|
||||
ExprNode getABarrierNode() {
|
||||
exists(IRGuardCondition g, ValueNumber value, boolean edge, Operand use |
|
||||
instructionGuardChecks(g, value.getAnInstruction(), edge) and
|
||||
use = value.getAnInstruction().getAUse() and
|
||||
result.asOperand() = use and
|
||||
g.controls(result.getBasicBlock(), edge)
|
||||
)
|
||||
or
|
||||
exists(
|
||||
IRGuardCondition g, boolean branch, Ssa::DefinitionExt def, IRBlock input, Ssa::PhiNode phi
|
||||
|
|
||||
instructionGuardChecks(g, def.getARead().asOperand().getDef(), branch) and
|
||||
guardControlsPhiInput(g, branch, def, input, phi) and
|
||||
result = TSsaPhiInputNode(phi, input)
|
||||
g.controls(use.getDef().getBlock(), edge)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,518 +0,0 @@
|
||||
/**
|
||||
* Provides the classes `ExprNode` and `IndirectExprNode` for converting between `Expr` and `Node`.
|
||||
*/
|
||||
|
||||
private import cpp
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import DataFlowUtil
|
||||
private import DataFlowPrivate
|
||||
private import semmle.code.cpp.ir.implementation.raw.internal.TranslatedExpr
|
||||
private import semmle.code.cpp.ir.implementation.raw.internal.InstructionTag
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
private Operand getAnInitializeDynamicAllocationInstructionAddress() {
|
||||
result = any(InitializeDynamicAllocationInstruction init).getAllocationAddressOperand()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the expression that should be returned as the result expression from `instr`.
|
||||
*
|
||||
* Note that this predicate may return multiple results in cases where a conversion belongs to a
|
||||
* different AST element than its operand.
|
||||
*/
|
||||
private Expr getConvertedResultExpression(Instruction instr, int n) {
|
||||
// Only fully converted instructions have a result for `asConvertedExpr`
|
||||
not conversionFlow(unique(Operand op |
|
||||
// The address operand of a `InitializeDynamicAllocationInstruction` is
|
||||
// special: we need to handle it during dataflow (since it's
|
||||
// effectively a store to an indirection), but it doesn't appear in
|
||||
// source syntax, so dataflow node <-> expression conversion shouldn't
|
||||
// care about it.
|
||||
op = getAUse(instr) and not op = getAnInitializeDynamicAllocationInstructionAddress()
|
||||
|
|
||||
op
|
||||
), _, false, false) and
|
||||
result = getConvertedResultExpressionImpl(instr) and
|
||||
n = 0
|
||||
or
|
||||
// If the conversion also has a result then we return multiple results
|
||||
exists(Operand operand | conversionFlow(operand, instr, false, false) |
|
||||
n = 1 and
|
||||
result = getConvertedResultExpressionImpl(operand.getDef())
|
||||
or
|
||||
result = getConvertedResultExpression(operand.getDef(), n - 1)
|
||||
)
|
||||
}
|
||||
|
||||
private Expr getConvertedResultExpressionImpl0(Instruction instr) {
|
||||
// IR construction inserts an additional cast to a `size_t` on the extent
|
||||
// of a `new[]` expression. The resulting `ConvertInstruction` doesn't have
|
||||
// a result for `getConvertedResultExpression`. We remap this here so that
|
||||
// this `ConvertInstruction` maps to the result of the expression that
|
||||
// represents the extent.
|
||||
exists(TranslatedNonConstantAllocationSize tas |
|
||||
result = tas.getExtent().getExpr() and
|
||||
instr = tas.getInstruction(AllocationExtentConvertTag())
|
||||
)
|
||||
or
|
||||
// There's no instruction that returns `ParenthesisExpr`, but some queries
|
||||
// expect this
|
||||
exists(TranslatedTransparentConversion ttc |
|
||||
result = ttc.getExpr().(ParenthesisExpr) and
|
||||
instr = ttc.getResult()
|
||||
)
|
||||
or
|
||||
// Certain expressions generate `CopyValueInstruction`s only when they
|
||||
// are needed. Examples of this include crement operations and compound
|
||||
// assignment operations. For example:
|
||||
// ```cpp
|
||||
// int x = ...
|
||||
// int y = x++;
|
||||
// ```
|
||||
// this generate IR like:
|
||||
// ```
|
||||
// r1(glval<int>) = VariableAddress[x] :
|
||||
// r2(int) = Constant[0] :
|
||||
// m3(int) = Store[x] : &:r1, r2
|
||||
// r4(glval<int>) = VariableAddress[y] :
|
||||
// r5(glval<int>) = VariableAddress[x] :
|
||||
// r6(int) = Load[x] : &:r5, m3
|
||||
// r7(int) = Constant[1] :
|
||||
// r8(int) = Add : r6, r7
|
||||
// m9(int) = Store[x] : &:r5, r8
|
||||
// r11(int) = CopyValue : r6
|
||||
// m12(int) = Store[y] : &:r4, r11
|
||||
// ```
|
||||
// When the `CopyValueInstruction` is not generated there is no instruction
|
||||
// whose `getConvertedResultExpression` maps back to the expression. When
|
||||
// such an instruction doesn't exist it means that the old value is not
|
||||
// needed, and in that case the only value that will propagate forward in
|
||||
// the program is the value that's been updated. So in those cases we just
|
||||
// use the result of `node.asDefinition()` as the result of `node.asExpr()`.
|
||||
exists(TranslatedCoreExpr tco |
|
||||
tco.getInstruction(_) = instr and
|
||||
tco.producesExprResult() and
|
||||
result = asDefinitionImpl0(instr)
|
||||
)
|
||||
}
|
||||
|
||||
private Expr getConvertedResultExpressionImpl(Instruction instr) {
|
||||
result = getConvertedResultExpressionImpl0(instr)
|
||||
or
|
||||
not exists(getConvertedResultExpressionImpl0(instr)) and
|
||||
result = instr.getConvertedResultExpression()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the result for `node.asDefinition()` (when `node` is the instruction
|
||||
* node that wraps `store`) in the cases where `store.getAst()` should not be
|
||||
* used to define the result of `node.asDefinition()`.
|
||||
*/
|
||||
private Expr asDefinitionImpl0(StoreInstruction store) {
|
||||
// For an expression such as `i += 2` we pretend that the generated
|
||||
// `StoreInstruction` contains the result of the expression even though
|
||||
// this isn't totally aligned with the C/C++ standard.
|
||||
exists(TranslatedAssignOperation tao |
|
||||
store = tao.getInstruction(AssignmentStoreTag()) and
|
||||
result = tao.getExpr()
|
||||
)
|
||||
or
|
||||
// Similarly for `i++` and `++i` we pretend that the generated
|
||||
// `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
|
||||
result = tco.getExpr()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the expression returned by `store.getAst()` should not be
|
||||
* returned as the result of `node.asDefinition()` when `node` is the
|
||||
* instruction node that wraps `store`.
|
||||
*/
|
||||
private predicate excludeAsDefinitionResult(StoreInstruction store) {
|
||||
// Exclude the store to the temporary generated by a ternary expression.
|
||||
exists(TranslatedConditionalExpr tce |
|
||||
store = tce.getInstruction(ConditionValueFalseStoreTag())
|
||||
or
|
||||
store = tce.getInstruction(ConditionValueTrueStoreTag())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the expression that represents the result of `StoreInstruction` for
|
||||
* dataflow purposes.
|
||||
*
|
||||
* For example, consider the following example
|
||||
* ```cpp
|
||||
* int x = 42; // 1
|
||||
* x = 34; // 2
|
||||
* ++x; // 3
|
||||
* x++; // 4
|
||||
* x += 1; // 5
|
||||
* int y = x += 2; // 6
|
||||
* ```
|
||||
* For (1) the result is `42`.
|
||||
* For (2) the result is `x = 34`.
|
||||
* For (3) the result is `++x`.
|
||||
* For (4) the result is `x++`.
|
||||
* For (5) the result is `x += 1`.
|
||||
* For (6) there are two results:
|
||||
* - For the `StoreInstruction` generated by `x += 2` the result
|
||||
* is `x += 2`
|
||||
* - For the `StoreInstruction` generated by `int y = ...` the result
|
||||
* is also `x += 2`
|
||||
*/
|
||||
cached
|
||||
Expr asDefinitionImpl(StoreInstruction store) {
|
||||
not exists(asDefinitionImpl0(store)) and
|
||||
not excludeAsDefinitionResult(store) and
|
||||
result = store.getAst().(Expr).getUnconverted()
|
||||
or
|
||||
result = asDefinitionImpl0(store)
|
||||
}
|
||||
|
||||
/** Holds if `node` is an `OperandNode` that should map `node.asExpr()` to `e`. */
|
||||
private predicate exprNodeShouldBeOperand(OperandNode node, Expr e, int n) {
|
||||
not exprNodeShouldBeIndirectOperand(_, e, n) and
|
||||
exists(Instruction def |
|
||||
unique( | | getAUse(def)) = node.getOperand() and
|
||||
e = getConvertedResultExpression(def, n)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `node` should be an `IndirectOperand` that maps `node.asIndirectExpr()` to `e`. */
|
||||
private predicate indirectExprNodeShouldBeIndirectOperand(
|
||||
IndirectOperand node, Expr e, int n, int indirectionIndex
|
||||
) {
|
||||
exists(Instruction def |
|
||||
node.hasOperandAndIndirectionIndex(unique( | | getAUse(def)), indirectionIndex) and
|
||||
e = getConvertedResultExpression(def, n)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `operand`'s definition is a `VariableAddressInstruction` whose variable is a temporary */
|
||||
private predicate isIRTempVariable(Operand operand) {
|
||||
operand.getDef().(VariableAddressInstruction).getIRVariable() instanceof IRTempVariable
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` is an indirect operand whose operand is an argument, and
|
||||
* the `n`'th expression associated with the operand is `e`.
|
||||
*/
|
||||
private predicate isIndirectOperandOfArgument(
|
||||
IndirectOperand node, ArgumentOperand operand, Expr e, int n
|
||||
) {
|
||||
node.hasOperandAndIndirectionIndex(operand, 1) and
|
||||
e = getConvertedResultExpression(operand.getDef(), n)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `opFrom` is an operand to a conversion, and `opTo` is the unique
|
||||
* use of the conversion.
|
||||
*/
|
||||
private predicate isConversionStep(Operand opFrom, Operand opTo) {
|
||||
exists(Instruction mid |
|
||||
conversionFlow(opFrom, mid, false, false) and
|
||||
opTo = unique( | | getAUse(mid))
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if an operand that satisfies `isIRTempVariable` flows to `op`
|
||||
* through a (possibly empty) sequence of conversions.
|
||||
*/
|
||||
private predicate irTempOperandConversionFlows(Operand op) {
|
||||
isIRTempVariable(op)
|
||||
or
|
||||
exists(Operand mid |
|
||||
irTempOperandConversionFlows(mid) and
|
||||
isConversionStep(mid, op)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `node` should be an `IndirectOperand` that maps `node.asExpr()` to `e`. */
|
||||
private predicate exprNodeShouldBeIndirectOperand(IndirectOperand node, Expr e, int n) {
|
||||
exists(ArgumentOperand operand |
|
||||
// When an argument (qualifier or positional) is a prvalue and the
|
||||
// parameter (qualifier or positional) is a (const) reference, IR
|
||||
// construction introduces a temporary `IRVariable`. The `VariableAddress`
|
||||
// instruction has the argument as its `getConvertedResultExpression`
|
||||
// result. However, the instruction actually represents the _address_ of
|
||||
// the argument. So to fix this mismatch, we have the indirection of the
|
||||
// `VariableAddressInstruction` map to the expression.
|
||||
isIndirectOperandOfArgument(node, operand, e, n) and
|
||||
irTempOperandConversionFlows(operand)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate exprNodeShouldBeIndirectOutNode(IndirectArgumentOutNode node, Expr e, int n) {
|
||||
exists(CallInstruction call |
|
||||
call.getStaticCallTarget() instanceof Constructor and
|
||||
e = getConvertedResultExpression(call, n) and
|
||||
call.getThisArgumentOperand() = node.getAddressOperand()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `node` should be an instruction node that maps `node.asExpr()` to `e`. */
|
||||
private predicate exprNodeShouldBeInstruction(Node node, Expr e, int n) {
|
||||
not exprNodeShouldBeOperand(_, e, n) and
|
||||
not exprNodeShouldBeIndirectOutNode(_, e, n) and
|
||||
not exprNodeShouldBeIndirectOperand(_, e, n) and
|
||||
e = getConvertedResultExpression(node.asInstruction(), n)
|
||||
}
|
||||
|
||||
/** Holds if `node` should be an `IndirectInstruction` that maps `node.asIndirectExpr()` to `e`. */
|
||||
private predicate indirectExprNodeShouldBeIndirectInstruction(
|
||||
IndirectInstruction node, Expr e, int n, int indirectionIndex
|
||||
) {
|
||||
not indirectExprNodeShouldBeIndirectOperand(_, e, n, indirectionIndex) and
|
||||
exists(Instruction instr |
|
||||
node.hasInstructionAndIndirectionIndex(instr, indirectionIndex) and
|
||||
e = getConvertedResultExpression(instr, n)
|
||||
)
|
||||
}
|
||||
|
||||
abstract private class ExprNodeBase extends Node {
|
||||
/**
|
||||
* Gets the expression corresponding to this node, if any. The returned
|
||||
* expression may be a `Conversion`.
|
||||
*/
|
||||
abstract Expr getConvertedExpr(int n);
|
||||
|
||||
/** Gets the non-conversion expression corresponding to this node, if any. */
|
||||
final Expr getExpr(int n) { result = this.getConvertedExpr(n).getUnconverted() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there exists a dataflow node whose `asExpr(n)` should evaluate
|
||||
* to `e`.
|
||||
*/
|
||||
private predicate exprNodeShouldBe(Expr e, int n) {
|
||||
exprNodeShouldBeInstruction(_, e, n) or
|
||||
exprNodeShouldBeOperand(_, e, n) or
|
||||
exprNodeShouldBeIndirectOutNode(_, e, n) or
|
||||
exprNodeShouldBeIndirectOperand(_, e, n)
|
||||
}
|
||||
|
||||
private class InstructionExprNode extends ExprNodeBase, InstructionNode {
|
||||
InstructionExprNode() {
|
||||
exists(Expr e, int n |
|
||||
exprNodeShouldBeInstruction(this, e, n) and
|
||||
not exists(Expr conv |
|
||||
exprNodeShouldBe(conv, n + 1) and
|
||||
conv.getUnconverted() = e.getUnconverted()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
final override Expr getConvertedExpr(int n) { exprNodeShouldBeInstruction(this, result, n) }
|
||||
}
|
||||
|
||||
private class OperandExprNode extends ExprNodeBase, OperandNode {
|
||||
OperandExprNode() {
|
||||
exists(Expr e, int n |
|
||||
exprNodeShouldBeOperand(this, e, n) and
|
||||
not exists(Expr conv |
|
||||
exprNodeShouldBe(conv, n + 1) and
|
||||
conv.getUnconverted() = e.getUnconverted()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
final override Expr getConvertedExpr(int n) { exprNodeShouldBeOperand(this, result, n) }
|
||||
}
|
||||
|
||||
abstract private class IndirectExprNodeBase extends Node {
|
||||
/**
|
||||
* Gets the expression corresponding to this node, if any. The returned
|
||||
* expression may be a `Conversion`.
|
||||
*/
|
||||
abstract Expr getConvertedExpr(int n, int indirectionIndex);
|
||||
|
||||
/** Gets the non-conversion expression corresponding to this node, if any. */
|
||||
final Expr getExpr(int n, int indirectionIndex) {
|
||||
result = this.getConvertedExpr(n, indirectionIndex).getUnconverted()
|
||||
}
|
||||
}
|
||||
|
||||
/** A signature for converting an indirect node to an expression. */
|
||||
private signature module IndirectNodeToIndirectExprSig {
|
||||
/** The indirect node class to be converted to an expression */
|
||||
class IndirectNode;
|
||||
|
||||
/**
|
||||
* Holds if the indirect expression at indirection index `indirectionIndex`
|
||||
* of `node` is `e`. The integer `n` specifies how many conversions has been
|
||||
* applied to `node`.
|
||||
*/
|
||||
predicate indirectNodeHasIndirectExpr(IndirectNode node, Expr e, int n, int indirectionIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* A module that implements the logic for deciding whether an indirect node
|
||||
* should be an `IndirectExprNode`.
|
||||
*/
|
||||
private module IndirectNodeToIndirectExpr<IndirectNodeToIndirectExprSig Sig> {
|
||||
import Sig
|
||||
|
||||
/**
|
||||
* This predicate shifts the indirection index by one when `conv` is a
|
||||
* `ReferenceDereferenceExpr`.
|
||||
*
|
||||
* This is necessary because `ReferenceDereferenceExpr` is a conversion
|
||||
* in the AST, but appears as a `LoadInstruction` in the IR.
|
||||
*/
|
||||
bindingset[e, indirectionIndex]
|
||||
private predicate adjustForReference(
|
||||
Expr e, int indirectionIndex, Expr conv, int adjustedIndirectionIndex
|
||||
) {
|
||||
conv.(ReferenceDereferenceExpr).getExpr() = e and
|
||||
adjustedIndirectionIndex = indirectionIndex - 1
|
||||
or
|
||||
not conv instanceof ReferenceDereferenceExpr and
|
||||
conv = e and
|
||||
adjustedIndirectionIndex = indirectionIndex
|
||||
}
|
||||
|
||||
/** Holds if `node` should be an `IndirectExprNode`. */
|
||||
predicate charpred(IndirectNode node) {
|
||||
exists(Expr e, int n, int indirectionIndex |
|
||||
indirectNodeHasIndirectExpr(node, e, n, indirectionIndex) and
|
||||
not exists(Expr conv, int adjustedIndirectionIndex |
|
||||
adjustForReference(e, indirectionIndex, conv, adjustedIndirectionIndex) and
|
||||
indirectExprNodeShouldBe(conv, n + 1, adjustedIndirectionIndex)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate indirectExprNodeShouldBe(Expr e, int n, int indirectionIndex) {
|
||||
indirectExprNodeShouldBeIndirectOperand(_, e, n, indirectionIndex) or
|
||||
indirectExprNodeShouldBeIndirectInstruction(_, e, n, indirectionIndex)
|
||||
}
|
||||
|
||||
private module IndirectOperandIndirectExprNodeImpl implements IndirectNodeToIndirectExprSig {
|
||||
class IndirectNode = IndirectOperand;
|
||||
|
||||
predicate indirectNodeHasIndirectExpr = indirectExprNodeShouldBeIndirectOperand/4;
|
||||
}
|
||||
|
||||
module IndirectOperandToIndirectExpr =
|
||||
IndirectNodeToIndirectExpr<IndirectOperandIndirectExprNodeImpl>;
|
||||
|
||||
private class IndirectOperandIndirectExprNode extends IndirectExprNodeBase instanceof IndirectOperand
|
||||
{
|
||||
IndirectOperandIndirectExprNode() { IndirectOperandToIndirectExpr::charpred(this) }
|
||||
|
||||
final override Expr getConvertedExpr(int n, int index) {
|
||||
IndirectOperandToIndirectExpr::indirectNodeHasIndirectExpr(this, result, n, index)
|
||||
}
|
||||
}
|
||||
|
||||
private module IndirectInstructionIndirectExprNodeImpl implements IndirectNodeToIndirectExprSig {
|
||||
class IndirectNode = IndirectInstruction;
|
||||
|
||||
predicate indirectNodeHasIndirectExpr = indirectExprNodeShouldBeIndirectInstruction/4;
|
||||
}
|
||||
|
||||
module IndirectInstructionToIndirectExpr =
|
||||
IndirectNodeToIndirectExpr<IndirectInstructionIndirectExprNodeImpl>;
|
||||
|
||||
private class IndirectInstructionIndirectExprNode extends IndirectExprNodeBase instanceof IndirectInstruction
|
||||
{
|
||||
IndirectInstructionIndirectExprNode() { IndirectInstructionToIndirectExpr::charpred(this) }
|
||||
|
||||
final override Expr getConvertedExpr(int n, int index) {
|
||||
IndirectInstructionToIndirectExpr::indirectNodeHasIndirectExpr(this, result, n, index)
|
||||
}
|
||||
}
|
||||
|
||||
private class IndirectArgumentOutExprNode extends ExprNodeBase, IndirectArgumentOutNode {
|
||||
IndirectArgumentOutExprNode() { exprNodeShouldBeIndirectOutNode(this, _, _) }
|
||||
|
||||
final override Expr getConvertedExpr(int n) { exprNodeShouldBeIndirectOutNode(this, result, n) }
|
||||
}
|
||||
|
||||
private class IndirectOperandExprNode extends ExprNodeBase instanceof IndirectOperand {
|
||||
IndirectOperandExprNode() { exprNodeShouldBeIndirectOperand(this, _, _) }
|
||||
|
||||
final override Expr getConvertedExpr(int n) { exprNodeShouldBeIndirectOperand(this, result, n) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression, viewed as a node in a data flow graph.
|
||||
*/
|
||||
cached
|
||||
class ExprNode extends Node instanceof ExprNodeBase {
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
cached
|
||||
Expr getExpr(int n) { result = super.getExpr(n) }
|
||||
|
||||
/**
|
||||
* Gets the non-conversion expression corresponding to this node, if any. If
|
||||
* this node strictly (in the sense of `getConvertedExpr`) corresponds to a
|
||||
* `Conversion`, then the result is that `Conversion`'s non-`Conversion` base
|
||||
* expression.
|
||||
*/
|
||||
cached
|
||||
final Expr getExpr() { result = this.getExpr(_) }
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
cached
|
||||
Expr getConvertedExpr(int n) { result = super.getConvertedExpr(n) }
|
||||
|
||||
/**
|
||||
* Gets the expression corresponding to this node, if any. The returned
|
||||
* expression may be a `Conversion`.
|
||||
*/
|
||||
cached
|
||||
final Expr getConvertedExpr() { result = this.getConvertedExpr(_) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An indirect expression, viewed as a node in a data flow graph.
|
||||
*/
|
||||
cached
|
||||
class IndirectExprNode extends Node instanceof IndirectExprNodeBase {
|
||||
/**
|
||||
* Gets the non-conversion expression corresponding to this node, if any. If
|
||||
* this node strictly (in the sense of `getConvertedExpr`) corresponds to a
|
||||
* `Conversion`, then the result is that `Conversion`'s non-`Conversion` base
|
||||
* expression.
|
||||
*/
|
||||
cached
|
||||
final Expr getExpr(int indirectionIndex) { result = this.getExpr(_, indirectionIndex) }
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
cached
|
||||
Expr getExpr(int n, int indirectionIndex) { result = super.getExpr(n, indirectionIndex) }
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
cached
|
||||
Expr getConvertedExpr(int n, int indirectionIndex) {
|
||||
result = super.getConvertedExpr(n, indirectionIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the expression corresponding to this node, if any. The returned
|
||||
* expression may be a `Conversion`.
|
||||
*/
|
||||
cached
|
||||
Expr getConvertedExpr(int indirectionIndex) {
|
||||
result = this.getConvertedExpr(_, indirectionIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
import Cached
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user