mirror of
https://github.com/github/codeql.git
synced 2026-05-16 12:17:07 +02:00
Compare commits
1 Commits
dbartol/co
...
remove-jav
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee314a4dad |
@@ -1,23 +1,8 @@
|
||||
{
|
||||
"provide": [
|
||||
"*/ql/src/qlpack.yml",
|
||||
"*/ql/lib/qlpack.yml",
|
||||
"*/ql/test/qlpack.yml",
|
||||
"*/ql/examples/qlpack.yml",
|
||||
"*/upgrades/qlpack.yml",
|
||||
"cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml",
|
||||
"javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml",
|
||||
"javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml",
|
||||
"misc/legacy-support/*/qlpack.yml",
|
||||
"misc/suite-helpers/qlpack.yml",
|
||||
"ruby/extractor-pack/codeql-extractor.yml",
|
||||
"ruby/ql/consistency-queries/qlpack.yml"
|
||||
],
|
||||
"versionPolicies": {
|
||||
"default": {
|
||||
"requireChangeNotes": true,
|
||||
"committedPrereleaseSuffix": "dev",
|
||||
"committedVersion": "nextPatchRelease"
|
||||
}
|
||||
}
|
||||
}
|
||||
{ "provide": [ "*/ql/src/qlpack.yml",
|
||||
"*/ql/lib/qlpack.yml",
|
||||
"*/ql/test/qlpack.yml",
|
||||
"cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml",
|
||||
"*/ql/examples/qlpack.yml",
|
||||
"*/upgrades/qlpack.yml",
|
||||
"misc/legacy-support/*/qlpack.yml",
|
||||
"misc/suite-helpers/qlpack.yml" ] }
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
{
|
||||
"extensions": [
|
||||
"rust-lang.rust",
|
||||
"bungcip.better-toml",
|
||||
"github.vscode-codeql",
|
||||
"slevesque.vscode-zipexplorer"
|
||||
],
|
||||
"settings": {
|
||||
"files.watcherExclude": {
|
||||
"**/target/**": true
|
||||
},
|
||||
"codeQL.runningQueries.memory": 2048
|
||||
}
|
||||
}
|
||||
|
||||
14
.github/actions/fetch-codeql/action.yml
vendored
14
.github/actions/fetch-codeql/action.yml
vendored
@@ -1,14 +0,0 @@
|
||||
name: Fetch CodeQL
|
||||
description: Fetches the latest version of CodeQL
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Fetch CodeQL
|
||||
shell: bash
|
||||
run: |
|
||||
LATEST=$(gh release list --repo https://github.com/github/codeql-cli-binaries | cut -f 1 | grep -v beta | sort --version-sort | tail -1)
|
||||
gh release download --repo https://github.com/github/codeql-cli-binaries --pattern codeql-linux64.zip "$LATEST"
|
||||
unzip -q -d "${RUNNER_TEMP}" codeql-linux64.zip
|
||||
echo "${RUNNER_TEMP}/codeql" >> "${GITHUB_PATH}"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
18
.github/dependabot.yml
vendored
18
.github/dependabot.yml
vendored
@@ -1,18 +0,0 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "cargo"
|
||||
directory: "ruby/node-types"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
- package-ecosystem: "cargo"
|
||||
directory: "ruby/generator"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
- package-ecosystem: "cargo"
|
||||
directory: "ruby/extractor"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
- package-ecosystem: "cargo"
|
||||
directory: "ruby/autobuilder"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
4
.github/labeler.yml
vendored
4
.github/labeler.yml
vendored
@@ -18,10 +18,6 @@ Python:
|
||||
- python/**/*
|
||||
- change-notes/**/*python*
|
||||
|
||||
Ruby:
|
||||
- ruby/**/*
|
||||
- change-notes/**/*ruby*
|
||||
|
||||
documentation:
|
||||
- "**/*.qhelp"
|
||||
- "**/*.md"
|
||||
|
||||
@@ -6,8 +6,6 @@ on:
|
||||
- '.github/workflows/csv-coverage-pr-comment.yml'
|
||||
- '*/ql/src/**/*.ql'
|
||||
- '*/ql/src/**/*.qll'
|
||||
- '*/ql/lib/**/*.ql'
|
||||
- '*/ql/lib/**/*.qll'
|
||||
- 'misc/scripts/library-coverage/*.py'
|
||||
# input data files
|
||||
- '*/documentation/library-coverage/cwe-sink.csv'
|
||||
|
||||
31
.github/workflows/post-pr-comment.yml
vendored
31
.github/workflows/post-pr-comment.yml
vendored
@@ -1,31 +0,0 @@
|
||||
name: Post pull-request comment
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Query help preview"]
|
||||
types:
|
||||
- completed
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
post_comment:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download artifact
|
||||
run: gh run download "${WORKFLOW_RUN_ID}" --repo "${GITHUB_REPOSITORY}" --name "comment"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
WORKFLOW_RUN_ID: ${{ github.event.workflow_run.id }}
|
||||
- run: |
|
||||
PR="$(grep -o '^[0-9]\+$' pr.txt)"
|
||||
PR_HEAD_SHA="$(gh api "/repos/${GITHUB_REPOSITORY}/pulls/${PR}" --jq .head.sha)"
|
||||
# Check that the pull-request head SHA matches the head SHA of the workflow run
|
||||
if [ "${WORKFLOW_RUN_HEAD_SHA}" != "${PR_HEAD_SHA}" ]; then
|
||||
echo "PR head SHA ${PR_HEAD_SHA} does not match workflow_run event SHA ${WORKFLOW_RUN_HEAD_SHA}. Stopping." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
gh pr comment "${PR}" --repo "${GITHUB_REPOSITORY}" -F comment.txt
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
WORKFLOW_RUN_HEAD_SHA: ${{ github.event.workflow_run.head_commit.id }}
|
||||
63
.github/workflows/qhelp-pr-preview.yml
vendored
63
.github/workflows/qhelp-pr-preview.yml
vendored
@@ -1,63 +0,0 @@
|
||||
name: Query help preview
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- "rc/*"
|
||||
paths:
|
||||
- "ruby/**/*.qhelp"
|
||||
|
||||
jobs:
|
||||
qhelp:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo "${{ github.event.number }}" > pr.txt
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: comment
|
||||
path: pr.txt
|
||||
retention-days: 1
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 2
|
||||
persist-credentials: false
|
||||
- uses: ./.github/actions/fetch-codeql
|
||||
- name: Determine changed files
|
||||
id: changes
|
||||
run: |
|
||||
(git diff -z --name-only --diff-filter=ACMRT HEAD~1 HEAD | grep -z '.qhelp$' | grep -z -v '.inc.qhelp';
|
||||
git diff -z --name-only --diff-filter=ACMRT HEAD~1 HEAD | grep -z '.inc.qhelp$' | xargs --null -rn1 basename | xargs --null -rn1 git grep -z -l) |
|
||||
grep -z '.qhelp$' | grep -z -v '^-' | sort -z -u > "${RUNNER_TEMP}/paths.txt"
|
||||
|
||||
- name: QHelp preview
|
||||
run: |
|
||||
EXIT_CODE=0
|
||||
echo "QHelp previews:" > comment.txt
|
||||
while read -r -d $'\0' path; do
|
||||
if [ ! -f "${path}" ]; then
|
||||
exit 1
|
||||
fi
|
||||
echo "<details> <summary>${path}</summary>"
|
||||
echo
|
||||
codeql generate query-help --format=markdown -- "./${path}" 2> errors.txt || EXIT_CODE="$?"
|
||||
if [ -s errors.txt ]; then
|
||||
echo "# errors/warnings:"
|
||||
echo '```'
|
||||
cat errors.txt
|
||||
cat errors.txt 1>&2
|
||||
echo '```'
|
||||
fi
|
||||
echo "</details>"
|
||||
done < "${RUNNER_TEMP}/paths.txt" >> comment.txt
|
||||
exit "${EXIT_CODE}"
|
||||
|
||||
- if: always()
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: comment
|
||||
path: comment.txt
|
||||
retention-days: 1
|
||||
224
.github/workflows/ruby-build.yml
vendored
224
.github/workflows/ruby-build.yml
vendored
@@ -1,224 +0,0 @@
|
||||
name: "Ruby: Build"
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "ruby/**"
|
||||
- .github/workflows/ruby-build.yml
|
||||
branches:
|
||||
- main
|
||||
- "rc/*"
|
||||
pull_request:
|
||||
paths:
|
||||
- "ruby/**"
|
||||
- .github/workflows/ruby-build.yml
|
||||
branches:
|
||||
- main
|
||||
- "rc/*"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: "Version tag to create"
|
||||
required: false
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ruby
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install GNU tar
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
brew install gnu-tar
|
||||
echo "/usr/local/opt/gnu-tar/libexec/gnubin" >> $GITHUB_PATH
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
ruby/target
|
||||
key: ${{ runner.os }}-rust-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
- name: Check formatting
|
||||
run: cargo fmt --all -- --check
|
||||
- name: Build
|
||||
run: cargo build --verbose
|
||||
- name: Run tests
|
||||
run: cargo test --verbose
|
||||
- name: Release build
|
||||
run: cargo build --release
|
||||
- name: Generate dbscheme
|
||||
if: ${{ matrix.os == 'ubuntu-latest' }}
|
||||
run: target/release/ruby-generator --dbscheme ql/lib/ruby.dbscheme --library ql/lib/codeql/ruby/ast/internal/TreeSitter.qll
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: ${{ matrix.os == 'ubuntu-latest' }}
|
||||
with:
|
||||
name: ruby.dbscheme
|
||||
path: ruby/ql/lib/ruby.dbscheme
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: ${{ matrix.os == 'ubuntu-latest' }}
|
||||
with:
|
||||
name: TreeSitter.qll
|
||||
path: ruby/ql/lib/codeql/ruby/ast/internal/TreeSitter.qll
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: extractor-${{ matrix.os }}
|
||||
path: |
|
||||
ruby/target/release/ruby-autobuilder
|
||||
ruby/target/release/ruby-autobuilder.exe
|
||||
ruby/target/release/ruby-extractor
|
||||
ruby/target/release/ruby-extractor.exe
|
||||
retention-days: 1
|
||||
compile-queries:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CODEQL_THREADS: 4 # TODO: remove this once it's set by the CLI
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Fetch CodeQL
|
||||
run: |
|
||||
LATEST=$(gh release list --repo https://github.com/github/codeql-cli-binaries | cut -f 1 | grep -v beta | sort --version-sort | tail -1)
|
||||
gh release download --repo https://github.com/github/codeql-cli-binaries --pattern codeql-linux64.zip "$LATEST"
|
||||
unzip -q codeql-linux64.zip
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
- name: Build Query Pack
|
||||
run: |
|
||||
codeql/codeql pack create ql/lib --output target/packs
|
||||
codeql/codeql pack install ql/src
|
||||
codeql/codeql pack create ql/src --output target/packs
|
||||
PACK_FOLDER=$(readlink -f target/packs/codeql/ruby-queries/*)
|
||||
codeql/codeql generate query-help --format=sarifv2.1.0 --output="${PACK_FOLDER}/rules.sarif" ql/src
|
||||
(cd ql/src; find queries \( -name '*.qhelp' -o -name '*.rb' -o -name '*.erb' \) -exec bash -c 'mkdir -p "'"${PACK_FOLDER}"'/$(dirname "{}")"' \; -exec cp "{}" "${PACK_FOLDER}/{}" \;)
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: codeql-ruby-queries
|
||||
path: |
|
||||
ruby/target/packs/*
|
||||
retention-days: 1
|
||||
|
||||
package:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build, compile-queries]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: ruby.dbscheme
|
||||
path: ruby/ruby
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: extractor-ubuntu-latest
|
||||
path: ruby/linux64
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: extractor-windows-latest
|
||||
path: ruby/win64
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: extractor-macos-latest
|
||||
path: ruby/osx64
|
||||
- run: |
|
||||
mkdir -p ruby
|
||||
cp -r codeql-extractor.yml tools ql/lib/ruby.dbscheme.stats ruby/
|
||||
mkdir -p ruby/tools/{linux64,osx64,win64}
|
||||
cp linux64/ruby-autobuilder ruby/tools/linux64/autobuilder
|
||||
cp osx64/ruby-autobuilder ruby/tools/osx64/autobuilder
|
||||
cp win64/ruby-autobuilder.exe ruby/tools/win64/autobuilder.exe
|
||||
cp linux64/ruby-extractor ruby/tools/linux64/extractor
|
||||
cp osx64/ruby-extractor ruby/tools/osx64/extractor
|
||||
cp win64/ruby-extractor.exe ruby/tools/win64/extractor.exe
|
||||
chmod +x ruby/tools/{linux64,osx64}/{autobuilder,extractor}
|
||||
zip -rq codeql-ruby.zip ruby
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: codeql-ruby-pack
|
||||
path: ruby/codeql-ruby.zip
|
||||
retention-days: 1
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: codeql-ruby-queries
|
||||
path: ruby/qlpacks
|
||||
- run: |
|
||||
echo '{
|
||||
"provide": [
|
||||
"ruby/codeql-extractor.yml",
|
||||
"qlpacks/*/*/*/qlpack.yml"
|
||||
]
|
||||
}' > .codeqlmanifest.json
|
||||
zip -rq codeql-ruby-bundle.zip .codeqlmanifest.json ruby qlpacks
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: codeql-ruby-bundle
|
||||
path: ruby/codeql-ruby-bundle.zip
|
||||
retention-days: 1
|
||||
|
||||
test:
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ github.workspace }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
needs: [package]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
repository: Shopify/example-ruby-app
|
||||
ref: 67a0decc5eb550f3a9228eda53925c3afd40dfe9
|
||||
- name: Fetch CodeQL
|
||||
shell: bash
|
||||
run: |
|
||||
LATEST=$(gh release list --repo https://github.com/github/codeql-cli-binaries | cut -f 1 | grep -v beta | sort --version-sort | tail -1)
|
||||
gh release download --repo https://github.com/github/codeql-cli-binaries --pattern codeql.zip "$LATEST"
|
||||
unzip -q codeql.zip
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
working-directory: ${{ runner.temp }}
|
||||
- name: Download Ruby bundle
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: codeql-ruby-bundle
|
||||
path: ${{ runner.temp }}
|
||||
- name: Unzip Ruby bundle
|
||||
shell: bash
|
||||
run: unzip -q -d "${{ runner.temp }}/ruby-bundle" "${{ runner.temp }}/codeql-ruby-bundle.zip"
|
||||
- name: Prepare test files
|
||||
shell: bash
|
||||
run: |
|
||||
echo "import ruby select count(File f)" > "test.ql"
|
||||
echo "| 4 |" > "test.expected"
|
||||
echo 'name: sample-tests
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
codeql/ruby-all: 0.0.1
|
||||
extractor: ruby
|
||||
tests: .
|
||||
' > qlpack.yml
|
||||
- name: Run QL test
|
||||
shell: bash
|
||||
run: |
|
||||
"${{ runner.temp }}/codeql/codeql" test run --search-path "${{ runner.temp }}/ruby-bundle" --additional-packs "${{ runner.temp }}/ruby-bundle" .
|
||||
- name: Create database
|
||||
shell: bash
|
||||
run: |
|
||||
"${{ runner.temp }}/codeql/codeql" database create --search-path "${{ runner.temp }}/ruby-bundle" --language ruby --source-root . ../database
|
||||
- name: Analyze database
|
||||
shell: bash
|
||||
run: |
|
||||
"${{ runner.temp }}/codeql/codeql" database analyze --search-path "${{ runner.temp }}/ruby-bundle" --format=sarifv2.1.0 --output=out.sarif ../database ruby-code-scanning.qls
|
||||
73
.github/workflows/ruby-dataset-measure.yml
vendored
73
.github/workflows/ruby-dataset-measure.yml
vendored
@@ -1,73 +0,0 @@
|
||||
name: "Ruby: Collect database stats"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- "rc/*"
|
||||
paths:
|
||||
- ruby/ql/lib/ruby.dbscheme
|
||||
- .github/workflows/ruby-dataset-measure.yml
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- "rc/*"
|
||||
paths:
|
||||
- ruby/ql/lib/ruby.dbscheme
|
||||
- .github/workflows/ruby-dataset-measure.yml
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
measure:
|
||||
env:
|
||||
CODEQL_THREADS: 4 # TODO: remove this once it's set by the CLI
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
repo: [rails/rails, discourse/discourse, spree/spree, ruby/ruby]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: ./.github/actions/fetch-codeql
|
||||
|
||||
- uses: ./ruby/actions/create-extractor-pack
|
||||
|
||||
- name: Checkout ${{ matrix.repo }}
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: ${{ matrix.repo }}
|
||||
path: ${{ github.workspace }}/repo
|
||||
- name: Create database
|
||||
run: |
|
||||
codeql database create \
|
||||
--search-path "${{ github.workspace }}/ruby/extractor-pack" \
|
||||
--threads 4 \
|
||||
--language ruby --source-root "${{ github.workspace }}/repo" \
|
||||
"${{ runner.temp }}/database"
|
||||
- name: Measure database
|
||||
run: |
|
||||
mkdir -p "stats/${{ matrix.repo }}"
|
||||
codeql dataset measure --threads 4 --output "stats/${{ matrix.repo }}/stats.xml" "${{ runner.temp }}/database/db-ruby"
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: measurements
|
||||
path: stats
|
||||
retention-days: 1
|
||||
|
||||
merge:
|
||||
runs-on: ubuntu-latest
|
||||
needs: measure
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: measurements
|
||||
path: stats
|
||||
- run: |
|
||||
python -m pip install --user lxml
|
||||
find stats -name 'stats.xml' | sort | xargs python ruby/scripts/merge_stats.py --output ruby/ql/lib/ruby.dbscheme.stats --normalise ruby_tokeninfo
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ruby.dbscheme.stats
|
||||
path: ruby/ql/lib/ruby.dbscheme.stats
|
||||
50
.github/workflows/ruby-qltest.yml
vendored
50
.github/workflows/ruby-qltest.yml
vendored
@@ -1,50 +0,0 @@
|
||||
name: "Ruby: Run QL Tests"
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "ruby/**"
|
||||
- .github/workflows/ruby-qltest.yml
|
||||
branches:
|
||||
- main
|
||||
- "rc/*"
|
||||
pull_request:
|
||||
paths:
|
||||
- "ruby/**"
|
||||
- .github/workflows/ruby-qltest.yml
|
||||
branches:
|
||||
- main
|
||||
- "rc/*"
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ruby
|
||||
|
||||
jobs:
|
||||
qltest:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/fetch-codeql
|
||||
- uses: ./ruby/actions/create-extractor-pack
|
||||
- name: Run QL tests
|
||||
run: |
|
||||
codeql test run --search-path "${{ github.workspace }}/ruby/extractor-pack" --check-databases --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --consistency-queries ql/consistency-queries ql/test
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
- name: Check QL formatting
|
||||
run: find ql "(" -name "*.ql" -or -name "*.qll" ")" -print0 | xargs -0 codeql query format --check-only
|
||||
- name: Check QL compilation
|
||||
run: |
|
||||
codeql query compile --check-only --threads=4 --warnings=error "ql/src" "ql/examples"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
- name: Check DB upgrade scripts
|
||||
run: |
|
||||
echo >empty.trap
|
||||
codeql dataset import -S ql/lib/upgrades/initial/ruby.dbscheme testdb empty.trap
|
||||
codeql dataset upgrade testdb --additional-packs ql/lib
|
||||
diff -q testdb/ruby.dbscheme ql/lib/ruby.dbscheme
|
||||
20
.github/workflows/sync-files.yml
vendored
20
.github/workflows/sync-files.yml
vendored
@@ -1,20 +0,0 @@
|
||||
name: Check synchronized files
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- 'rc/*'
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- 'rc/*'
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Check synchronized files
|
||||
run: python config/sync-files.py
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -24,9 +24,3 @@
|
||||
/codeql/
|
||||
|
||||
csharp/extractor/Semmle.Extraction.CSharp.Driver/Properties/launchSettings.json
|
||||
|
||||
# Avoid committing cached package components
|
||||
.codeql
|
||||
|
||||
# Compiled class file
|
||||
*.class
|
||||
@@ -3,7 +3,6 @@
|
||||
/java/ @github/codeql-java
|
||||
/javascript/ @github/codeql-javascript
|
||||
/python/ @github/codeql-python
|
||||
/ruby/ @github/codeql-ruby
|
||||
|
||||
# Make @xcorail (GitHub Security Lab) a code owner for experimental queries so he gets pinged when we promote a query out of experimental
|
||||
/cpp/**/experimental/**/* @github/codeql-c-analysis @xcorail
|
||||
@@ -11,7 +10,6 @@
|
||||
/java/**/experimental/**/* @github/codeql-java @xcorail
|
||||
/javascript/**/experimental/**/* @github/codeql-javascript @xcorail
|
||||
/python/**/experimental/**/* @github/codeql-python @xcorail
|
||||
/ruby/**/experimental/**/* @github/codeql-ruby @xcorail
|
||||
|
||||
# Notify members of codeql-go about PRs to the shared data-flow library files
|
||||
/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll @github/codeql-java @github/codeql-go
|
||||
@@ -24,4 +22,4 @@
|
||||
/docs/codeql-cli/ @github/codeql-cli-reviewers
|
||||
/docs/codeql-for-visual-studio-code/ @github/codeql-vscode-reviewers
|
||||
/docs/ql-language-reference/ @github/codeql-frontend-reviewers
|
||||
/docs/query-*-style-guide.md @github/codeql-analysis-reviewers
|
||||
/docs/query-*-style-guide.md @github/codeql-analysis-reviewers
|
||||
@@ -11,14 +11,13 @@ If you have an idea for a query that you would like to share with other CodeQL u
|
||||
|
||||
1. **Directory structure**
|
||||
|
||||
There are six language-specific query directories in this repository:
|
||||
There are five language-specific query directories in this repository:
|
||||
|
||||
* C/C++: `cpp/ql/src`
|
||||
* C#: `csharp/ql/src`
|
||||
* Java: `java/ql/src`
|
||||
* JavaScript: `javascript/ql/src`
|
||||
* Python: `python/ql/src`
|
||||
* Ruby: `ruby/ql/src`
|
||||
|
||||
Each language-specific directory contains further subdirectories that group queries based on their `@tags` or purpose.
|
||||
- Experimental queries and libraries are stored in the `experimental` subdirectory within each language-specific directory in the [CodeQL repository](https://github.com/github/codeql). For example, experimental Java queries and libraries are stored in `java/ql/src/experimental` and any corresponding tests in `java/ql/test/experimental`.
|
||||
|
||||
@@ -24,17 +24,14 @@
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll"
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll"
|
||||
],
|
||||
"DataFlow Java/C++/C#/Python Common": [
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll"
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll"
|
||||
],
|
||||
"TaintTracking::Configuration Java/C++/C#/Python": [
|
||||
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
|
||||
@@ -52,21 +49,18 @@
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking1/TaintTrackingImpl.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking2/TaintTrackingImpl.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingImpl.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingImpl.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/tainttracking1/TaintTrackingImpl.qll"
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingImpl.qll"
|
||||
],
|
||||
"DataFlow Java/C++/C#/Python Consistency checks": [
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplConsistency.qll"
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll"
|
||||
],
|
||||
"DataFlow Java/C# Flow Summaries": [
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll"
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll"
|
||||
],
|
||||
"SsaReadPosition Java/C#": [
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll",
|
||||
@@ -373,10 +367,8 @@
|
||||
],
|
||||
"Inline Test Expectations": [
|
||||
"cpp/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
||||
"csharp/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
||||
"java/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
||||
"python/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
||||
"ruby/ql/test/TestUtilities/InlineExpectationsTest.qll"
|
||||
"python/ql/test/TestUtilities/InlineExpectationsTest.qll"
|
||||
],
|
||||
"C++ ExternalAPIs": [
|
||||
"cpp/ql/src/Security/CWE/CWE-020/ExternalAPIs.qll",
|
||||
@@ -448,9 +440,7 @@
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/SsaImplCommon.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/controlflow/internal/pressa/SsaImplCommon.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/basessa/SsaImplCommon.qll",
|
||||
"csharp/ql/lib/semmle/code/cil/internal/SsaImplCommon.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/SsaImplCommon.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaImplCommon.qll"
|
||||
"csharp/ql/lib/semmle/code/cil/internal/SsaImplCommon.qll"
|
||||
],
|
||||
"CryptoAlgorithms Python/JS": [
|
||||
"javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll",
|
||||
@@ -460,10 +450,9 @@
|
||||
"javascript/ql/lib/semmle/javascript/security/internal/SensitiveDataHeuristics.qll",
|
||||
"python/ql/lib/semmle/python/security/internal/SensitiveDataHeuristics.qll"
|
||||
],
|
||||
"ReDoS Util Python/JS/Ruby": [
|
||||
"ReDoS Util Python/JS": [
|
||||
"javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll",
|
||||
"python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll",
|
||||
"ruby/ql/lib/codeql/ruby/security/performance/ReDoSUtil.qll"
|
||||
"python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll"
|
||||
],
|
||||
"ReDoS Exponential Python/JS": [
|
||||
"javascript/ql/lib/semmle/javascript/security/performance/ExponentialBackTracking.qll",
|
||||
@@ -471,28 +460,6 @@
|
||||
],
|
||||
"ReDoS Polynomial Python/JS": [
|
||||
"javascript/ql/lib/semmle/javascript/security/performance/SuperlinearBackTracking.qll",
|
||||
"python/ql/lib/semmle/python/security/performance/SuperlinearBackTracking.qll",
|
||||
"ruby/ql/lib/codeql/ruby/security/performance/SuperlinearBackTracking.qll"
|
||||
],
|
||||
"BadTagFilterQuery Python/JS/Ruby": [
|
||||
"javascript/ql/lib/semmle/javascript/security/BadTagFilterQuery.qll",
|
||||
"python/ql/lib/semmle/python/security/BadTagFilterQuery.qll",
|
||||
"ruby/ql/lib/codeql/ruby/security/BadTagFilterQuery.qll"
|
||||
],
|
||||
"CFG": [
|
||||
"csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImplShared.qll",
|
||||
"ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImplShared.qll"
|
||||
],
|
||||
"TypeTracker": [
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll",
|
||||
"ruby/ql/lib/codeql/ruby/typetracking/TypeTracker.qll"
|
||||
],
|
||||
"CodeQL Tutorial": [
|
||||
"cpp/ql/lib/tutorial.qll",
|
||||
"csharp/ql/lib/tutorial.qll",
|
||||
"java/ql/lib/tutorial.qll",
|
||||
"javascript/ql/lib/tutorial.qll",
|
||||
"python/ql/lib/tutorial.qll",
|
||||
"ruby/ql/lib/tutorial.qll"
|
||||
"python/ql/lib/semmle/python/security/performance/SuperlinearBackTracking.qll"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
lgtm,codescanning
|
||||
* A new query (`cpp/cleartext-transmission`) has been added. This is similar to the `cpp/cleartext-storage-file`, `cpp/cleartext-storage-buffer` and `cpp/cleartext-storage-database` queries but looks for cases where sensitive information is most likely transmitted over a network.
|
||||
@@ -1,2 +0,0 @@
|
||||
lgtm,codescanning
|
||||
* The "Uncontrolled data used in OS command" (`cpp/command-line-injection`) query has been enhanced to reduce false positive results and its `@precision` increased to `high`
|
||||
@@ -1,2 +0,0 @@
|
||||
lgtm,codescanning
|
||||
* Several improvements made to the `NullTermination.qll` library and the 'Potential improper null termination' (cpp/improper-null-termination). These changes reduce the number of false positive results for this query and related query 'User-controlled data may not be null terminated' (cpp/user-controlled-null-termination-tainted).
|
||||
@@ -1,3 +0,0 @@
|
||||
codescanning
|
||||
* Problems with extraction that in most cases won't break the analysis in a significant way are now reported as warnings rather than errors.
|
||||
* The failed extractor invocations query now has severity `error`.
|
||||
@@ -1,4 +0,0 @@
|
||||
lgtm,codescanning
|
||||
* The QL library `semmle.code.cpp.commons.Exclusions` now contains a predicate
|
||||
`isFromSystemMacroDefinition` for identifying code that originates from a
|
||||
macro outside the project being analyzed.
|
||||
@@ -1,2 +0,0 @@
|
||||
lgtm,codescanning
|
||||
* A new query `cpp/non-https-url` has been added for C/C++. The query flags uses of `http` URLs that might be better replaced with `https`.
|
||||
@@ -1,2 +0,0 @@
|
||||
lgtm,codescanning
|
||||
* A new query `cpp/certificate-not-checked` has been added for C/C++. The query flags unsafe use of OpenSSL and similar libraries.
|
||||
@@ -1,2 +0,0 @@
|
||||
lgtm,codescanning
|
||||
* A new query `cpp/certificate-result-conflation` has been added for C/C++. The query flags unsafe use of OpenSSL and similar libraries.
|
||||
@@ -1,7 +0,0 @@
|
||||
## 0.0.4
|
||||
|
||||
### New Features
|
||||
|
||||
* The QL library `semmle.code.cpp.commons.Exclusions` now contains a predicate
|
||||
`isFromSystemMacroDefinition` for identifying code that originates from a
|
||||
macro outside the project being analyzed.
|
||||
@@ -1,7 +0,0 @@
|
||||
## 0.0.4
|
||||
|
||||
### New Features
|
||||
|
||||
* The QL library `semmle.code.cpp.commons.Exclusions` now contains a predicate
|
||||
`isFromSystemMacroDefinition` for identifying code that originates from a
|
||||
macro outside the project being analyzed.
|
||||
@@ -1,2 +0,0 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.4
|
||||
@@ -52,8 +52,11 @@ module PrivateCleartextWrite {
|
||||
|
||||
class WriteSink extends Sink {
|
||||
WriteSink() {
|
||||
this.asExpr() = any(FileWrite f).getASource() or
|
||||
this.asExpr() = any(BufferWrite b).getAChild()
|
||||
exists(FileWrite f, BufferWrite b |
|
||||
this.asExpr() = f.getASource()
|
||||
or
|
||||
this.asExpr() = b.getAChild()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,25 +13,26 @@ import cpp
|
||||
|
||||
/** A string for `match` that identifies strings that look like they represent private data. */
|
||||
private string privateNames() {
|
||||
result =
|
||||
[
|
||||
// Inspired by the list on https://cwe.mitre.org/data/definitions/359.html
|
||||
// Government identifiers, such as Social Security Numbers
|
||||
"%social%security%number%",
|
||||
// Contact information, such as home addresses and telephone numbers
|
||||
"%postcode%", "%zipcode%",
|
||||
// result = "%telephone%" or
|
||||
// Geographic location - where the user is (or was)
|
||||
"%latitude%", "%longitude%",
|
||||
// Financial data - such as credit card numbers, salary, bank accounts, and debts
|
||||
"%creditcard%", "%salary%", "%bankaccount%",
|
||||
// Communications - e-mail addresses, private e-mail messages, SMS text messages, chat logs, etc.
|
||||
// result = "%email%" or
|
||||
// result = "%mobile%" or
|
||||
"%employer%",
|
||||
// Health - medical conditions, insurance status, prescription records
|
||||
"%medical%"
|
||||
]
|
||||
// Inspired by the list on https://cwe.mitre.org/data/definitions/359.html
|
||||
// Government identifiers, such as Social Security Numbers
|
||||
result = "%social%security%number%" or
|
||||
// Contact information, such as home addresses and telephone numbers
|
||||
result = "%postcode%" or
|
||||
result = "%zipcode%" or
|
||||
// result = "%telephone%" or
|
||||
// Geographic location - where the user is (or was)
|
||||
result = "%latitude%" or
|
||||
result = "%longitude%" or
|
||||
// Financial data - such as credit card numbers, salary, bank accounts, and debts
|
||||
result = "%creditcard%" or
|
||||
result = "%salary%" or
|
||||
result = "%bankaccount%" or
|
||||
// Communications - e-mail addresses, private e-mail messages, SMS text messages, chat logs, etc.
|
||||
// result = "%email%" or
|
||||
// result = "%mobile%" or
|
||||
result = "%employer%" or
|
||||
// Health - medical conditions, insurance status, prescription records
|
||||
result = "%medical%"
|
||||
}
|
||||
|
||||
/** An expression that might contain private data. */
|
||||
|
||||
18
cpp/ql/lib/external/ExternalArtifact.qll
vendored
18
cpp/ql/lib/external/ExternalArtifact.qll
vendored
@@ -15,7 +15,7 @@ class ExternalData extends @externalDataElement {
|
||||
* Gets the path of the file this data was loaded from, with its
|
||||
* extension replaced by `.ql`.
|
||||
*/
|
||||
string getQueryPath() { result = this.getDataPath().regexpReplaceAll("\\.[^.]*$", ".ql") }
|
||||
string getQueryPath() { result = getDataPath().regexpReplaceAll("\\.[^.]*$", ".ql") }
|
||||
|
||||
/** Gets the number of fields in this data item. */
|
||||
int getNumFields() { result = 1 + max(int i | externalData(this, _, i, _) | i) }
|
||||
@@ -24,22 +24,22 @@ class ExternalData extends @externalDataElement {
|
||||
string getField(int i) { externalData(this, _, i, result) }
|
||||
|
||||
/** Gets the integer value of the `i`th field of this data item. */
|
||||
int getFieldAsInt(int i) { result = this.getField(i).toInt() }
|
||||
int getFieldAsInt(int i) { result = getField(i).toInt() }
|
||||
|
||||
/** Gets the floating-point value of the `i`th field of this data item. */
|
||||
float getFieldAsFloat(int i) { result = this.getField(i).toFloat() }
|
||||
float getFieldAsFloat(int i) { result = getField(i).toFloat() }
|
||||
|
||||
/** Gets the value of the `i`th field of this data item, interpreted as a date. */
|
||||
date getFieldAsDate(int i) { result = this.getField(i).toDate() }
|
||||
date getFieldAsDate(int i) { result = getField(i).toDate() }
|
||||
|
||||
/** Gets a textual representation of this data item. */
|
||||
string toString() { result = this.getQueryPath() + ": " + this.buildTupleString(0) }
|
||||
string toString() { result = getQueryPath() + ": " + buildTupleString(0) }
|
||||
|
||||
/** Gets a textual representation of this data item, starting with the `n`th field. */
|
||||
private string buildTupleString(int n) {
|
||||
n = this.getNumFields() - 1 and result = this.getField(n)
|
||||
n = getNumFields() - 1 and result = getField(n)
|
||||
or
|
||||
n < this.getNumFields() - 1 and result = this.getField(n) + "," + this.buildTupleString(n + 1)
|
||||
n < getNumFields() - 1 and result = getField(n) + "," + buildTupleString(n + 1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,8 +53,8 @@ class DefectExternalData extends ExternalData {
|
||||
}
|
||||
|
||||
/** Gets the URL associated with this data item. */
|
||||
string getURL() { result = this.getField(0) }
|
||||
string getURL() { result = getField(0) }
|
||||
|
||||
/** Gets the message associated with this data item. */
|
||||
string getMessage() { result = this.getField(1) }
|
||||
string getMessage() { result = getField(1) }
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.0.5-dev
|
||||
groups: cpp
|
||||
version: 0.0.2
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
library: true
|
||||
dependencies:
|
||||
codeql/cpp-upgrades: 0.0.3
|
||||
codeql/cpp-upgrades: 0.0.2
|
||||
|
||||
@@ -237,7 +237,7 @@ class Class extends UserType {
|
||||
exists(ClassDerivation cd | cd.getBaseClass() = base |
|
||||
result =
|
||||
this.accessOfBaseMemberMulti(cd.getDerivedClass(),
|
||||
fieldInBase.accessInDirectDerived(cd.getASpecifier()))
|
||||
fieldInBase.accessInDirectDerived(cd.getASpecifier().(AccessSpecifier)))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -261,20 +261,21 @@ class Class extends UserType {
|
||||
* includes the case of `base` = `this`.
|
||||
*/
|
||||
AccessSpecifier accessOfBaseMember(Declaration member) {
|
||||
result = this.accessOfBaseMember(member.getDeclaringType(), member.getASpecifier())
|
||||
result =
|
||||
this.accessOfBaseMember(member.getDeclaringType(), member.getASpecifier().(AccessSpecifier))
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: name changed to `hasImplicitCopyConstructor` to reflect that
|
||||
* `= default` members are no longer included.
|
||||
*/
|
||||
deprecated predicate hasGeneratedCopyConstructor() { this.hasImplicitCopyConstructor() }
|
||||
deprecated predicate hasGeneratedCopyConstructor() { hasImplicitCopyConstructor() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: name changed to `hasImplicitCopyAssignmentOperator` to
|
||||
* reflect that `= default` members are no longer included.
|
||||
*/
|
||||
deprecated predicate hasGeneratedCopyAssignmentOperator() { this.hasImplicitCopyConstructor() }
|
||||
deprecated predicate hasGeneratedCopyAssignmentOperator() { hasImplicitCopyConstructor() }
|
||||
|
||||
/**
|
||||
* Holds if this class, struct or union has an implicitly-declared copy
|
||||
@@ -318,7 +319,7 @@ class Class extends UserType {
|
||||
exists(Type t | t = this.getAFieldSubobjectType().getUnspecifiedType() |
|
||||
// Note: Overload resolution is not implemented -- all copy
|
||||
// constructors are considered equal.
|
||||
this.cannotAccessCopyConstructorOnAny(t)
|
||||
this.cannotAccessCopyConstructorOnAny(t.(Class))
|
||||
)
|
||||
or
|
||||
// - T has direct or virtual base class that cannot be copied (has deleted,
|
||||
@@ -391,7 +392,7 @@ class Class extends UserType {
|
||||
exists(Type t | t = this.getAFieldSubobjectType().getUnspecifiedType() |
|
||||
// Note: Overload resolution is not implemented -- all copy assignment
|
||||
// operators are considered equal.
|
||||
this.cannotAccessCopyAssignmentOperatorOnAny(t)
|
||||
this.cannotAccessCopyAssignmentOperatorOnAny(t.(Class))
|
||||
)
|
||||
or
|
||||
exists(Class c | c = this.getADirectOrVirtualBase() |
|
||||
@@ -486,7 +487,7 @@ class Class extends UserType {
|
||||
exists(ClassDerivation cd |
|
||||
// Add the offset of the direct base class and the offset of `baseClass`
|
||||
// within that direct base class.
|
||||
cd = this.getADerivation() and
|
||||
cd = getADerivation() and
|
||||
result = cd.getBaseClass().getANonVirtualBaseClassByteOffset(baseClass) + cd.getByteOffset()
|
||||
)
|
||||
}
|
||||
@@ -501,12 +502,12 @@ class Class extends UserType {
|
||||
*/
|
||||
int getABaseClassByteOffset(Class baseClass) {
|
||||
// Handle the non-virtual case.
|
||||
result = this.getANonVirtualBaseClassByteOffset(baseClass)
|
||||
result = getANonVirtualBaseClassByteOffset(baseClass)
|
||||
or
|
||||
exists(Class virtualBaseClass, int virtualBaseOffset, int offsetFromVirtualBase |
|
||||
// Look for the base class as a non-virtual base of a direct or indirect
|
||||
// virtual base, adding the two offsets.
|
||||
this.getVirtualBaseClassByteOffset(virtualBaseClass) = virtualBaseOffset and
|
||||
getVirtualBaseClassByteOffset(virtualBaseClass) = virtualBaseOffset and
|
||||
offsetFromVirtualBase = virtualBaseClass.getANonVirtualBaseClassByteOffset(baseClass) and
|
||||
result = virtualBaseOffset + offsetFromVirtualBase
|
||||
)
|
||||
@@ -622,11 +623,11 @@ class Class extends UserType {
|
||||
* inherits one).
|
||||
*/
|
||||
predicate isPolymorphic() {
|
||||
exists(MemberFunction f | f.getDeclaringType() = this.getABaseClass*() and f.isVirtual())
|
||||
exists(MemberFunction f | f.getDeclaringType() = getABaseClass*() and f.isVirtual())
|
||||
}
|
||||
|
||||
override predicate involvesTemplateParameter() {
|
||||
this.getATemplateArgument().(Type).involvesTemplateParameter()
|
||||
getATemplateArgument().(Type).involvesTemplateParameter()
|
||||
}
|
||||
|
||||
/** Holds if this class, struct or union was declared 'final'. */
|
||||
@@ -764,7 +765,7 @@ class ClassDerivation extends Locatable, @derivation {
|
||||
* };
|
||||
* ```
|
||||
*/
|
||||
Class getBaseClass() { result = this.getBaseType().getUnderlyingType() }
|
||||
Class getBaseClass() { result = getBaseType().getUnderlyingType() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ClassDerivation" }
|
||||
|
||||
@@ -817,7 +818,7 @@ class ClassDerivation extends Locatable, @derivation {
|
||||
predicate hasSpecifier(string s) { this.getASpecifier().hasName(s) }
|
||||
|
||||
/** Holds if the derivation is for a virtual base class. */
|
||||
predicate isVirtual() { this.hasSpecifier("virtual") }
|
||||
predicate isVirtual() { hasSpecifier("virtual") }
|
||||
|
||||
/** Gets the location of the derivation. */
|
||||
override Location getLocation() { derivations(underlyingElement(this), _, _, _, result) }
|
||||
@@ -845,7 +846,7 @@ class ClassDerivation extends Locatable, @derivation {
|
||||
* ```
|
||||
*/
|
||||
class LocalClass extends Class {
|
||||
LocalClass() { this.isLocal() }
|
||||
LocalClass() { isLocal() }
|
||||
|
||||
override string getAPrimaryQlClass() { not this instanceof LocalStruct and result = "LocalClass" }
|
||||
|
||||
@@ -988,9 +989,9 @@ class ClassTemplateSpecialization extends Class {
|
||||
TemplateClass getPrimaryTemplate() {
|
||||
// Ignoring template arguments, the primary template has the same name
|
||||
// as each of its specializations.
|
||||
result.getSimpleName() = this.getSimpleName() and
|
||||
result.getSimpleName() = getSimpleName() and
|
||||
// It is in the same namespace as its specializations.
|
||||
result.getNamespace() = this.getNamespace() and
|
||||
result.getNamespace() = getNamespace() and
|
||||
// It is distinguished by the fact that each of its template arguments
|
||||
// is a distinct template parameter.
|
||||
count(TemplateParameter tp | tp = result.getATemplateArgument()) =
|
||||
@@ -1107,7 +1108,7 @@ deprecated class Interface extends Class {
|
||||
* ```
|
||||
*/
|
||||
class VirtualClassDerivation extends ClassDerivation {
|
||||
VirtualClassDerivation() { this.hasSpecifier("virtual") }
|
||||
VirtualClassDerivation() { hasSpecifier("virtual") }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "VirtualClassDerivation" }
|
||||
}
|
||||
@@ -1135,7 +1136,7 @@ class VirtualBaseClass extends Class {
|
||||
VirtualClassDerivation getAVirtualDerivation() { result.getBaseClass() = this }
|
||||
|
||||
/** A class/struct that is derived from this one using virtual inheritance. */
|
||||
Class getAVirtuallyDerivedClass() { result = this.getAVirtualDerivation().getDerivedClass() }
|
||||
Class getAVirtuallyDerivedClass() { result = getAVirtualDerivation().getDerivedClass() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1154,7 +1155,7 @@ class ProxyClass extends UserType {
|
||||
override string getAPrimaryQlClass() { result = "ProxyClass" }
|
||||
|
||||
/** Gets the location of the proxy class. */
|
||||
override Location getLocation() { result = this.getTemplateParameter().getDefinitionLocation() }
|
||||
override Location getLocation() { result = getTemplateParameter().getDefinitionLocation() }
|
||||
|
||||
/** Gets the template parameter for which this is the proxy class. */
|
||||
TemplateParameter getTemplateParameter() {
|
||||
|
||||
@@ -184,7 +184,7 @@ class Declaration extends Locatable, @declaration {
|
||||
predicate hasDefinition() { exists(this.getDefinition()) }
|
||||
|
||||
/** DEPRECATED: Use `hasDefinition` instead. */
|
||||
predicate isDefined() { this.hasDefinition() }
|
||||
predicate isDefined() { hasDefinition() }
|
||||
|
||||
/** Gets the preferred location of this declaration, if any. */
|
||||
override Location getLocation() { none() }
|
||||
@@ -209,7 +209,7 @@ class Declaration extends Locatable, @declaration {
|
||||
predicate isStatic() { this.hasSpecifier("static") }
|
||||
|
||||
/** Holds if this declaration is a member of a class/struct/union. */
|
||||
predicate isMember() { this.hasDeclaringType() }
|
||||
predicate isMember() { hasDeclaringType() }
|
||||
|
||||
/** Holds if this declaration is a member of a class/struct/union. */
|
||||
predicate hasDeclaringType() { exists(this.getDeclaringType()) }
|
||||
@@ -226,14 +226,14 @@ class Declaration extends Locatable, @declaration {
|
||||
* When called on a template, this will return a template parameter type for
|
||||
* both typed and non-typed parameters.
|
||||
*/
|
||||
final Locatable getATemplateArgument() { result = this.getTemplateArgument(_) }
|
||||
final Locatable getATemplateArgument() { result = getTemplateArgument(_) }
|
||||
|
||||
/**
|
||||
* Gets a template argument used to instantiate this declaration from a template.
|
||||
* When called on a template, this will return a non-typed template
|
||||
* parameter value.
|
||||
*/
|
||||
final Locatable getATemplateArgumentKind() { result = this.getTemplateArgumentKind(_) }
|
||||
final Locatable getATemplateArgumentKind() { result = getTemplateArgumentKind(_) }
|
||||
|
||||
/**
|
||||
* Gets the `i`th template argument used to instantiate this declaration from a
|
||||
@@ -252,9 +252,9 @@ class Declaration extends Locatable, @declaration {
|
||||
* `getTemplateArgument(1)` return `1`.
|
||||
*/
|
||||
final Locatable getTemplateArgument(int index) {
|
||||
if exists(this.getTemplateArgumentValue(index))
|
||||
then result = this.getTemplateArgumentValue(index)
|
||||
else result = this.getTemplateArgumentType(index)
|
||||
if exists(getTemplateArgumentValue(index))
|
||||
then result = getTemplateArgumentValue(index)
|
||||
else result = getTemplateArgumentType(index)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -275,13 +275,14 @@ class Declaration extends Locatable, @declaration {
|
||||
* `getTemplateArgumentKind(0)`.
|
||||
*/
|
||||
final Locatable getTemplateArgumentKind(int index) {
|
||||
exists(this.getTemplateArgumentValue(index)) and
|
||||
result = this.getTemplateArgumentType(index)
|
||||
if exists(getTemplateArgumentValue(index))
|
||||
then result = getTemplateArgumentType(index)
|
||||
else none()
|
||||
}
|
||||
|
||||
/** Gets the number of template arguments for this declaration. */
|
||||
final int getNumberOfTemplateArguments() {
|
||||
result = count(int i | exists(this.getTemplateArgument(i)))
|
||||
result = count(int i | exists(getTemplateArgument(i)))
|
||||
}
|
||||
|
||||
private Type getTemplateArgumentType(int index) {
|
||||
@@ -327,9 +328,9 @@ class DeclarationEntry extends Locatable, TDeclarationEntry {
|
||||
* available), or the name declared by this entry otherwise.
|
||||
*/
|
||||
string getCanonicalName() {
|
||||
if this.getDeclaration().hasDefinition()
|
||||
then result = this.getDeclaration().getDefinition().getName()
|
||||
else result = this.getName()
|
||||
if getDeclaration().hasDefinition()
|
||||
then result = getDeclaration().getDefinition().getName()
|
||||
else result = getName()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -370,18 +371,18 @@ class DeclarationEntry extends Locatable, TDeclarationEntry {
|
||||
/**
|
||||
* Holds if this declaration entry has a specifier with the given name.
|
||||
*/
|
||||
predicate hasSpecifier(string specifier) { this.getASpecifier() = specifier }
|
||||
predicate hasSpecifier(string specifier) { getASpecifier() = specifier }
|
||||
|
||||
/** Holds if this declaration entry is a definition. */
|
||||
predicate isDefinition() { none() } // overridden in subclasses
|
||||
|
||||
override string toString() {
|
||||
if this.isDefinition()
|
||||
then result = "definition of " + this.getName()
|
||||
if isDefinition()
|
||||
then result = "definition of " + getName()
|
||||
else
|
||||
if this.getName() = this.getCanonicalName()
|
||||
then result = "declaration of " + this.getName()
|
||||
else result = "declaration of " + this.getCanonicalName() + " as " + this.getName()
|
||||
if getName() = getCanonicalName()
|
||||
then result = "declaration of " + getName()
|
||||
else result = "declaration of " + getCanonicalName() + " as " + getName()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -490,7 +491,8 @@ class AccessHolder extends Declaration, TAccessHolder {
|
||||
*/
|
||||
pragma[inline]
|
||||
predicate canAccessMember(Declaration member, Class derived) {
|
||||
this.couldAccessMember(member.getDeclaringType(), member.getASpecifier(), derived)
|
||||
this.couldAccessMember(member.getDeclaringType(), member.getASpecifier().(AccessSpecifier),
|
||||
derived)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -579,7 +581,7 @@ private class DirectAccessHolder extends Element {
|
||||
// transitive closure with a restricted base case.
|
||||
this.thisCanAccessClassStep(base, derived)
|
||||
or
|
||||
exists(Class between | this.thisCanAccessClassTrans(base, between) |
|
||||
exists(Class between | thisCanAccessClassTrans(base, between) |
|
||||
isDirectPublicBaseOf(between, derived) or
|
||||
this.thisCanAccessClassStep(between, derived)
|
||||
)
|
||||
|
||||
@@ -61,7 +61,7 @@ class ElementBase extends @element {
|
||||
/**
|
||||
* Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs.
|
||||
*/
|
||||
final string getPrimaryQlClasses() { result = concat(this.getAPrimaryQlClass(), ",") }
|
||||
final string getPrimaryQlClasses() { result = concat(getAPrimaryQlClass(), ",") }
|
||||
|
||||
/**
|
||||
* Gets the name of a primary CodeQL class to which this element belongs.
|
||||
@@ -206,9 +206,9 @@ class Element extends ElementBase {
|
||||
/** Gets the closest `Element` enclosing this one. */
|
||||
cached
|
||||
Element getEnclosingElement() {
|
||||
result = this.getEnclosingElementPref()
|
||||
result = getEnclosingElementPref()
|
||||
or
|
||||
not exists(this.getEnclosingElementPref()) and
|
||||
not exists(getEnclosingElementPref()) and
|
||||
(
|
||||
this = result.(Class).getAMember()
|
||||
or
|
||||
@@ -281,7 +281,7 @@ private predicate isFromUninstantiatedTemplateRec(Element e, Element template) {
|
||||
* ```
|
||||
*/
|
||||
class StaticAssert extends Locatable, @static_assert {
|
||||
override string toString() { result = "static_assert(..., \"" + this.getMessage() + "\")" }
|
||||
override string toString() { result = "static_assert(..., \"" + getMessage() + "\")" }
|
||||
|
||||
/**
|
||||
* Gets the expression which this static assertion ensures is true.
|
||||
|
||||
@@ -85,7 +85,7 @@ class Enum extends UserType, IntegralOrEnumType {
|
||||
* ```
|
||||
*/
|
||||
class LocalEnum extends Enum {
|
||||
LocalEnum() { this.isLocal() }
|
||||
LocalEnum() { isLocal() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LocalEnum" }
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ class Container extends Locatable, @container {
|
||||
* DEPRECATED: Use `getLocation` instead.
|
||||
* Gets a URL representing the location of this container.
|
||||
*
|
||||
* For more information see [Providing URLs](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/#providing-urls).
|
||||
* For more information see [Providing URLs](https://help.semmle.com/QL/learn-ql/ql/locations.html#providing-urls).
|
||||
*/
|
||||
deprecated string getURL() { none() } // overridden by subclasses
|
||||
|
||||
@@ -52,7 +52,7 @@ class Container extends Locatable, @container {
|
||||
*/
|
||||
string getRelativePath() {
|
||||
exists(string absPath, string pref |
|
||||
absPath = this.getAbsolutePath() and sourceLocationPrefix(pref)
|
||||
absPath = getAbsolutePath() and sourceLocationPrefix(pref)
|
||||
|
|
||||
absPath = pref and result = ""
|
||||
or
|
||||
@@ -79,7 +79,7 @@ class Container extends Locatable, @container {
|
||||
* </table>
|
||||
*/
|
||||
string getBaseName() {
|
||||
result = this.getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1)
|
||||
result = getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,9 +105,7 @@ class Container extends Locatable, @container {
|
||||
* <tr><td>"/tmp/x.tar.gz"</td><td>"gz"</td></tr>
|
||||
* </table>
|
||||
*/
|
||||
string getExtension() {
|
||||
result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3)
|
||||
}
|
||||
string getExtension() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) }
|
||||
|
||||
/**
|
||||
* Gets the stem of this container, that is, the prefix of its base name up to
|
||||
@@ -126,9 +124,7 @@ class Container extends Locatable, @container {
|
||||
* <tr><td>"/tmp/x.tar.gz"</td><td>"x.tar"</td></tr>
|
||||
* </table>
|
||||
*/
|
||||
string getStem() {
|
||||
result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1)
|
||||
}
|
||||
string getStem() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) }
|
||||
|
||||
/** Gets the parent container of this file or folder, if any. */
|
||||
Container getParentContainer() {
|
||||
@@ -139,20 +135,20 @@ class Container extends Locatable, @container {
|
||||
Container getAChildContainer() { this = result.getParentContainer() }
|
||||
|
||||
/** Gets a file in this container. */
|
||||
File getAFile() { result = this.getAChildContainer() }
|
||||
File getAFile() { result = getAChildContainer() }
|
||||
|
||||
/** Gets the file in this container that has the given `baseName`, if any. */
|
||||
File getFile(string baseName) {
|
||||
result = this.getAFile() and
|
||||
result = getAFile() and
|
||||
result.getBaseName() = baseName
|
||||
}
|
||||
|
||||
/** Gets a sub-folder in this container. */
|
||||
Folder getAFolder() { result = this.getAChildContainer() }
|
||||
Folder getAFolder() { result = getAChildContainer() }
|
||||
|
||||
/** Gets the sub-folder in this container that has the given `baseName`, if any. */
|
||||
Folder getFolder(string baseName) {
|
||||
result = this.getAFolder() and
|
||||
result = getAFolder() and
|
||||
result.getBaseName() = baseName
|
||||
}
|
||||
|
||||
@@ -161,7 +157,7 @@ class Container extends Locatable, @container {
|
||||
*
|
||||
* This is the absolute path of the container.
|
||||
*/
|
||||
override string toString() { result = this.getAbsolutePath() }
|
||||
override string toString() { result = getAbsolutePath() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -43,26 +43,26 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
|
||||
*/
|
||||
string getFullSignature() {
|
||||
exists(string name, string templateArgs, string args |
|
||||
result = name + templateArgs + args + " -> " + this.getType().toString() and
|
||||
name = this.getQualifiedName() and
|
||||
result = name + templateArgs + args + " -> " + getType().toString() and
|
||||
name = getQualifiedName() and
|
||||
(
|
||||
if exists(this.getATemplateArgument())
|
||||
if exists(getATemplateArgument())
|
||||
then
|
||||
templateArgs =
|
||||
"<" +
|
||||
concat(int i |
|
||||
exists(this.getTemplateArgument(i))
|
||||
exists(getTemplateArgument(i))
|
||||
|
|
||||
this.getTemplateArgument(i).toString(), ", " order by i
|
||||
getTemplateArgument(i).toString(), ", " order by i
|
||||
) + ">"
|
||||
else templateArgs = ""
|
||||
) and
|
||||
args =
|
||||
"(" +
|
||||
concat(int i |
|
||||
exists(this.getParameter(i))
|
||||
exists(getParameter(i))
|
||||
|
|
||||
this.getParameter(i).getType().toString(), ", " order by i
|
||||
getParameter(i).getType().toString(), ", " order by i
|
||||
) + ")"
|
||||
)
|
||||
}
|
||||
@@ -70,7 +70,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
|
||||
/** Gets a specifier of this function. */
|
||||
override Specifier getASpecifier() {
|
||||
funspecifiers(underlyingElement(this), unresolveElement(result)) or
|
||||
result.hasName(this.getADeclarationEntry().getASpecifier())
|
||||
result.hasName(getADeclarationEntry().getASpecifier())
|
||||
}
|
||||
|
||||
/** Gets an attribute of this function. */
|
||||
@@ -149,7 +149,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
|
||||
* Holds if this function is declared with `__attribute__((naked))` or
|
||||
* `__declspec(naked)`.
|
||||
*/
|
||||
predicate isNaked() { this.getAnAttribute().hasName("naked") }
|
||||
predicate isNaked() { getAnAttribute().hasName("naked") }
|
||||
|
||||
/**
|
||||
* Holds if this function has a trailing return type.
|
||||
@@ -172,7 +172,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
|
||||
* Gets the return type of this function after specifiers have been deeply
|
||||
* stripped and typedefs have been resolved.
|
||||
*/
|
||||
Type getUnspecifiedType() { result = this.getType().getUnspecifiedType() }
|
||||
Type getUnspecifiedType() { result = getType().getUnspecifiedType() }
|
||||
|
||||
/**
|
||||
* Gets the nth parameter of this function. There is no result for the
|
||||
@@ -206,7 +206,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
|
||||
int getEffectiveNumberOfParameters() {
|
||||
// This method is overridden in `MemberFunction`, where the result is
|
||||
// adjusted to account for the implicit `this` parameter.
|
||||
result = this.getNumberOfParameters()
|
||||
result = getNumberOfParameters()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -216,7 +216,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
|
||||
* return `int p1, int p2`.
|
||||
*/
|
||||
string getParameterString() {
|
||||
result = concat(int i | | min(this.getParameter(i).getTypedName()), ", " order by i)
|
||||
result = concat(int i | | min(getParameter(i).getTypedName()), ", " order by i)
|
||||
}
|
||||
|
||||
/** Gets a call to this function. */
|
||||
@@ -229,7 +229,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
|
||||
*/
|
||||
override FunctionDeclarationEntry getADeclarationEntry() {
|
||||
if fun_decls(_, underlyingElement(this), _, _, _)
|
||||
then this.declEntry(result)
|
||||
then declEntry(result)
|
||||
else
|
||||
exists(Function f |
|
||||
this.isConstructedFrom(f) and
|
||||
@@ -250,7 +250,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
|
||||
* Gets the location of a `FunctionDeclarationEntry` corresponding to this
|
||||
* declaration.
|
||||
*/
|
||||
override Location getADeclarationLocation() { result = this.getADeclarationEntry().getLocation() }
|
||||
override Location getADeclarationLocation() { result = getADeclarationEntry().getLocation() }
|
||||
|
||||
/** Holds if this Function is a Template specialization. */
|
||||
predicate isSpecialization() {
|
||||
@@ -265,14 +265,14 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
|
||||
* definition, if any.
|
||||
*/
|
||||
override FunctionDeclarationEntry getDefinition() {
|
||||
result = this.getADeclarationEntry() and
|
||||
result = getADeclarationEntry() and
|
||||
result.isDefinition()
|
||||
}
|
||||
|
||||
/** Gets the location of the definition, if any. */
|
||||
override Location getDefinitionLocation() {
|
||||
if exists(this.getDefinition())
|
||||
then result = this.getDefinition().getLocation()
|
||||
if exists(getDefinition())
|
||||
then result = getDefinition().getLocation()
|
||||
else exists(Function f | this.isConstructedFrom(f) and result = f.getDefinition().getLocation())
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
|
||||
* definition, if possible.)
|
||||
*/
|
||||
override Location getLocation() {
|
||||
if exists(this.getDefinition())
|
||||
if exists(getDefinition())
|
||||
then result = this.getDefinitionLocation()
|
||||
else result = this.getADeclarationLocation()
|
||||
}
|
||||
@@ -299,7 +299,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
|
||||
BlockStmt getBlock() { result.getParentScope() = this }
|
||||
|
||||
/** Holds if this function has an entry point. */
|
||||
predicate hasEntryPoint() { exists(this.getEntryPoint()) }
|
||||
predicate hasEntryPoint() { exists(getEntryPoint()) }
|
||||
|
||||
/**
|
||||
* Gets the first node in this function's control flow graph.
|
||||
@@ -392,7 +392,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
|
||||
* Holds if this function has C linkage, as specified by one of its
|
||||
* declaration entries. For example: `extern "C" void foo();`.
|
||||
*/
|
||||
predicate hasCLinkage() { this.getADeclarationEntry().hasCLinkage() }
|
||||
predicate hasCLinkage() { getADeclarationEntry().hasCLinkage() }
|
||||
|
||||
/**
|
||||
* Holds if this function is constructed from `f` as a result
|
||||
@@ -409,27 +409,27 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
|
||||
* several functions that are not linked together have been compiled. An
|
||||
* example would be a project with many 'main' functions.
|
||||
*/
|
||||
predicate isMultiplyDefined() { strictcount(this.getFile()) > 1 }
|
||||
predicate isMultiplyDefined() { strictcount(getFile()) > 1 }
|
||||
|
||||
/** Holds if this function is a varargs function. */
|
||||
predicate isVarargs() { this.hasSpecifier("varargs") }
|
||||
predicate isVarargs() { hasSpecifier("varargs") }
|
||||
|
||||
/** Gets a type that is specified to be thrown by the function. */
|
||||
Type getAThrownType() { result = this.getADeclarationEntry().getAThrownType() }
|
||||
Type getAThrownType() { result = getADeclarationEntry().getAThrownType() }
|
||||
|
||||
/**
|
||||
* Gets the `i`th type specified to be thrown by the function.
|
||||
*/
|
||||
Type getThrownType(int i) { result = this.getADeclarationEntry().getThrownType(i) }
|
||||
Type getThrownType(int i) { result = getADeclarationEntry().getThrownType(i) }
|
||||
|
||||
/** Holds if the function has an exception specification. */
|
||||
predicate hasExceptionSpecification() { this.getADeclarationEntry().hasExceptionSpecification() }
|
||||
predicate hasExceptionSpecification() { getADeclarationEntry().hasExceptionSpecification() }
|
||||
|
||||
/** Holds if this function has a `throw()` exception specification. */
|
||||
predicate isNoThrow() { this.getADeclarationEntry().isNoThrow() }
|
||||
predicate isNoThrow() { getADeclarationEntry().isNoThrow() }
|
||||
|
||||
/** Holds if this function has a `noexcept` exception specification. */
|
||||
predicate isNoExcept() { this.getADeclarationEntry().isNoExcept() }
|
||||
predicate isNoExcept() { getADeclarationEntry().isNoExcept() }
|
||||
|
||||
/**
|
||||
* Gets a function that overloads this one.
|
||||
@@ -539,7 +539,7 @@ private predicate candGetAnOverloadNonMember(string name, Namespace namespace, F
|
||||
*/
|
||||
class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
|
||||
/** Gets the function which is being declared or defined. */
|
||||
override Function getDeclaration() { result = this.getFunction() }
|
||||
override Function getDeclaration() { result = getFunction() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "FunctionDeclarationEntry" }
|
||||
|
||||
@@ -586,7 +586,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
|
||||
* case, catch) plus the number of branching expressions (`?`, `&&`,
|
||||
* `||`) plus one.
|
||||
*/
|
||||
int getCyclomaticComplexity() { result = 1 + cyclomaticComplexityBranches(this.getBlock()) }
|
||||
int getCyclomaticComplexity() { result = 1 + cyclomaticComplexityBranches(getBlock()) }
|
||||
|
||||
/**
|
||||
* If this is a function definition, get the block containing the
|
||||
@@ -594,7 +594,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
|
||||
*/
|
||||
BlockStmt getBlock() {
|
||||
this.isDefinition() and
|
||||
result = this.getFunction().getBlock() and
|
||||
result = getFunction().getBlock() and
|
||||
result.getFile() = this.getFile()
|
||||
}
|
||||
|
||||
@@ -604,7 +604,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
|
||||
*/
|
||||
pragma[noopt]
|
||||
int getNumberOfLines() {
|
||||
exists(BlockStmt b, Location l, int start, int end, int diff | b = this.getBlock() |
|
||||
exists(BlockStmt b, Location l, int start, int end, int diff | b = getBlock() |
|
||||
l = b.getLocation() and
|
||||
start = l.getStartLine() and
|
||||
end = l.getEndLine() and
|
||||
@@ -618,7 +618,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
|
||||
* declaration.
|
||||
*/
|
||||
ParameterDeclarationEntry getAParameterDeclarationEntry() {
|
||||
result = this.getParameterDeclarationEntry(_)
|
||||
result = getParameterDeclarationEntry(_)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -639,8 +639,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
|
||||
* return 'int p1, int p2'.
|
||||
*/
|
||||
string getParameterString() {
|
||||
result =
|
||||
concat(int i | | min(this.getParameterDeclarationEntry(i).getTypedName()), ", " order by i)
|
||||
result = concat(int i | | min(getParameterDeclarationEntry(i).getTypedName()), ", " order by i)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -648,10 +647,10 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
|
||||
*
|
||||
* `extern "C" void foo();`
|
||||
*/
|
||||
predicate hasCLinkage() { this.getASpecifier() = "c_linkage" }
|
||||
predicate hasCLinkage() { getASpecifier() = "c_linkage" }
|
||||
|
||||
/** Holds if this declaration entry has a void parameter list. */
|
||||
predicate hasVoidParamList() { this.getASpecifier() = "void_param_list" }
|
||||
predicate hasVoidParamList() { getASpecifier() = "void_param_list" }
|
||||
|
||||
/** Holds if this declaration is also a definition of its function. */
|
||||
override predicate isDefinition() { fun_def(underlyingElement(this)) }
|
||||
@@ -666,7 +665,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
|
||||
predicate isImplicit() { fun_implicit(underlyingElement(this)) }
|
||||
|
||||
/** Gets a type that is specified to be thrown by the declared function. */
|
||||
Type getAThrownType() { result = this.getThrownType(_) }
|
||||
Type getAThrownType() { result = getThrownType(_) }
|
||||
|
||||
/**
|
||||
* Gets the `i`th type specified to be thrown by the declared function
|
||||
@@ -691,8 +690,8 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
|
||||
predicate hasExceptionSpecification() {
|
||||
fun_decl_throws(underlyingElement(this), _, _) or
|
||||
fun_decl_noexcept(underlyingElement(this), _) or
|
||||
this.isNoThrow() or
|
||||
this.isNoExcept()
|
||||
isNoThrow() or
|
||||
isNoExcept()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -764,7 +763,7 @@ class Operator extends Function {
|
||||
*/
|
||||
class TemplateFunction extends Function {
|
||||
TemplateFunction() {
|
||||
is_function_template(underlyingElement(this)) and exists(this.getATemplateArgument())
|
||||
is_function_template(underlyingElement(this)) and exists(getATemplateArgument())
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "TemplateFunction" }
|
||||
|
||||
@@ -23,7 +23,7 @@ class Include extends PreprocessorDirective, @ppd_include {
|
||||
* Gets the token which occurs after `#include`, for example `"filename"`
|
||||
* or `<filename>`.
|
||||
*/
|
||||
string getIncludeText() { result = this.getHead() }
|
||||
string getIncludeText() { result = getHead() }
|
||||
|
||||
/** Gets the file directly included by this `#include`. */
|
||||
File getIncludedFile() { includes(underlyingElement(this), unresolveElement(result)) }
|
||||
@@ -53,7 +53,7 @@ class Include extends PreprocessorDirective, @ppd_include {
|
||||
* ```
|
||||
*/
|
||||
class IncludeNext extends Include, @ppd_include_next {
|
||||
override string toString() { result = "#include_next " + this.getIncludeText() }
|
||||
override string toString() { result = "#include_next " + getIncludeText() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,5 +65,5 @@ class IncludeNext extends Include, @ppd_include_next {
|
||||
* ```
|
||||
*/
|
||||
class Import extends Include, @ppd_objc_import {
|
||||
override string toString() { result = "#import " + this.getIncludeText() }
|
||||
override string toString() { result = "#import " + getIncludeText() }
|
||||
}
|
||||
|
||||
@@ -34,8 +34,8 @@ class Initializer extends ControlFlowNode, @initialiser {
|
||||
override predicate fromSource() { not this.getLocation() instanceof UnknownLocation }
|
||||
|
||||
override string toString() {
|
||||
if exists(this.getDeclaration())
|
||||
then result = "initializer for " + max(this.getDeclaration().getName())
|
||||
if exists(getDeclaration())
|
||||
then result = "initializer for " + max(getDeclaration().getName())
|
||||
else result = "initializer"
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ class Location extends @location {
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
@@ -79,8 +79,8 @@ class Location extends @location {
|
||||
|
||||
/** Holds if location `l` is completely contained within this one. */
|
||||
predicate subsumes(Location l) {
|
||||
exists(File f | f = this.getFile() |
|
||||
exists(int thisStart, int thisEnd | this.charLoc(f, thisStart, thisEnd) |
|
||||
exists(File f | f = getFile() |
|
||||
exists(int thisStart, int thisEnd | charLoc(f, thisStart, thisEnd) |
|
||||
exists(int lStart, int lEnd | l.charLoc(f, lStart, lEnd) |
|
||||
thisStart <= lStart and lEnd <= thisEnd
|
||||
)
|
||||
@@ -97,10 +97,10 @@ class Location extends @location {
|
||||
* see `subsumes`.
|
||||
*/
|
||||
predicate charLoc(File f, int start, int end) {
|
||||
f = this.getFile() and
|
||||
f = getFile() and
|
||||
exists(int maxCols | maxCols = maxCols(f) |
|
||||
start = this.getStartLine() * maxCols + this.getStartColumn() and
|
||||
end = this.getEndLine() * maxCols + this.getEndColumn()
|
||||
start = getStartLine() * maxCols + getStartColumn() and
|
||||
end = getEndLine() * maxCols + getEndColumn()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -144,7 +144,7 @@ class Locatable extends Element { }
|
||||
* expressions, one for statements and one for other program elements.
|
||||
*/
|
||||
class UnknownLocation extends Location {
|
||||
UnknownLocation() { this.getFile().getAbsolutePath() = "" }
|
||||
UnknownLocation() { getFile().getAbsolutePath() = "" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -44,10 +44,10 @@ class Macro extends PreprocessorDirective, @ppd_define {
|
||||
* Gets the name of the macro. For example, `MAX` in
|
||||
* `#define MAX(x,y) (((x)>(y))?(x):(y))`.
|
||||
*/
|
||||
string getName() { result = this.getHead().splitAt("(", 0) }
|
||||
string getName() { result = getHead().splitAt("(", 0) }
|
||||
|
||||
/** Holds if the macro has name `name`. */
|
||||
predicate hasName(string name) { this.getName() = name }
|
||||
predicate hasName(string name) { getName() = name }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,7 +130,7 @@ class MacroAccess extends Locatable, @macroinvocation {
|
||||
override string toString() { result = this.getMacro().getHead() }
|
||||
|
||||
/** Gets the name of the accessed macro. */
|
||||
string getMacroName() { result = this.getMacro().getName() }
|
||||
string getMacroName() { result = getMacro().getName() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -197,8 +197,8 @@ class MacroInvocation extends MacroAccess {
|
||||
* expression. In other cases, it may have multiple results or no results.
|
||||
*/
|
||||
Expr getExpr() {
|
||||
result = this.getAnExpandedElement() and
|
||||
not result.getParent() = this.getAnExpandedElement() and
|
||||
result = getAnExpandedElement() and
|
||||
not result.getParent() = getAnExpandedElement() and
|
||||
not result instanceof Conversion
|
||||
}
|
||||
|
||||
@@ -208,8 +208,8 @@ class MacroInvocation extends MacroAccess {
|
||||
* element is not a statement (for example if it is an expression).
|
||||
*/
|
||||
Stmt getStmt() {
|
||||
result = this.getAnExpandedElement() and
|
||||
not result.getParent() = this.getAnExpandedElement()
|
||||
result = getAnExpandedElement() and
|
||||
not result.getParent() = getAnExpandedElement()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -278,7 +278,7 @@ deprecated class MacroInvocationExpr extends Expr {
|
||||
MacroInvocation getInvocation() { result.getExpr() = this }
|
||||
|
||||
/** Gets the name of the invoked macro. */
|
||||
string getMacroName() { result = this.getInvocation().getMacroName() }
|
||||
string getMacroName() { result = getInvocation().getMacroName() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -298,7 +298,7 @@ deprecated class MacroInvocationStmt extends Stmt {
|
||||
MacroInvocation getInvocation() { result.getStmt() = this }
|
||||
|
||||
/** Gets the name of the invoked macro. */
|
||||
string getMacroName() { result = this.getInvocation().getMacroName() }
|
||||
string getMacroName() { result = getInvocation().getMacroName() }
|
||||
}
|
||||
|
||||
/** Holds if `l` is the location of a macro. */
|
||||
|
||||
@@ -36,9 +36,7 @@ class MemberFunction extends Function {
|
||||
* `this` parameter.
|
||||
*/
|
||||
override int getEffectiveNumberOfParameters() {
|
||||
if this.isStatic()
|
||||
then result = this.getNumberOfParameters()
|
||||
else result = this.getNumberOfParameters() + 1
|
||||
if isStatic() then result = getNumberOfParameters() else result = getNumberOfParameters() + 1
|
||||
}
|
||||
|
||||
/** Holds if this member is private. */
|
||||
@@ -51,13 +49,13 @@ class MemberFunction extends Function {
|
||||
predicate isPublic() { this.hasSpecifier("public") }
|
||||
|
||||
/** Holds if this declaration has the lvalue ref-qualifier */
|
||||
predicate isLValueRefQualified() { this.hasSpecifier("&") }
|
||||
predicate isLValueRefQualified() { hasSpecifier("&") }
|
||||
|
||||
/** Holds if this declaration has the rvalue ref-qualifier */
|
||||
predicate isRValueRefQualified() { this.hasSpecifier("&&") }
|
||||
predicate isRValueRefQualified() { hasSpecifier("&&") }
|
||||
|
||||
/** Holds if this declaration has a ref-qualifier */
|
||||
predicate isRefQualified() { this.isLValueRefQualified() or this.isRValueRefQualified() }
|
||||
predicate isRefQualified() { isLValueRefQualified() or isRValueRefQualified() }
|
||||
|
||||
/** Holds if this function overrides that function. */
|
||||
predicate overrides(MemberFunction that) {
|
||||
@@ -75,10 +73,10 @@ class MemberFunction extends Function {
|
||||
* class body.
|
||||
*/
|
||||
FunctionDeclarationEntry getClassBodyDeclarationEntry() {
|
||||
if strictcount(this.getADeclarationEntry()) = 1
|
||||
then result = this.getDefinition()
|
||||
if strictcount(getADeclarationEntry()) = 1
|
||||
then result = getDefinition()
|
||||
else (
|
||||
result = this.getADeclarationEntry() and result != this.getDefinition()
|
||||
result = getADeclarationEntry() and result != getDefinition()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -200,7 +198,7 @@ class Constructor extends MemberFunction {
|
||||
* compiler-generated action which initializes a base class or member
|
||||
* variable.
|
||||
*/
|
||||
ConstructorInit getAnInitializer() { result = this.getInitializer(_) }
|
||||
ConstructorInit getAnInitializer() { result = getInitializer(_) }
|
||||
|
||||
/**
|
||||
* Gets an entry in the constructor's initializer list, or a
|
||||
@@ -222,8 +220,8 @@ class ImplicitConversionFunction extends MemberFunction {
|
||||
functions(underlyingElement(this), _, 4)
|
||||
or
|
||||
// ConversionConstructor (deprecated)
|
||||
strictcount(Parameter p | p = this.getAParameter() and not p.hasInitializer()) = 1 and
|
||||
not this.hasSpecifier("explicit")
|
||||
strictcount(Parameter p | p = getAParameter() and not p.hasInitializer()) = 1 and
|
||||
not hasSpecifier("explicit")
|
||||
}
|
||||
|
||||
/** Gets the type this `ImplicitConversionFunction` takes as input. */
|
||||
@@ -250,8 +248,8 @@ class ImplicitConversionFunction extends MemberFunction {
|
||||
*/
|
||||
deprecated class ConversionConstructor extends Constructor, ImplicitConversionFunction {
|
||||
ConversionConstructor() {
|
||||
strictcount(Parameter p | p = this.getAParameter() and not p.hasInitializer()) = 1 and
|
||||
not this.hasSpecifier("explicit")
|
||||
strictcount(Parameter p | p = getAParameter() and not p.hasInitializer()) = 1 and
|
||||
not hasSpecifier("explicit")
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() {
|
||||
@@ -303,15 +301,15 @@ class CopyConstructor extends Constructor {
|
||||
hasCopySignature(this) and
|
||||
(
|
||||
// The rest of the parameters all have default values
|
||||
forall(int i | i > 0 and exists(this.getParameter(i)) | this.getParameter(i).hasInitializer())
|
||||
forall(int i | i > 0 and exists(getParameter(i)) | getParameter(i).hasInitializer())
|
||||
or
|
||||
// or this is a template class, in which case the default values have
|
||||
// not been extracted even if they exist. In that case, we assume that
|
||||
// there are default values present since that is the most common case
|
||||
// in real-world code.
|
||||
this.getDeclaringType() instanceof TemplateClass
|
||||
getDeclaringType() instanceof TemplateClass
|
||||
) and
|
||||
not exists(this.getATemplateArgument())
|
||||
not exists(getATemplateArgument())
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "CopyConstructor" }
|
||||
@@ -327,8 +325,8 @@ class CopyConstructor extends Constructor {
|
||||
// type-checked for each template instantiation; if an argument in an
|
||||
// instantiation fails to type-check then the corresponding parameter has
|
||||
// no default argument in the instantiation.
|
||||
this.getDeclaringType() instanceof TemplateClass and
|
||||
this.getNumberOfParameters() > 1
|
||||
getDeclaringType() instanceof TemplateClass and
|
||||
getNumberOfParameters() > 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,15 +358,15 @@ class MoveConstructor extends Constructor {
|
||||
hasMoveSignature(this) and
|
||||
(
|
||||
// The rest of the parameters all have default values
|
||||
forall(int i | i > 0 and exists(this.getParameter(i)) | this.getParameter(i).hasInitializer())
|
||||
forall(int i | i > 0 and exists(getParameter(i)) | getParameter(i).hasInitializer())
|
||||
or
|
||||
// or this is a template class, in which case the default values have
|
||||
// not been extracted even if they exist. In that case, we assume that
|
||||
// there are default values present since that is the most common case
|
||||
// in real-world code.
|
||||
this.getDeclaringType() instanceof TemplateClass
|
||||
getDeclaringType() instanceof TemplateClass
|
||||
) and
|
||||
not exists(this.getATemplateArgument())
|
||||
not exists(getATemplateArgument())
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "MoveConstructor" }
|
||||
@@ -384,8 +382,8 @@ class MoveConstructor extends Constructor {
|
||||
// type-checked for each template instantiation; if an argument in an
|
||||
// instantiation fails to type-check then the corresponding parameter has
|
||||
// no default argument in the instantiation.
|
||||
this.getDeclaringType() instanceof TemplateClass and
|
||||
this.getNumberOfParameters() > 1
|
||||
getDeclaringType() instanceof TemplateClass and
|
||||
getNumberOfParameters() > 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -428,7 +426,7 @@ class Destructor extends MemberFunction {
|
||||
* Gets a compiler-generated action which destructs a base class or member
|
||||
* variable.
|
||||
*/
|
||||
DestructorDestruction getADestruction() { result = this.getDestruction(_) }
|
||||
DestructorDestruction getADestruction() { result = getDestruction(_) }
|
||||
|
||||
/**
|
||||
* Gets a compiler-generated action which destructs a base class or member
|
||||
@@ -477,16 +475,16 @@ class ConversionOperator extends MemberFunction, ImplicitConversionFunction {
|
||||
*/
|
||||
class CopyAssignmentOperator extends Operator {
|
||||
CopyAssignmentOperator() {
|
||||
this.hasName("operator=") and
|
||||
hasName("operator=") and
|
||||
(
|
||||
hasCopySignature(this)
|
||||
or
|
||||
// Unlike CopyConstructor, this member allows a non-reference
|
||||
// parameter.
|
||||
this.getParameter(0).getUnspecifiedType() = this.getDeclaringType()
|
||||
getParameter(0).getUnspecifiedType() = getDeclaringType()
|
||||
) and
|
||||
not exists(this.getParameter(1)) and
|
||||
not exists(this.getATemplateArgument())
|
||||
not exists(getATemplateArgument())
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "CopyAssignmentOperator" }
|
||||
@@ -509,10 +507,10 @@ class CopyAssignmentOperator extends Operator {
|
||||
*/
|
||||
class MoveAssignmentOperator extends Operator {
|
||||
MoveAssignmentOperator() {
|
||||
this.hasName("operator=") and
|
||||
hasName("operator=") and
|
||||
hasMoveSignature(this) and
|
||||
not exists(this.getParameter(1)) and
|
||||
not exists(this.getATemplateArgument())
|
||||
not exists(getATemplateArgument())
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "MoveAssignmentOperator" }
|
||||
|
||||
@@ -38,8 +38,8 @@ class Namespace extends NameQualifyingElement, @namespace {
|
||||
* unless the namespace has exactly one declaration entry.
|
||||
*/
|
||||
override Location getLocation() {
|
||||
if strictcount(this.getADeclarationEntry()) = 1
|
||||
then result = this.getADeclarationEntry().getLocation()
|
||||
if strictcount(getADeclarationEntry()) = 1
|
||||
then result = getADeclarationEntry().getLocation()
|
||||
else result instanceof UnknownDefaultLocation
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ class Namespace extends NameQualifyingElement, @namespace {
|
||||
predicate hasName(string name) { name = this.getName() }
|
||||
|
||||
/** Holds if this namespace is anonymous. */
|
||||
predicate isAnonymous() { this.hasName("(unnamed namespace)") }
|
||||
predicate isAnonymous() { hasName("(unnamed namespace)") }
|
||||
|
||||
/** Gets the name of the parent namespace, if it exists. */
|
||||
private string getParentName() {
|
||||
@@ -60,9 +60,9 @@ class Namespace extends NameQualifyingElement, @namespace {
|
||||
|
||||
/** Gets the qualified name of this namespace. For example: `a::b`. */
|
||||
string getQualifiedName() {
|
||||
if exists(this.getParentName())
|
||||
then result = this.getParentNamespace().getQualifiedName() + "::" + this.getName()
|
||||
else result = this.getName()
|
||||
if exists(getParentName())
|
||||
then result = getParentNamespace().getQualifiedName() + "::" + getName()
|
||||
else result = getName()
|
||||
}
|
||||
|
||||
/** Gets the parent namespace, if any. */
|
||||
@@ -99,7 +99,7 @@ class Namespace extends NameQualifyingElement, @namespace {
|
||||
/** Gets a version of the `QualifiedName` that is more suitable for display purposes. */
|
||||
string getFriendlyName() { result = this.getQualifiedName() }
|
||||
|
||||
final override string toString() { result = this.getFriendlyName() }
|
||||
final override string toString() { result = getFriendlyName() }
|
||||
|
||||
/** Gets a declaration of (part of) this namespace. */
|
||||
NamespaceDeclarationEntry getADeclarationEntry() { result.getNamespace() = this }
|
||||
|
||||
@@ -40,12 +40,12 @@ class Parameter extends LocalScopeVariable, @parameter {
|
||||
*/
|
||||
override string getName() {
|
||||
exists(VariableDeclarationEntry vde |
|
||||
vde = this.getANamedDeclarationEntry() and result = vde.getName()
|
||||
vde = getANamedDeclarationEntry() and result = vde.getName()
|
||||
|
|
||||
vde.isDefinition() or not this.getANamedDeclarationEntry().isDefinition()
|
||||
vde.isDefinition() or not getANamedDeclarationEntry().isDefinition()
|
||||
)
|
||||
or
|
||||
not exists(this.getANamedDeclarationEntry()) and
|
||||
not exists(getANamedDeclarationEntry()) and
|
||||
result = "(unnamed parameter " + this.getIndex().toString() + ")"
|
||||
}
|
||||
|
||||
@@ -58,12 +58,8 @@ class Parameter extends LocalScopeVariable, @parameter {
|
||||
*/
|
||||
string getTypedName() {
|
||||
exists(string typeString, string nameString |
|
||||
(
|
||||
if exists(this.getType().getName())
|
||||
then typeString = this.getType().getName()
|
||||
else typeString = ""
|
||||
) and
|
||||
(if exists(this.getName()) then nameString = this.getName() else nameString = "") and
|
||||
(if exists(getType().getName()) then typeString = getType().getName() else typeString = "") and
|
||||
(if exists(getName()) then nameString = getName() else nameString = "") and
|
||||
(
|
||||
if typeString != "" and nameString != ""
|
||||
then result = typeString + " " + nameString
|
||||
@@ -73,7 +69,7 @@ class Parameter extends LocalScopeVariable, @parameter {
|
||||
}
|
||||
|
||||
private VariableDeclarationEntry getANamedDeclarationEntry() {
|
||||
result = this.getAnEffectiveDeclarationEntry() and result.getName() != ""
|
||||
result = getAnEffectiveDeclarationEntry() and result.getName() != ""
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,13 +82,13 @@ class Parameter extends LocalScopeVariable, @parameter {
|
||||
* own).
|
||||
*/
|
||||
private VariableDeclarationEntry getAnEffectiveDeclarationEntry() {
|
||||
if this.getFunction().isConstructedFrom(_)
|
||||
if getFunction().isConstructedFrom(_)
|
||||
then
|
||||
exists(Function prototypeInstantiation |
|
||||
prototypeInstantiation.getParameter(this.getIndex()) = result.getVariable() and
|
||||
this.getFunction().isConstructedFrom(prototypeInstantiation)
|
||||
prototypeInstantiation.getParameter(getIndex()) = result.getVariable() and
|
||||
getFunction().isConstructedFrom(prototypeInstantiation)
|
||||
)
|
||||
else result = this.getADeclarationEntry()
|
||||
else result = getADeclarationEntry()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,7 +114,7 @@ class Parameter extends LocalScopeVariable, @parameter {
|
||||
* `getName()` is not "(unnamed parameter i)" (where `i` is the index
|
||||
* of the parameter).
|
||||
*/
|
||||
predicate isNamed() { exists(this.getANamedDeclarationEntry()) }
|
||||
predicate isNamed() { exists(getANamedDeclarationEntry()) }
|
||||
|
||||
/**
|
||||
* Gets the function to which this parameter belongs, if it is a function
|
||||
@@ -161,9 +157,9 @@ class Parameter extends LocalScopeVariable, @parameter {
|
||||
*/
|
||||
override Location getLocation() {
|
||||
exists(VariableDeclarationEntry vde |
|
||||
vde = this.getAnEffectiveDeclarationEntry() and result = vde.getLocation()
|
||||
vde = getAnEffectiveDeclarationEntry() and result = vde.getLocation()
|
||||
|
|
||||
vde.isDefinition() or not this.getAnEffectiveDeclarationEntry().isDefinition()
|
||||
vde.isDefinition() or not getAnEffectiveDeclarationEntry().isDefinition()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@ class PreprocessorDirective extends Locatable, @preprocdirect {
|
||||
PreprocessorBranch getAGuard() {
|
||||
exists(PreprocessorEndif e, int line |
|
||||
result.getEndIf() = e and
|
||||
e.getFile() = this.getFile() and
|
||||
result.getFile() = this.getFile() and
|
||||
e.getFile() = getFile() and
|
||||
result.getFile() = getFile() and
|
||||
line = this.getLocation().getStartLine() and
|
||||
result.getLocation().getStartLine() < line and
|
||||
line < e.getLocation().getEndLine()
|
||||
@@ -69,9 +69,7 @@ class PreprocessorBranchDirective extends PreprocessorDirective, TPreprocessorBr
|
||||
* directives in different translation units, then there can be more than
|
||||
* one result.
|
||||
*/
|
||||
PreprocessorEndif getEndIf() {
|
||||
preprocpair(unresolveElement(this.getIf()), unresolveElement(result))
|
||||
}
|
||||
PreprocessorEndif getEndIf() { preprocpair(unresolveElement(getIf()), unresolveElement(result)) }
|
||||
|
||||
/**
|
||||
* Gets the next `#elif`, `#else` or `#endif` matching this branching
|
||||
@@ -139,7 +137,7 @@ class PreprocessorBranch extends PreprocessorBranchDirective, @ppd_branch {
|
||||
* which evaluated it, or was not taken by any translation unit which
|
||||
* evaluated it.
|
||||
*/
|
||||
predicate wasPredictable() { not (this.wasTaken() and this.wasNotTaken()) }
|
||||
predicate wasPredictable() { not (wasTaken() and wasNotTaken()) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -270,7 +268,7 @@ class PreprocessorUndef extends PreprocessorDirective, @ppd_undef {
|
||||
/**
|
||||
* Gets the name of the macro that is undefined.
|
||||
*/
|
||||
string getName() { result = this.getHead() }
|
||||
string getName() { result = getHead() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -105,8 +105,8 @@ private class DumpType extends Type {
|
||||
// for a `SpecifiedType`, insert the qualifiers after
|
||||
// `getDeclaratorSuffixBeforeQualifiers()`.
|
||||
result =
|
||||
this.getTypeSpecifier() + this.getDeclaratorPrefix() +
|
||||
this.getDeclaratorSuffixBeforeQualifiers() + this.getDeclaratorSuffix()
|
||||
getTypeSpecifier() + getDeclaratorPrefix() + getDeclaratorSuffixBeforeQualifiers() +
|
||||
getDeclaratorSuffix()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -147,35 +147,29 @@ private class DumpType extends Type {
|
||||
}
|
||||
|
||||
private class BuiltInDumpType extends DumpType, BuiltInType {
|
||||
override string getTypeSpecifier() { result = this.toString() }
|
||||
override string getTypeSpecifier() { result = toString() }
|
||||
}
|
||||
|
||||
private class IntegralDumpType extends BuiltInDumpType, IntegralType {
|
||||
override string getTypeSpecifier() { result = this.getCanonicalArithmeticType().toString() }
|
||||
override string getTypeSpecifier() { result = getCanonicalArithmeticType().toString() }
|
||||
}
|
||||
|
||||
private class DerivedDumpType extends DumpType, DerivedType {
|
||||
override string getTypeSpecifier() { result = this.getBaseType().(DumpType).getTypeSpecifier() }
|
||||
override string getTypeSpecifier() { result = getBaseType().(DumpType).getTypeSpecifier() }
|
||||
|
||||
override string getDeclaratorSuffixBeforeQualifiers() {
|
||||
result = this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
|
||||
result = getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
|
||||
}
|
||||
|
||||
override string getDeclaratorSuffix() {
|
||||
result = this.getBaseType().(DumpType).getDeclaratorSuffix()
|
||||
}
|
||||
override string getDeclaratorSuffix() { result = getBaseType().(DumpType).getDeclaratorSuffix() }
|
||||
}
|
||||
|
||||
private class DecltypeDumpType extends DumpType, Decltype {
|
||||
override string getTypeSpecifier() { result = this.getBaseType().(DumpType).getTypeSpecifier() }
|
||||
override string getTypeSpecifier() { result = getBaseType().(DumpType).getTypeSpecifier() }
|
||||
|
||||
override string getDeclaratorPrefix() {
|
||||
result = this.getBaseType().(DumpType).getDeclaratorPrefix()
|
||||
}
|
||||
override string getDeclaratorPrefix() { result = getBaseType().(DumpType).getDeclaratorPrefix() }
|
||||
|
||||
override string getDeclaratorSuffix() {
|
||||
result = this.getBaseType().(DumpType).getDeclaratorSuffix()
|
||||
}
|
||||
override string getDeclaratorSuffix() { result = getBaseType().(DumpType).getDeclaratorSuffix() }
|
||||
}
|
||||
|
||||
private class PointerIshDumpType extends DerivedDumpType {
|
||||
@@ -186,10 +180,10 @@ private class PointerIshDumpType extends DerivedDumpType {
|
||||
|
||||
override string getDeclaratorPrefix() {
|
||||
exists(string declarator |
|
||||
result = this.getBaseType().(DumpType).getDeclaratorPrefix() + declarator and
|
||||
if this.getBaseType().getUnspecifiedType() instanceof ArrayType
|
||||
then declarator = "(" + this.getDeclaratorToken() + ")"
|
||||
else declarator = this.getDeclaratorToken()
|
||||
result = getBaseType().(DumpType).getDeclaratorPrefix() + declarator and
|
||||
if getBaseType().getUnspecifiedType() instanceof ArrayType
|
||||
then declarator = "(" + getDeclaratorToken() + ")"
|
||||
else declarator = getDeclaratorToken()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -212,13 +206,13 @@ private class RValueReferenceDumpType extends PointerIshDumpType, RValueReferenc
|
||||
}
|
||||
|
||||
private class PointerToMemberDumpType extends DumpType, PointerToMemberType {
|
||||
override string getTypeSpecifier() { result = this.getBaseType().(DumpType).getTypeSpecifier() }
|
||||
override string getTypeSpecifier() { result = getBaseType().(DumpType).getTypeSpecifier() }
|
||||
|
||||
override string getDeclaratorPrefix() {
|
||||
exists(string declarator, string parenDeclarator, Type baseType |
|
||||
declarator = this.getClass().(DumpType).getTypeIdentityString() + "::*" and
|
||||
result = this.getBaseType().(DumpType).getDeclaratorPrefix() + " " + parenDeclarator and
|
||||
baseType = this.getBaseType().getUnspecifiedType() and
|
||||
declarator = getClass().(DumpType).getTypeIdentityString() + "::*" and
|
||||
result = getBaseType().(DumpType).getDeclaratorPrefix() + " " + parenDeclarator and
|
||||
baseType = getBaseType().getUnspecifiedType() and
|
||||
if baseType instanceof ArrayType or baseType instanceof RoutineType
|
||||
then parenDeclarator = "(" + declarator
|
||||
else parenDeclarator = declarator
|
||||
@@ -227,44 +221,38 @@ private class PointerToMemberDumpType extends DumpType, PointerToMemberType {
|
||||
|
||||
override string getDeclaratorSuffixBeforeQualifiers() {
|
||||
exists(Type baseType |
|
||||
baseType = this.getBaseType().getUnspecifiedType() and
|
||||
baseType = getBaseType().getUnspecifiedType() and
|
||||
if baseType instanceof ArrayType or baseType instanceof RoutineType
|
||||
then result = ")" + this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
|
||||
else result = this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
|
||||
then result = ")" + getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
|
||||
else result = getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
|
||||
)
|
||||
}
|
||||
|
||||
override string getDeclaratorSuffix() {
|
||||
result = this.getBaseType().(DumpType).getDeclaratorSuffix()
|
||||
}
|
||||
override string getDeclaratorSuffix() { result = getBaseType().(DumpType).getDeclaratorSuffix() }
|
||||
}
|
||||
|
||||
private class ArrayDumpType extends DerivedDumpType, ArrayType {
|
||||
override string getDeclaratorPrefix() {
|
||||
result = this.getBaseType().(DumpType).getDeclaratorPrefix()
|
||||
}
|
||||
override string getDeclaratorPrefix() { result = getBaseType().(DumpType).getDeclaratorPrefix() }
|
||||
|
||||
override string getDeclaratorSuffixBeforeQualifiers() {
|
||||
if exists(this.getArraySize())
|
||||
if exists(getArraySize())
|
||||
then
|
||||
result =
|
||||
"[" + this.getArraySize().toString() + "]" +
|
||||
this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
|
||||
else result = "[]" + this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
|
||||
"[" + getArraySize().toString() + "]" +
|
||||
getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
|
||||
else result = "[]" + getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
|
||||
}
|
||||
}
|
||||
|
||||
private class FunctionPointerIshDumpType extends DerivedDumpType, FunctionPointerIshType {
|
||||
override string getDeclaratorSuffixBeforeQualifiers() {
|
||||
result = ")" + this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
|
||||
result = ")" + getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers()
|
||||
}
|
||||
|
||||
override string getDeclaratorSuffix() {
|
||||
result = this.getBaseType().(DumpType).getDeclaratorSuffix()
|
||||
}
|
||||
override string getDeclaratorSuffix() { result = getBaseType().(DumpType).getDeclaratorSuffix() }
|
||||
|
||||
override string getDeclaratorPrefix() {
|
||||
result = this.getBaseType().(DumpType).getDeclaratorPrefix() + "(" + this.getDeclaratorToken()
|
||||
result = getBaseType().(DumpType).getDeclaratorPrefix() + "(" + getDeclaratorToken()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -286,10 +274,10 @@ private class BlockDumpType extends FunctionPointerIshDumpType, BlockType {
|
||||
}
|
||||
|
||||
private class RoutineDumpType extends DumpType, RoutineType {
|
||||
override string getTypeSpecifier() { result = this.getReturnType().(DumpType).getTypeSpecifier() }
|
||||
override string getTypeSpecifier() { result = getReturnType().(DumpType).getTypeSpecifier() }
|
||||
|
||||
override string getDeclaratorPrefix() {
|
||||
result = this.getReturnType().(DumpType).getDeclaratorPrefix()
|
||||
result = getReturnType().(DumpType).getDeclaratorPrefix()
|
||||
}
|
||||
|
||||
language[monotonicAggregates]
|
||||
@@ -297,41 +285,39 @@ private class RoutineDumpType extends DumpType, RoutineType {
|
||||
result =
|
||||
"(" +
|
||||
concat(int i |
|
||||
exists(this.getParameterType(i))
|
||||
exists(getParameterType(i))
|
||||
|
|
||||
getParameterTypeString(this.getParameterType(i)), ", " order by i
|
||||
getParameterTypeString(getParameterType(i)), ", " order by i
|
||||
) + ")"
|
||||
}
|
||||
|
||||
override string getDeclaratorSuffix() {
|
||||
result =
|
||||
this.getReturnType().(DumpType).getDeclaratorSuffixBeforeQualifiers() +
|
||||
this.getReturnType().(DumpType).getDeclaratorSuffix()
|
||||
getReturnType().(DumpType).getDeclaratorSuffixBeforeQualifiers() +
|
||||
getReturnType().(DumpType).getDeclaratorSuffix()
|
||||
}
|
||||
}
|
||||
|
||||
private class SpecifiedDumpType extends DerivedDumpType, SpecifiedType {
|
||||
override string getDeclaratorPrefix() {
|
||||
exists(string basePrefix |
|
||||
basePrefix = this.getBaseType().(DumpType).getDeclaratorPrefix() and
|
||||
if this.getBaseType().getUnspecifiedType() instanceof RoutineType
|
||||
basePrefix = getBaseType().(DumpType).getDeclaratorPrefix() and
|
||||
if getBaseType().getUnspecifiedType() instanceof RoutineType
|
||||
then result = basePrefix
|
||||
else result = basePrefix + " " + this.getSpecifierString()
|
||||
else result = basePrefix + " " + getSpecifierString()
|
||||
)
|
||||
}
|
||||
|
||||
override string getDeclaratorSuffixBeforeQualifiers() {
|
||||
exists(string baseSuffix |
|
||||
baseSuffix = this.getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() and
|
||||
if this.getBaseType().getUnspecifiedType() instanceof RoutineType
|
||||
then result = baseSuffix + " " + this.getSpecifierString()
|
||||
baseSuffix = getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() and
|
||||
if getBaseType().getUnspecifiedType() instanceof RoutineType
|
||||
then result = baseSuffix + " " + getSpecifierString()
|
||||
else result = baseSuffix
|
||||
)
|
||||
}
|
||||
|
||||
override string getDeclaratorSuffix() {
|
||||
result = this.getBaseType().(DumpType).getDeclaratorSuffix()
|
||||
}
|
||||
override string getDeclaratorSuffix() { result = getBaseType().(DumpType).getDeclaratorSuffix() }
|
||||
}
|
||||
|
||||
private class UserDumpType extends DumpType, DumpDeclaration, UserType {
|
||||
@@ -344,18 +330,18 @@ private class UserDumpType extends DumpType, DumpDeclaration, UserType {
|
||||
// "lambda [] type at line 12, col. 40"
|
||||
// Use `min(getSimpleName())` to work around an extractor bug where a lambda can have different names
|
||||
// from different compilation units.
|
||||
simpleName = "(" + min(this.getSimpleName()) + ")"
|
||||
else simpleName = this.getSimpleName()
|
||||
simpleName = "(" + min(getSimpleName()) + ")"
|
||||
else simpleName = getSimpleName()
|
||||
) and
|
||||
result = getScopePrefix(this) + simpleName + this.getTemplateArgumentsString()
|
||||
result = getScopePrefix(this) + simpleName + getTemplateArgumentsString()
|
||||
)
|
||||
}
|
||||
|
||||
override string getTypeSpecifier() { result = this.getIdentityString() }
|
||||
override string getTypeSpecifier() { result = getIdentityString() }
|
||||
}
|
||||
|
||||
private class DumpProxyClass extends UserDumpType, ProxyClass {
|
||||
override string getIdentityString() { result = this.getName() }
|
||||
override string getIdentityString() { result = getName() }
|
||||
}
|
||||
|
||||
private class DumpVariable extends DumpDeclaration, Variable {
|
||||
@@ -374,9 +360,9 @@ private class DumpVariable extends DumpDeclaration, Variable {
|
||||
private class DumpFunction extends DumpDeclaration, Function {
|
||||
override string getIdentityString() {
|
||||
result =
|
||||
this.getType().(DumpType).getTypeSpecifier() + this.getType().(DumpType).getDeclaratorPrefix()
|
||||
+ " " + getScopePrefix(this) + this.getName() + this.getTemplateArgumentsString() +
|
||||
this.getDeclaratorSuffixBeforeQualifiers() + this.getDeclaratorSuffix()
|
||||
getType().(DumpType).getTypeSpecifier() + getType().(DumpType).getDeclaratorPrefix() + " " +
|
||||
getScopePrefix(this) + getName() + getTemplateArgumentsString() +
|
||||
getDeclaratorSuffixBeforeQualifiers() + getDeclaratorSuffix()
|
||||
}
|
||||
|
||||
language[monotonicAggregates]
|
||||
@@ -384,29 +370,28 @@ private class DumpFunction extends DumpDeclaration, Function {
|
||||
result =
|
||||
"(" +
|
||||
concat(int i |
|
||||
exists(this.getParameter(i).getType())
|
||||
exists(getParameter(i).getType())
|
||||
|
|
||||
getParameterTypeString(this.getParameter(i).getType()), ", " order by i
|
||||
) + ")" + this.getQualifierString()
|
||||
getParameterTypeString(getParameter(i).getType()), ", " order by i
|
||||
) + ")" + getQualifierString()
|
||||
}
|
||||
|
||||
private string getQualifierString() {
|
||||
if exists(this.getACVQualifier())
|
||||
if exists(getACVQualifier())
|
||||
then
|
||||
result =
|
||||
" " + strictconcat(string qualifier | qualifier = this.getACVQualifier() | qualifier, " ")
|
||||
result = " " + strictconcat(string qualifier | qualifier = getACVQualifier() | qualifier, " ")
|
||||
else result = ""
|
||||
}
|
||||
|
||||
private string getACVQualifier() {
|
||||
result = this.getASpecifier().getName() and
|
||||
result = getASpecifier().getName() and
|
||||
result = ["const", "volatile"]
|
||||
}
|
||||
|
||||
private string getDeclaratorSuffix() {
|
||||
result =
|
||||
this.getType().(DumpType).getDeclaratorSuffixBeforeQualifiers() +
|
||||
this.getType().(DumpType).getDeclaratorSuffix()
|
||||
getType().(DumpType).getDeclaratorSuffixBeforeQualifiers() +
|
||||
getType().(DumpType).getDeclaratorSuffix()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,11 @@ class Specifier extends Element, @specifier {
|
||||
* A C/C++ function specifier: `inline`, `virtual`, or `explicit`.
|
||||
*/
|
||||
class FunctionSpecifier extends Specifier {
|
||||
FunctionSpecifier() { this.hasName(["inline", "virtual", "explicit"]) }
|
||||
FunctionSpecifier() {
|
||||
this.hasName("inline") or
|
||||
this.hasName("virtual") or
|
||||
this.hasName("explicit")
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "FunctionSpecifier" }
|
||||
}
|
||||
@@ -41,7 +45,13 @@ class FunctionSpecifier extends Specifier {
|
||||
* or `mutable".
|
||||
*/
|
||||
class StorageClassSpecifier extends Specifier {
|
||||
StorageClassSpecifier() { this.hasName(["auto", "register", "static", "extern", "mutable"]) }
|
||||
StorageClassSpecifier() {
|
||||
this.hasName("auto") or
|
||||
this.hasName("register") or
|
||||
this.hasName("static") or
|
||||
this.hasName("extern") or
|
||||
this.hasName("mutable")
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "StorageClassSpecifier" }
|
||||
}
|
||||
@@ -50,7 +60,11 @@ class StorageClassSpecifier extends Specifier {
|
||||
* A C++ access specifier: `public`, `protected`, or `private`.
|
||||
*/
|
||||
class AccessSpecifier extends Specifier {
|
||||
AccessSpecifier() { this.hasName(["public", "protected", "private"]) }
|
||||
AccessSpecifier() {
|
||||
this.hasName("public") or
|
||||
this.hasName("protected") or
|
||||
this.hasName("private")
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the visibility of a field with access specifier `this` if it is
|
||||
@@ -126,7 +140,7 @@ class Attribute extends Element, @attribute {
|
||||
AttributeArgument getArgument(int i) { result.getAttribute() = this and result.getIndex() = i }
|
||||
|
||||
/** Gets an argument of the attribute. */
|
||||
AttributeArgument getAnArgument() { result = this.getArgument(_) }
|
||||
AttributeArgument getAnArgument() { result = getArgument(_) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,7 +166,7 @@ class StdAttribute extends Attribute, @stdattribute {
|
||||
* Holds if this attribute has the given namespace and name.
|
||||
*/
|
||||
predicate hasQualifiedName(string namespace, string name) {
|
||||
namespace = this.getNamespace() and this.hasName(name)
|
||||
namespace = getNamespace() and hasName(name)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +184,7 @@ class Declspec extends Attribute, @declspec { }
|
||||
*/
|
||||
class MicrosoftAttribute extends Attribute, @msattribute {
|
||||
AttributeArgument getNamedArgument(string name) {
|
||||
result = this.getAnArgument() and result.getName() = name
|
||||
result = getAnArgument() and result.getName() = name
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,13 +212,13 @@ class AlignAs extends Attribute, @alignas {
|
||||
* ```
|
||||
*/
|
||||
class FormatAttribute extends GnuAttribute {
|
||||
FormatAttribute() { this.getName() = "format" }
|
||||
FormatAttribute() { getName() = "format" }
|
||||
|
||||
/**
|
||||
* Gets the archetype of this format attribute, for example
|
||||
* `"printf"`.
|
||||
*/
|
||||
string getArchetype() { result = this.getArgument(0).getValueText() }
|
||||
string getArchetype() { result = getArgument(0).getValueText() }
|
||||
|
||||
/**
|
||||
* Gets the index in (1-based) format attribute notation associated
|
||||
@@ -222,7 +236,7 @@ class FormatAttribute extends GnuAttribute {
|
||||
* Gets the (0-based) index of the format string,
|
||||
* according to this attribute.
|
||||
*/
|
||||
int getFormatIndex() { result = this.getArgument(1).getValueInt() - this.firstArgumentNumber() }
|
||||
int getFormatIndex() { result = getArgument(1).getValueInt() - firstArgumentNumber() }
|
||||
|
||||
/**
|
||||
* Gets the (0-based) index of the first format argument (if any),
|
||||
@@ -230,8 +244,8 @@ class FormatAttribute extends GnuAttribute {
|
||||
*/
|
||||
int getFirstFormatArgIndex() {
|
||||
exists(int val |
|
||||
val = this.getArgument(2).getValueInt() and
|
||||
result = val - this.firstArgumentNumber() and
|
||||
val = getArgument(2).getValueInt() and
|
||||
result = val - firstArgumentNumber() and
|
||||
not val = 0 // indicates a `vprintf` style format function with arguments not directly available.
|
||||
)
|
||||
}
|
||||
@@ -263,7 +277,7 @@ class AttributeArgument extends Element, @attribute_arg {
|
||||
/**
|
||||
* Gets the value of this argument, if its value is integral.
|
||||
*/
|
||||
int getValueInt() { result = this.getValueText().toInt() }
|
||||
int getValueInt() { result = getValueText().toInt() }
|
||||
|
||||
/**
|
||||
* Gets the value of this argument, if its value is a type.
|
||||
@@ -290,11 +304,11 @@ class AttributeArgument extends Element, @attribute_arg {
|
||||
then result = "empty argument"
|
||||
else
|
||||
exists(string prefix, string tail |
|
||||
(if exists(this.getName()) then prefix = this.getName() + "=" else prefix = "") and
|
||||
(if exists(getName()) then prefix = getName() + "=" else prefix = "") and
|
||||
(
|
||||
if exists(@attribute_arg_type self | self = underlyingElement(this))
|
||||
then tail = this.getValueType().getName()
|
||||
else tail = this.getValueText()
|
||||
then tail = getValueType().getName()
|
||||
else tail = getValueText()
|
||||
) and
|
||||
result = prefix + tail
|
||||
)
|
||||
|
||||
@@ -41,7 +41,7 @@ class Struct extends Class {
|
||||
* ```
|
||||
*/
|
||||
class LocalStruct extends Struct {
|
||||
LocalStruct() { this.isLocal() }
|
||||
LocalStruct() { isLocal() }
|
||||
|
||||
override string getAPrimaryQlClass() { not this instanceof LocalUnion and result = "LocalStruct" }
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@ import semmle.code.cpp.File
|
||||
*/
|
||||
private class GoogleTestHeader extends File {
|
||||
GoogleTestHeader() {
|
||||
this.getBaseName() = "gtest.h" and
|
||||
this.getParentContainer().getBaseName() = "gtest"
|
||||
getBaseName() = "gtest.h" and
|
||||
getParentContainer().getBaseName() = "gtest"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,8 +30,8 @@ private class GoogleTest extends MacroInvocation {
|
||||
*/
|
||||
private class BoostTestFolder extends Folder {
|
||||
BoostTestFolder() {
|
||||
this.getBaseName() = "test" and
|
||||
this.getParentContainer().getBaseName() = "boost"
|
||||
getBaseName() = "test" and
|
||||
getParentContainer().getBaseName() = "boost"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ private class BoostTest extends MacroInvocation {
|
||||
* The `cppunit` directory.
|
||||
*/
|
||||
private class CppUnitFolder extends Folder {
|
||||
CppUnitFolder() { this.getBaseName() = "cppunit" }
|
||||
CppUnitFolder() { getBaseName() = "cppunit" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,8 +57,8 @@ private class CppUnitFolder extends Folder {
|
||||
*/
|
||||
private class CppUnitClass extends Class {
|
||||
CppUnitClass() {
|
||||
this.getFile().getParentContainer+() instanceof CppUnitFolder and
|
||||
this.getNamespace().getParentNamespace*().getName() = "CppUnit"
|
||||
getFile().getParentContainer+() instanceof CppUnitFolder and
|
||||
getNamespace().getParentNamespace*().getName() = "CppUnit"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ class Type extends Locatable, @type {
|
||||
* Holds if this type refers to type `t` (by default,
|
||||
* a type always refers to itself).
|
||||
*/
|
||||
predicate refersTo(Type t) { this.refersToDirectly*(t) }
|
||||
predicate refersTo(Type t) { refersToDirectly*(t) }
|
||||
|
||||
/**
|
||||
* Holds if this type refers to type `t` directly.
|
||||
@@ -1080,11 +1080,11 @@ class DerivedType extends Type, @derivedtype {
|
||||
|
||||
override predicate refersToDirectly(Type t) { t = this.getBaseType() }
|
||||
|
||||
override predicate involvesReference() { this.getBaseType().involvesReference() }
|
||||
override predicate involvesReference() { getBaseType().involvesReference() }
|
||||
|
||||
override predicate involvesTemplateParameter() { this.getBaseType().involvesTemplateParameter() }
|
||||
override predicate involvesTemplateParameter() { getBaseType().involvesTemplateParameter() }
|
||||
|
||||
override Type stripType() { result = this.getBaseType().stripType() }
|
||||
override Type stripType() { result = getBaseType().stripType() }
|
||||
|
||||
/**
|
||||
* Holds if this type has the `__autoreleasing` specifier or if it points to
|
||||
@@ -1165,35 +1165,33 @@ class Decltype extends Type, @decltype {
|
||||
*/
|
||||
predicate parenthesesWouldChangeMeaning() { decltypes(underlyingElement(this), _, _, true) }
|
||||
|
||||
override Type getUnderlyingType() { result = this.getBaseType().getUnderlyingType() }
|
||||
override Type getUnderlyingType() { result = getBaseType().getUnderlyingType() }
|
||||
|
||||
override Type stripTopLevelSpecifiers() { result = this.getBaseType().stripTopLevelSpecifiers() }
|
||||
override Type stripTopLevelSpecifiers() { result = getBaseType().stripTopLevelSpecifiers() }
|
||||
|
||||
override Type stripType() { result = this.getBaseType().stripType() }
|
||||
override Type stripType() { result = getBaseType().stripType() }
|
||||
|
||||
override Type resolveTypedefs() { result = this.getBaseType().resolveTypedefs() }
|
||||
override Type resolveTypedefs() { result = getBaseType().resolveTypedefs() }
|
||||
|
||||
override Location getLocation() { result = this.getExpr().getLocation() }
|
||||
override Location getLocation() { result = getExpr().getLocation() }
|
||||
|
||||
override string toString() { result = "decltype(...)" }
|
||||
|
||||
override string getName() { none() }
|
||||
|
||||
override int getSize() { result = this.getBaseType().getSize() }
|
||||
override int getSize() { result = getBaseType().getSize() }
|
||||
|
||||
override int getAlignment() { result = this.getBaseType().getAlignment() }
|
||||
override int getAlignment() { result = getBaseType().getAlignment() }
|
||||
|
||||
override int getPointerIndirectionLevel() {
|
||||
result = this.getBaseType().getPointerIndirectionLevel()
|
||||
}
|
||||
override int getPointerIndirectionLevel() { result = getBaseType().getPointerIndirectionLevel() }
|
||||
|
||||
override string explain() {
|
||||
result = "decltype resulting in {" + this.getBaseType().explain() + "}"
|
||||
}
|
||||
|
||||
override predicate involvesReference() { this.getBaseType().involvesReference() }
|
||||
override predicate involvesReference() { getBaseType().involvesReference() }
|
||||
|
||||
override predicate involvesTemplateParameter() { this.getBaseType().involvesTemplateParameter() }
|
||||
override predicate involvesTemplateParameter() { getBaseType().involvesTemplateParameter() }
|
||||
|
||||
override predicate isDeeplyConst() { this.getBaseType().isDeeplyConst() }
|
||||
|
||||
@@ -1225,7 +1223,7 @@ class PointerType extends DerivedType {
|
||||
override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConst() }
|
||||
|
||||
override Type resolveTypedefs() {
|
||||
result.(PointerType).getBaseType() = this.getBaseType().resolveTypedefs()
|
||||
result.(PointerType).getBaseType() = getBaseType().resolveTypedefs()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1242,9 +1240,7 @@ class ReferenceType extends DerivedType {
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ReferenceType" }
|
||||
|
||||
override int getPointerIndirectionLevel() {
|
||||
result = this.getBaseType().getPointerIndirectionLevel()
|
||||
}
|
||||
override int getPointerIndirectionLevel() { result = getBaseType().getPointerIndirectionLevel() }
|
||||
|
||||
override string explain() { result = "reference to {" + this.getBaseType().explain() + "}" }
|
||||
|
||||
@@ -1255,7 +1251,7 @@ class ReferenceType extends DerivedType {
|
||||
override predicate involvesReference() { any() }
|
||||
|
||||
override Type resolveTypedefs() {
|
||||
result.(ReferenceType).getBaseType() = this.getBaseType().resolveTypedefs()
|
||||
result.(ReferenceType).getBaseType() = getBaseType().resolveTypedefs()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1334,11 +1330,11 @@ class SpecifiedType extends DerivedType {
|
||||
}
|
||||
|
||||
override Type resolveTypedefs() {
|
||||
result.(SpecifiedType).getBaseType() = this.getBaseType().resolveTypedefs() and
|
||||
result.getASpecifier() = this.getASpecifier()
|
||||
result.(SpecifiedType).getBaseType() = getBaseType().resolveTypedefs() and
|
||||
result.getASpecifier() = getASpecifier()
|
||||
}
|
||||
|
||||
override Type stripTopLevelSpecifiers() { result = this.getBaseType().stripTopLevelSpecifiers() }
|
||||
override Type stripTopLevelSpecifiers() { result = getBaseType().stripTopLevelSpecifiers() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1437,8 +1433,7 @@ class GNUVectorType extends DerivedType {
|
||||
override int getAlignment() { arraysizes(underlyingElement(this), _, _, result) }
|
||||
|
||||
override string explain() {
|
||||
result =
|
||||
"GNU " + this.getNumElements() + " element vector of {" + this.getBaseType().explain() + "}"
|
||||
result = "GNU " + getNumElements() + " element vector of {" + this.getBaseType().explain() + "}"
|
||||
}
|
||||
|
||||
override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConst() }
|
||||
@@ -1473,9 +1468,7 @@ class FunctionReferenceType extends FunctionPointerIshType {
|
||||
|
||||
override string getAPrimaryQlClass() { result = "FunctionReferenceType" }
|
||||
|
||||
override int getPointerIndirectionLevel() {
|
||||
result = this.getBaseType().getPointerIndirectionLevel()
|
||||
}
|
||||
override int getPointerIndirectionLevel() { result = getBaseType().getPointerIndirectionLevel() }
|
||||
|
||||
override string explain() {
|
||||
result = "reference to {" + this.getBaseType().(RoutineType).explain() + "}"
|
||||
@@ -1542,8 +1535,8 @@ class FunctionPointerIshType extends DerivedType {
|
||||
int getNumberOfParameters() { result = count(int i | exists(this.getParameterType(i))) }
|
||||
|
||||
override predicate involvesTemplateParameter() {
|
||||
this.getReturnType().involvesTemplateParameter() or
|
||||
this.getAParameterType().involvesTemplateParameter()
|
||||
getReturnType().involvesTemplateParameter() or
|
||||
getAParameterType().involvesTemplateParameter()
|
||||
}
|
||||
|
||||
override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConst() }
|
||||
@@ -1588,7 +1581,7 @@ class PointerToMemberType extends Type, @ptrtomember {
|
||||
this.getBaseType().explain() + "}"
|
||||
}
|
||||
|
||||
override predicate involvesTemplateParameter() { this.getBaseType().involvesTemplateParameter() }
|
||||
override predicate involvesTemplateParameter() { getBaseType().involvesTemplateParameter() }
|
||||
|
||||
override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConst() }
|
||||
}
|
||||
@@ -1657,6 +1650,7 @@ class RoutineType extends Type, @routinetype {
|
||||
i = 0 and result = "" and not exists(this.getAParameterType())
|
||||
or
|
||||
(
|
||||
exists(this.getParameterType(i)) and
|
||||
if i < max(int j | exists(this.getParameterType(j)))
|
||||
then
|
||||
// Not the last one
|
||||
@@ -1677,8 +1671,8 @@ class RoutineType extends Type, @routinetype {
|
||||
override predicate isDeeplyConstBelow() { none() } // Current limitation: no such thing as a const routine type
|
||||
|
||||
override predicate involvesTemplateParameter() {
|
||||
this.getReturnType().involvesTemplateParameter() or
|
||||
this.getAParameterType().involvesTemplateParameter()
|
||||
getReturnType().involvesTemplateParameter() or
|
||||
getAParameterType().involvesTemplateParameter()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ class TypedefType extends UserType {
|
||||
|
||||
override Type getUnderlyingType() { result = this.getBaseType().getUnderlyingType() }
|
||||
|
||||
override Type stripTopLevelSpecifiers() { result = this.getBaseType().stripTopLevelSpecifiers() }
|
||||
override Type stripTopLevelSpecifiers() { result = getBaseType().stripTopLevelSpecifiers() }
|
||||
|
||||
override int getSize() { result = this.getBaseType().getSize() }
|
||||
|
||||
@@ -43,11 +43,11 @@ class TypedefType extends UserType {
|
||||
result = this.getBaseType().getASpecifier()
|
||||
}
|
||||
|
||||
override predicate involvesReference() { this.getBaseType().involvesReference() }
|
||||
override predicate involvesReference() { getBaseType().involvesReference() }
|
||||
|
||||
override Type resolveTypedefs() { result = this.getBaseType().resolveTypedefs() }
|
||||
override Type resolveTypedefs() { result = getBaseType().resolveTypedefs() }
|
||||
|
||||
override Type stripType() { result = this.getBaseType().stripType() }
|
||||
override Type stripType() { result = getBaseType().stripType() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,7 +90,7 @@ class UsingAliasTypedefType extends TypedefType {
|
||||
* ```
|
||||
*/
|
||||
class LocalTypedefType extends TypedefType {
|
||||
LocalTypedefType() { this.isLocal() }
|
||||
LocalTypedefType() { isLocal() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LocalTypedefType" }
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ class Union extends Struct {
|
||||
* ```
|
||||
*/
|
||||
class LocalUnion extends Union {
|
||||
LocalUnion() { this.isLocal() }
|
||||
LocalUnion() { isLocal() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LocalUnion" }
|
||||
}
|
||||
|
||||
@@ -30,19 +30,19 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @
|
||||
* Gets the simple name of this type, without any template parameters. For example
|
||||
* if the name of the type is `"myType<int>"`, the simple name is just `"myType"`.
|
||||
*/
|
||||
string getSimpleName() { result = this.getName().regexpReplaceAll("<.*", "") }
|
||||
string getSimpleName() { result = getName().regexpReplaceAll("<.*", "") }
|
||||
|
||||
override predicate hasName(string name) { usertypes(underlyingElement(this), name, _) }
|
||||
|
||||
/** Holds if this type is anonymous. */
|
||||
predicate isAnonymous() { this.getName().matches("(unnamed%") }
|
||||
predicate isAnonymous() { getName().matches("(unnamed%") }
|
||||
|
||||
override predicate hasSpecifier(string s) { Type.super.hasSpecifier(s) }
|
||||
|
||||
override Specifier getASpecifier() { result = Type.super.getASpecifier() }
|
||||
|
||||
override Location getLocation() {
|
||||
if this.hasDefinition()
|
||||
if hasDefinition()
|
||||
then result = this.getDefinitionLocation()
|
||||
else result = this.getADeclarationLocation()
|
||||
}
|
||||
@@ -53,16 +53,16 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @
|
||||
else exists(Class t | this.(Class).isConstructedFrom(t) and result = t.getADeclarationEntry())
|
||||
}
|
||||
|
||||
override Location getADeclarationLocation() { result = this.getADeclarationEntry().getLocation() }
|
||||
override Location getADeclarationLocation() { result = getADeclarationEntry().getLocation() }
|
||||
|
||||
override TypeDeclarationEntry getDefinition() {
|
||||
result = this.getADeclarationEntry() and
|
||||
result = getADeclarationEntry() and
|
||||
result.isDefinition()
|
||||
}
|
||||
|
||||
override Location getDefinitionLocation() {
|
||||
if exists(this.getDefinition())
|
||||
then result = this.getDefinition().getLocation()
|
||||
if exists(getDefinition())
|
||||
then result = getDefinition().getLocation()
|
||||
else
|
||||
exists(Class t |
|
||||
this.(Class).isConstructedFrom(t) and result = t.getDefinition().getLocation()
|
||||
@@ -80,7 +80,7 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @
|
||||
* Holds if this is a local type (that is, a type that has a directly-enclosing
|
||||
* function).
|
||||
*/
|
||||
predicate isLocal() { exists(this.getEnclosingFunction()) }
|
||||
predicate isLocal() { exists(getEnclosingFunction()) }
|
||||
|
||||
/*
|
||||
* Dummy implementations of inherited methods. This class must not be
|
||||
@@ -107,9 +107,9 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @
|
||||
* ```
|
||||
*/
|
||||
class TypeDeclarationEntry extends DeclarationEntry, @type_decl {
|
||||
override UserType getDeclaration() { result = this.getType() }
|
||||
override UserType getDeclaration() { result = getType() }
|
||||
|
||||
override string getName() { result = this.getType().getName() }
|
||||
override string getName() { result = getType().getName() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "TypeDeclarationEntry" }
|
||||
|
||||
|
||||
@@ -104,17 +104,17 @@ class Variable extends Declaration, @variable {
|
||||
|
||||
override VariableDeclarationEntry getADeclarationEntry() { result.getDeclaration() = this }
|
||||
|
||||
override Location getADeclarationLocation() { result = this.getADeclarationEntry().getLocation() }
|
||||
override Location getADeclarationLocation() { result = getADeclarationEntry().getLocation() }
|
||||
|
||||
override VariableDeclarationEntry getDefinition() {
|
||||
result = this.getADeclarationEntry() and
|
||||
result = getADeclarationEntry() and
|
||||
result.isDefinition()
|
||||
}
|
||||
|
||||
override Location getDefinitionLocation() { result = this.getDefinition().getLocation() }
|
||||
override Location getDefinitionLocation() { result = getDefinition().getLocation() }
|
||||
|
||||
override Location getLocation() {
|
||||
if exists(this.getDefinition())
|
||||
if exists(getDefinition())
|
||||
then result = this.getDefinitionLocation()
|
||||
else result = this.getADeclarationLocation()
|
||||
}
|
||||
@@ -199,7 +199,7 @@ class Variable extends Declaration, @variable {
|
||||
* ```
|
||||
*/
|
||||
class VariableDeclarationEntry extends DeclarationEntry, @var_decl {
|
||||
override Variable getDeclaration() { result = this.getVariable() }
|
||||
override Variable getDeclaration() { result = getVariable() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "VariableDeclarationEntry" }
|
||||
|
||||
@@ -276,33 +276,32 @@ class ParameterDeclarationEntry extends VariableDeclarationEntry {
|
||||
int getIndex() { param_decl_bind(underlyingElement(this), result, _) }
|
||||
|
||||
private string getAnonymousParameterDescription() {
|
||||
not exists(this.getName()) and
|
||||
not exists(getName()) and
|
||||
exists(string idx |
|
||||
idx =
|
||||
((this.getIndex() + 1).toString() + "th")
|
||||
((getIndex() + 1).toString() + "th")
|
||||
.replaceAll("1th", "1st")
|
||||
.replaceAll("2th", "2nd")
|
||||
.replaceAll("3th", "3rd")
|
||||
.replaceAll("11st", "11th")
|
||||
.replaceAll("12nd", "12th")
|
||||
.replaceAll("13rd", "13th") and
|
||||
if exists(this.getCanonicalName())
|
||||
then
|
||||
result = "declaration of " + this.getCanonicalName() + " as anonymous " + idx + " parameter"
|
||||
if exists(getCanonicalName())
|
||||
then result = "declaration of " + getCanonicalName() + " as anonymous " + idx + " parameter"
|
||||
else result = "declaration of " + idx + " parameter"
|
||||
)
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
this.isDefinition() and
|
||||
result = "definition of " + this.getName()
|
||||
isDefinition() and
|
||||
result = "definition of " + getName()
|
||||
or
|
||||
not this.isDefinition() and
|
||||
if this.getName() = this.getCanonicalName()
|
||||
then result = "declaration of " + this.getName()
|
||||
else result = "declaration of " + this.getCanonicalName() + " as " + this.getName()
|
||||
not isDefinition() and
|
||||
if getName() = getCanonicalName()
|
||||
then result = "declaration of " + getName()
|
||||
else result = "declaration of " + getCanonicalName() + " as " + getName()
|
||||
or
|
||||
result = this.getAnonymousParameterDescription()
|
||||
result = getAnonymousParameterDescription()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -312,12 +311,8 @@ class ParameterDeclarationEntry extends VariableDeclarationEntry {
|
||||
*/
|
||||
string getTypedName() {
|
||||
exists(string typeString, string nameString |
|
||||
(
|
||||
if exists(this.getType().getName())
|
||||
then typeString = this.getType().getName()
|
||||
else typeString = ""
|
||||
) and
|
||||
(if exists(this.getName()) then nameString = this.getName() else nameString = "") and
|
||||
(if exists(getType().getName()) then typeString = getType().getName() else typeString = "") and
|
||||
(if exists(getName()) then nameString = getName() else nameString = "") and
|
||||
if typeString != "" and nameString != ""
|
||||
then result = typeString + " " + nameString
|
||||
else result = typeString + nameString
|
||||
@@ -545,7 +540,7 @@ class MemberVariable extends Variable, @membervariable {
|
||||
}
|
||||
|
||||
/** Holds if this member is mutable. */
|
||||
predicate isMutable() { this.getADeclarationEntry().hasSpecifier("mutable") }
|
||||
predicate isMutable() { getADeclarationEntry().hasSpecifier("mutable") }
|
||||
|
||||
private Type getAType() { membervariables(underlyingElement(this), unresolveElement(result), _) }
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ class XMLLocatable extends @xmllocatable, TXMLLocatable {
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
@@ -108,7 +108,7 @@ class XMLParent extends @xmlparent {
|
||||
}
|
||||
|
||||
/** Gets the text value contained in this XML parent. */
|
||||
string getTextValue() { result = this.allCharactersString() }
|
||||
string getTextValue() { result = allCharactersString() }
|
||||
|
||||
/** Gets a printable representation of this XML parent. */
|
||||
string toString() { result = this.getName() }
|
||||
@@ -119,7 +119,7 @@ class XMLFile extends XMLParent, File {
|
||||
XMLFile() { xmlEncoding(this, _) }
|
||||
|
||||
/** Gets a printable representation of this XML file. */
|
||||
override string toString() { result = this.getName() }
|
||||
override string toString() { result = getName() }
|
||||
|
||||
/** Gets the name of this XML file. */
|
||||
override string getName() { result = File.super.getAbsolutePath() }
|
||||
@@ -129,14 +129,14 @@ class XMLFile extends XMLParent, File {
|
||||
*
|
||||
* Gets the path of this XML file.
|
||||
*/
|
||||
deprecated string getPath() { result = this.getAbsolutePath() }
|
||||
deprecated string getPath() { result = getAbsolutePath() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getParentContainer().getAbsolutePath()` instead.
|
||||
*
|
||||
* Gets the path of the folder that contains this XML file.
|
||||
*/
|
||||
deprecated string getFolder() { result = this.getParentContainer().getAbsolutePath() }
|
||||
deprecated string getFolder() { result = getParentContainer().getAbsolutePath() }
|
||||
|
||||
/** Gets the encoding of this XML file. */
|
||||
string getEncoding() { xmlEncoding(this, result) }
|
||||
@@ -200,7 +200,7 @@ class XMLDTD extends XMLLocatable, @xmldtd {
|
||||
*/
|
||||
class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
|
||||
/** Holds if this XML element has the given `name`. */
|
||||
predicate hasName(string name) { name = this.getName() }
|
||||
predicate hasName(string name) { name = getName() }
|
||||
|
||||
/** Gets the name of this XML element. */
|
||||
override string getName() { xmlElements(this, result, _, _, _) }
|
||||
@@ -239,7 +239,7 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
|
||||
string getAttributeValue(string name) { result = this.getAttribute(name).getValue() }
|
||||
|
||||
/** Gets a printable representation of this XML element. */
|
||||
override string toString() { result = this.getName() }
|
||||
override string toString() { result = getName() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -375,8 +375,8 @@ class Wchar_t extends Type {
|
||||
class MicrosoftInt8Type extends IntegralType {
|
||||
MicrosoftInt8Type() {
|
||||
this instanceof CharType and
|
||||
not this.isExplicitlyUnsigned() and
|
||||
not this.isExplicitlySigned()
|
||||
not isExplicitlyUnsigned() and
|
||||
not isExplicitlySigned()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -391,8 +391,8 @@ class MicrosoftInt8Type extends IntegralType {
|
||||
class MicrosoftInt16Type extends IntegralType {
|
||||
MicrosoftInt16Type() {
|
||||
this instanceof ShortType and
|
||||
not this.isExplicitlyUnsigned() and
|
||||
not this.isExplicitlySigned()
|
||||
not isExplicitlyUnsigned() and
|
||||
not isExplicitlySigned()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -407,8 +407,8 @@ class MicrosoftInt16Type extends IntegralType {
|
||||
class MicrosoftInt32Type extends IntegralType {
|
||||
MicrosoftInt32Type() {
|
||||
this instanceof IntType and
|
||||
not this.isExplicitlyUnsigned() and
|
||||
not this.isExplicitlySigned()
|
||||
not isExplicitlyUnsigned() and
|
||||
not isExplicitlySigned()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -423,8 +423,8 @@ class MicrosoftInt32Type extends IntegralType {
|
||||
class MicrosoftInt64Type extends IntegralType {
|
||||
MicrosoftInt64Type() {
|
||||
this instanceof LongLongType and
|
||||
not this.isExplicitlyUnsigned() and
|
||||
not this.isExplicitlySigned()
|
||||
not isExplicitlyUnsigned() and
|
||||
not isExplicitlySigned()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ DependencyOptions getDependencyOptions() { any() }
|
||||
class DependsSource extends Element {
|
||||
DependsSource() {
|
||||
// not inside a template instantiation
|
||||
not exists(Element other | this.isFromTemplateInstantiation(other)) or
|
||||
not exists(Element other | isFromTemplateInstantiation(other)) or
|
||||
// allow DeclarationEntrys of template specializations
|
||||
this.(DeclarationEntry).getDeclaration().(Function).isConstructedFrom(_) or
|
||||
this.(DeclarationEntry).getDeclaration().(Class).isConstructedFrom(_)
|
||||
@@ -275,7 +275,7 @@ private predicate dependsOnDeclarationEntry(Element src, DeclarationEntry dest)
|
||||
dependsOnTransitive(src, mid) and
|
||||
not mid instanceof Type and
|
||||
not mid instanceof EnumConstant and
|
||||
getDeclarationEntries(mid, dest) and
|
||||
getDeclarationEntries(mid, dest.(DeclarationEntry)) and
|
||||
not dest instanceof TypeDeclarationEntry
|
||||
)
|
||||
or
|
||||
@@ -283,9 +283,9 @@ private predicate dependsOnDeclarationEntry(Element src, DeclarationEntry dest)
|
||||
// dependency from a Type / Variable / Function use -> any (visible) definition
|
||||
dependsOnTransitive(src, mid) and
|
||||
not mid instanceof EnumConstant and
|
||||
getDeclarationEntries(mid, dest) and
|
||||
getDeclarationEntries(mid, dest.(DeclarationEntry)) and
|
||||
// must be definition
|
||||
dest.isDefinition()
|
||||
dest.(DeclarationEntry).isDefinition()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -307,7 +307,7 @@ private predicate dependsOnFull(DependsSource src, Symbol dest, int category) {
|
||||
// dependency from a Variable / Function use -> non-visible definition (link time)
|
||||
dependsOnTransitive(src, mid) and
|
||||
not mid instanceof EnumConstant and
|
||||
getDeclarationEntries(mid, dest) and
|
||||
getDeclarationEntries(mid, dest.(DeclarationEntry)) and
|
||||
not dest instanceof TypeDeclarationEntry and
|
||||
// must be definition
|
||||
dest.(DeclarationEntry).isDefinition() and
|
||||
|
||||
@@ -81,8 +81,8 @@ predicate functionContainsPreprocCode(Function f) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e` is completely or partially from a macro invocation `mi`, as
|
||||
* opposed to being passed in as an argument.
|
||||
* Holds if `e` is completely or partially from a macro definition, as opposed
|
||||
* to being passed in as an argument.
|
||||
*
|
||||
* In the following example, the call to `f` is from a macro definition,
|
||||
* while `y`, `+`, `1`, and `;` are not. This assumes that no identifier apart
|
||||
@@ -93,8 +93,8 @@ predicate functionContainsPreprocCode(Function f) {
|
||||
* M(y + 1);
|
||||
* ```
|
||||
*/
|
||||
private predicate isFromMacroInvocation(Element e, MacroInvocation mi) {
|
||||
exists(Location eLocation, Location miLocation |
|
||||
predicate isFromMacroDefinition(Element e) {
|
||||
exists(MacroInvocation mi, Location eLocation, Location miLocation |
|
||||
mi.getAnExpandedElement() = e and
|
||||
eLocation = e.getLocation() and
|
||||
miLocation = mi.getLocation() and
|
||||
@@ -109,36 +109,3 @@ private predicate isFromMacroInvocation(Element e, MacroInvocation mi) {
|
||||
eLocation.getEndColumn() >= miLocation.getEndColumn()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e` is completely or partially from a macro definition, as opposed
|
||||
* to being passed in as an argument.
|
||||
*
|
||||
* In the following example, the call to `f` is from a macro definition,
|
||||
* while `y`, `+`, `1`, and `;` are not. This assumes that no identifier apart
|
||||
* from `M` refers to a macro.
|
||||
* ```
|
||||
* #define M(x) f(x)
|
||||
* ...
|
||||
* M(y + 1);
|
||||
* ```
|
||||
*/
|
||||
predicate isFromMacroDefinition(Element e) { isFromMacroInvocation(e, _) }
|
||||
|
||||
/**
|
||||
* Holds if `e` is completely or partially from a _system macro_ definition, as
|
||||
* opposed to being passed in as an argument. A system macro is a macro whose
|
||||
* definition is outside the source directory of the database.
|
||||
*
|
||||
* If the system macro is invoked through a non-system macro, then this
|
||||
* predicate does not hold.
|
||||
*
|
||||
* See also `isFromMacroDefinition`.
|
||||
*/
|
||||
predicate isFromSystemMacroDefinition(Element e) {
|
||||
exists(MacroInvocation mi |
|
||||
isFromMacroInvocation(e, mi) and
|
||||
// Has no relative path in the database, meaning it's a system file.
|
||||
not exists(mi.getMacro().getFile().getRelativePath())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,35 +1,18 @@
|
||||
import cpp
|
||||
private import semmle.code.cpp.models.interfaces.ArrayFunction
|
||||
private import semmle.code.cpp.models.implementations.Strcat
|
||||
import semmle.code.cpp.dataflow.DataFlow
|
||||
|
||||
/**
|
||||
* Holds if the expression `e` assigns something including `va` to a
|
||||
* stack variable `v0`.
|
||||
*/
|
||||
private predicate mayAddNullTerminatorHelper(Expr e, VariableAccess va, StackVariable v0) {
|
||||
exists(Expr val |
|
||||
exprDefinition(v0, e, val) and // `e` is `v0 := val`
|
||||
val.getAChild*() = va
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[n1, n2]
|
||||
private predicate controlFlowNodeSuccessorTransitive(ControlFlowNode n1, ControlFlowNode n2) {
|
||||
exists(BasicBlock bb1, int pos1, BasicBlock bb2, int pos2 |
|
||||
pragma[only_bind_into](bb1).getNode(pos1) = n1 and
|
||||
pragma[only_bind_into](bb2).getNode(pos2) = n2 and
|
||||
(
|
||||
bb1 = bb2 and pos1 < pos2
|
||||
or
|
||||
bb1.getASuccessor+() = bb2
|
||||
)
|
||||
private predicate mayAddNullTerminatorHelper(Expr e, VariableAccess va, Expr e0) {
|
||||
exists(StackVariable v0, Expr val |
|
||||
exprDefinition(v0, e, val) and
|
||||
val.getAChild*() = va and
|
||||
mayAddNullTerminator(e0, v0.getAnAccess())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the expression `e` may add a null terminator to the string
|
||||
* accessed by `va`.
|
||||
* Holds if the expression `e` may add a null terminator to the string in
|
||||
* variable `v`.
|
||||
*/
|
||||
predicate mayAddNullTerminator(Expr e, VariableAccess va) {
|
||||
// Assignment: dereferencing or array access
|
||||
@@ -46,10 +29,14 @@ predicate mayAddNullTerminator(Expr e, VariableAccess va) {
|
||||
)
|
||||
or
|
||||
// Assignment to another stack variable
|
||||
exists(StackVariable v0, Expr e0 |
|
||||
mayAddNullTerminatorHelper(e, va, v0) and
|
||||
mayAddNullTerminator(pragma[only_bind_into](e0), pragma[only_bind_into](v0.getAnAccess())) and
|
||||
controlFlowNodeSuccessorTransitive(e, e0)
|
||||
exists(Expr e0, BasicBlock bb, int pos, BasicBlock bb0, int pos0 |
|
||||
mayAddNullTerminatorHelper(e, va, e0) and
|
||||
bb.getNode(pos) = e and
|
||||
bb0.getNode(pos0) = e0
|
||||
|
|
||||
bb = bb0 and pos < pos0
|
||||
or
|
||||
bb.getASuccessor+() = bb0
|
||||
)
|
||||
or
|
||||
// Assignment to non-stack variable
|
||||
@@ -58,28 +45,22 @@ predicate mayAddNullTerminator(Expr e, VariableAccess va) {
|
||||
ae.getRValue().getAChild*() = va
|
||||
)
|
||||
or
|
||||
// Function calls...
|
||||
// Function call: library function, varargs function, function
|
||||
// containing assembler code, or function where the relevant
|
||||
// parameter is potentially added a null terminator.
|
||||
exists(Call c, Function f, int i |
|
||||
e = c and
|
||||
f = c.getTarget() and
|
||||
not functionArgumentMustBeNullTerminated(f, i) and
|
||||
c.getAnArgumentSubExpr(i) = va
|
||||
|
|
||||
// library function
|
||||
not f.hasEntryPoint()
|
||||
not f.hasEntryPoint() and not functionArgumentMustBeNullTerminated(f, i)
|
||||
or
|
||||
// function where the relevant parameter is potentially added a null terminator
|
||||
mayAddNullTerminator(_, f.getParameter(i).getAnAccess())
|
||||
or
|
||||
// varargs function
|
||||
f.isVarargs() and i >= f.getNumberOfParameters()
|
||||
or
|
||||
// function containing assembler code
|
||||
exists(AsmStmt s | s.getEnclosingFunction() = f)
|
||||
or
|
||||
// function where the relevant parameter is returned (leaking it to be potentially null terminated elsewhere)
|
||||
DataFlow::localFlow(DataFlow::parameterNode(f.getParameter(i)),
|
||||
DataFlow::exprNode(any(ReturnStmt rs).getExpr()))
|
||||
)
|
||||
or
|
||||
// Call without target (e.g., function pointer call)
|
||||
@@ -131,9 +112,14 @@ predicate variableMustBeNullTerminated(VariableAccess va) {
|
||||
variableMustBeNullTerminated(use) and
|
||||
// Simplified: check that `p` may not be null terminated on *any*
|
||||
// path to `use` (including the one found via `parameterUsePair`)
|
||||
not exists(Expr e |
|
||||
mayAddNullTerminator(pragma[only_bind_into](e), p.getAnAccess()) and
|
||||
controlFlowNodeSuccessorTransitive(e, use)
|
||||
not exists(Expr e, BasicBlock bb1, int pos1, BasicBlock bb2, int pos2 |
|
||||
mayAddNullTerminator(e, p.getAnAccess()) and
|
||||
bb1.getNode(pos1) = e and
|
||||
bb2.getNode(pos2) = use
|
||||
|
|
||||
bb1 = bb2 and pos1 < pos2
|
||||
or
|
||||
bb1.getASuccessor+() = bb2
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -6,11 +6,9 @@ import semmle.code.cpp.Type
|
||||
import semmle.code.cpp.commons.CommonType
|
||||
import semmle.code.cpp.commons.StringAnalysis
|
||||
import semmle.code.cpp.models.interfaces.FormattingFunction
|
||||
private import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
|
||||
private import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
|
||||
|
||||
class PrintfFormatAttribute extends FormatAttribute {
|
||||
PrintfFormatAttribute() { this.getArchetype() = ["printf", "__printf__"] }
|
||||
PrintfFormatAttribute() { getArchetype() = ["printf", "__printf__"] }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -22,13 +20,13 @@ class AttributeFormattingFunction extends FormattingFunction {
|
||||
|
||||
AttributeFormattingFunction() {
|
||||
exists(PrintfFormatAttribute printf_attrib |
|
||||
printf_attrib = this.getAnAttribute() and
|
||||
printf_attrib = getAnAttribute() and
|
||||
exists(printf_attrib.getFirstFormatArgIndex()) // exclude `vprintf` style format functions
|
||||
)
|
||||
}
|
||||
|
||||
override int getFormatParameterIndex() {
|
||||
forex(PrintfFormatAttribute printf_attrib | printf_attrib = this.getAnAttribute() |
|
||||
forex(PrintfFormatAttribute printf_attrib | printf_attrib = getAnAttribute() |
|
||||
result = printf_attrib.getFormatIndex()
|
||||
)
|
||||
}
|
||||
@@ -134,7 +132,7 @@ deprecated predicate variadicFormatter(Function f, int formatParamIndex) {
|
||||
class UserDefinedFormattingFunction extends FormattingFunction {
|
||||
override string getAPrimaryQlClass() { result = "UserDefinedFormattingFunction" }
|
||||
|
||||
UserDefinedFormattingFunction() { this.isVarargs() and callsVariadicFormatter(this, _, _, _) }
|
||||
UserDefinedFormattingFunction() { isVarargs() and callsVariadicFormatter(this, _, _, _) }
|
||||
|
||||
override int getFormatParameterIndex() { callsVariadicFormatter(this, _, result, _) }
|
||||
|
||||
@@ -177,7 +175,9 @@ class FormattingFunctionCall extends Expr {
|
||||
/**
|
||||
* Gets the index at which the format string occurs in the argument list.
|
||||
*/
|
||||
int getFormatParameterIndex() { result = this.getTarget().getFormatParameterIndex() }
|
||||
int getFormatParameterIndex() {
|
||||
result = this.getTarget().(FormattingFunction).getFormatParameterIndex()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the format expression used in this call.
|
||||
@@ -191,7 +191,7 @@ class FormattingFunctionCall extends Expr {
|
||||
exists(int i |
|
||||
result = this.getArgument(i) and
|
||||
n >= 0 and
|
||||
n = i - this.getTarget().getFirstFormatArgumentIndex()
|
||||
n = i - getTarget().(FormattingFunction).getFirstFormatArgumentIndex()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -251,35 +251,8 @@ class FormattingFunctionCall extends Expr {
|
||||
int getNumFormatArgument() {
|
||||
result = count(this.getFormatArgument(_)) and
|
||||
// format arguments must be known
|
||||
exists(this.getTarget().getFirstFormatArgumentIndex())
|
||||
exists(getTarget().(FormattingFunction).getFirstFormatArgumentIndex())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the argument, if any, to which the output is written. If `isStream` is
|
||||
* `true`, the output argument is a stream (that is, this call behaves like
|
||||
* `fprintf`). If `isStream` is `false`, the output argument is a buffer (that
|
||||
* is, this call behaves like `sprintf`)
|
||||
*/
|
||||
Expr getOutputArgument(boolean isStream) {
|
||||
result =
|
||||
this.(Call)
|
||||
.getArgument(this.(Call)
|
||||
.getTarget()
|
||||
.(FormattingFunction)
|
||||
.getOutputParameterIndex(isStream))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of digits required to represent the integer represented by `f`.
|
||||
*
|
||||
* `f` is assumed to be nonnegative.
|
||||
*/
|
||||
bindingset[f]
|
||||
private int lengthInBase10(float f) {
|
||||
f = 0 and result = 1
|
||||
or
|
||||
result = f.log10().floor() + 1
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -301,27 +274,33 @@ class FormatLiteral extends Literal {
|
||||
* a `char *` (either way, `%S` will have the opposite meaning).
|
||||
* DEPRECATED: Use getDefaultCharType() instead.
|
||||
*/
|
||||
deprecated predicate isWideCharDefault() { this.getUse().getTarget().isWideCharDefault() }
|
||||
deprecated predicate isWideCharDefault() {
|
||||
getUse().getTarget().(FormattingFunction).isWideCharDefault()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default character type expected for `%s` by this format literal. Typically
|
||||
* `char` or `wchar_t`.
|
||||
*/
|
||||
Type getDefaultCharType() { result = this.getUse().getTarget().getDefaultCharType() }
|
||||
Type getDefaultCharType() {
|
||||
result = getUse().getTarget().(FormattingFunction).getDefaultCharType()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the non-default character type expected for `%S` by this format literal. Typically
|
||||
* `wchar_t` or `char`. On some snapshots there may be multiple results where we can't tell
|
||||
* which is correct for a particular function.
|
||||
*/
|
||||
Type getNonDefaultCharType() { result = this.getUse().getTarget().getNonDefaultCharType() }
|
||||
Type getNonDefaultCharType() {
|
||||
result = getUse().getTarget().(FormattingFunction).getNonDefaultCharType()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the wide character type for this format literal. This is usually `wchar_t`. On some
|
||||
* snapshots there may be multiple results where we can't tell which is correct for a
|
||||
* particular function.
|
||||
*/
|
||||
Type getWideCharType() { result = this.getUse().getTarget().getWideCharType() }
|
||||
Type getWideCharType() { result = getUse().getTarget().(FormattingFunction).getWideCharType() }
|
||||
|
||||
/**
|
||||
* Holds if this `FormatLiteral` is in a context that supports
|
||||
@@ -359,7 +338,7 @@ class FormatLiteral extends Literal {
|
||||
}
|
||||
|
||||
private string getFlagRegexp() {
|
||||
if this.isMicrosoft() then result = "[-+ #0']*" else result = "[-+ #0'I]*"
|
||||
if isMicrosoft() then result = "[-+ #0']*" else result = "[-+ #0'I]*"
|
||||
}
|
||||
|
||||
private string getFieldWidthRegexp() { result = "(?:[1-9][0-9]*|\\*|\\*[0-9]+\\$)?" }
|
||||
@@ -367,13 +346,13 @@ class FormatLiteral extends Literal {
|
||||
private string getPrecRegexp() { result = "(?:\\.(?:[0-9]*|\\*|\\*[0-9]+\\$))?" }
|
||||
|
||||
private string getLengthRegexp() {
|
||||
if this.isMicrosoft()
|
||||
if isMicrosoft()
|
||||
then result = "(?:hh?|ll?|L|q|j|z|t|w|I32|I64|I)?"
|
||||
else result = "(?:hh?|ll?|L|q|j|z|Z|t)?"
|
||||
}
|
||||
|
||||
private string getConvCharRegexp() {
|
||||
if this.isMicrosoft()
|
||||
if isMicrosoft()
|
||||
then result = "[aAcCdeEfFgGimnopsSuxXZ@]"
|
||||
else result = "[aAcCdeEfFgGimnopsSuxX@]"
|
||||
}
|
||||
@@ -753,16 +732,16 @@ class FormatLiteral extends Literal {
|
||||
* Gets the argument type required by the nth conversion specifier.
|
||||
*/
|
||||
Type getConversionType(int n) {
|
||||
result = this.getConversionType1(n) or
|
||||
result = this.getConversionType1b(n) or
|
||||
result = this.getConversionType2(n) or
|
||||
result = this.getConversionType3(n) or
|
||||
result = this.getConversionType4(n) or
|
||||
result = this.getConversionType6(n) or
|
||||
result = this.getConversionType7(n) or
|
||||
result = this.getConversionType8(n) or
|
||||
result = this.getConversionType9(n) or
|
||||
result = this.getConversionType10(n)
|
||||
result = getConversionType1(n) or
|
||||
result = getConversionType1b(n) or
|
||||
result = getConversionType2(n) or
|
||||
result = getConversionType3(n) or
|
||||
result = getConversionType4(n) or
|
||||
result = getConversionType6(n) or
|
||||
result = getConversionType7(n) or
|
||||
result = getConversionType8(n) or
|
||||
result = getConversionType9(n) or
|
||||
result = getConversionType10(n)
|
||||
}
|
||||
|
||||
private Type getConversionType1(int n) {
|
||||
@@ -792,15 +771,15 @@ class FormatLiteral extends Literal {
|
||||
or
|
||||
conv = ["c", "C"] and
|
||||
len = ["l", "w"] and
|
||||
result = this.getWideCharType()
|
||||
result = getWideCharType()
|
||||
or
|
||||
conv = "c" and
|
||||
(len != "l" and len != "w" and len != "h") and
|
||||
result = this.getDefaultCharType()
|
||||
result = getDefaultCharType()
|
||||
or
|
||||
conv = "C" and
|
||||
(len != "l" and len != "w" and len != "h") and
|
||||
result = this.getNonDefaultCharType()
|
||||
result = getNonDefaultCharType()
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -837,15 +816,15 @@ class FormatLiteral extends Literal {
|
||||
or
|
||||
conv = ["s", "S"] and
|
||||
len = ["l", "w"] and
|
||||
result.(PointerType).getBaseType() = this.getWideCharType()
|
||||
result.(PointerType).getBaseType() = getWideCharType()
|
||||
or
|
||||
conv = "s" and
|
||||
(len != "l" and len != "w" and len != "h") and
|
||||
result.(PointerType).getBaseType() = this.getDefaultCharType()
|
||||
result.(PointerType).getBaseType() = getDefaultCharType()
|
||||
or
|
||||
conv = "S" and
|
||||
(len != "l" and len != "w" and len != "h") and
|
||||
result.(PointerType).getBaseType() = this.getNonDefaultCharType()
|
||||
result.(PointerType).getBaseType() = getNonDefaultCharType()
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -900,19 +879,19 @@ class FormatLiteral extends Literal {
|
||||
exists(string len, string conv |
|
||||
this.parseConvSpec(n, _, _, _, _, _, len, conv) and
|
||||
(len != "l" and len != "w" and len != "h") and
|
||||
this.getUse().getTarget().getFormatCharType().getSize() > 1 and // wide function
|
||||
getUse().getTarget().(FormattingFunction).getFormatCharType().getSize() > 1 and // wide function
|
||||
(
|
||||
conv = "c" and
|
||||
result = this.getNonDefaultCharType()
|
||||
result = getNonDefaultCharType()
|
||||
or
|
||||
conv = "C" and
|
||||
result = this.getDefaultCharType()
|
||||
result = getDefaultCharType()
|
||||
or
|
||||
conv = "s" and
|
||||
result.(PointerType).getBaseType() = this.getNonDefaultCharType()
|
||||
result.(PointerType).getBaseType() = getNonDefaultCharType()
|
||||
or
|
||||
conv = "S" and
|
||||
result.(PointerType).getBaseType() = this.getDefaultCharType()
|
||||
result.(PointerType).getBaseType() = getDefaultCharType()
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -945,13 +924,9 @@ class FormatLiteral extends Literal {
|
||||
* not account for positional arguments (`$`).
|
||||
*/
|
||||
int getFormatArgumentIndexFor(int n, int mode) {
|
||||
this.hasFormatArgumentIndexFor(n, mode) and
|
||||
hasFormatArgumentIndexFor(n, mode) and
|
||||
(3 * n) + mode =
|
||||
rank[result + 1](int n2, int mode2 |
|
||||
this.hasFormatArgumentIndexFor(n2, mode2)
|
||||
|
|
||||
(3 * n2) + mode2
|
||||
)
|
||||
rank[result + 1](int n2, int mode2 | hasFormatArgumentIndexFor(n2, mode2) | (3 * n2) + mode2)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -961,7 +936,7 @@ class FormatLiteral extends Literal {
|
||||
int getNumArgNeeded(int n) {
|
||||
exists(this.getConvSpecOffset(n)) and
|
||||
exists(this.getConversionChar(n)) and
|
||||
result = count(int mode | this.hasFormatArgumentIndexFor(n, mode))
|
||||
result = count(int mode | hasFormatArgumentIndexFor(n, mode))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -973,7 +948,7 @@ class FormatLiteral extends Literal {
|
||||
// At least one conversion specifier has a parameter field, in which case,
|
||||
// they all should have.
|
||||
result = max(string s | this.getParameterField(_) = s + "$" | s.toInt())
|
||||
else result = count(int n, int mode | this.hasFormatArgumentIndexFor(n, mode))
|
||||
else result = count(int n, int mode | hasFormatArgumentIndexFor(n, mode))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1060,89 +1035,65 @@ class FormatLiteral extends Literal {
|
||||
or
|
||||
this.getConversionChar(n).toLowerCase() = ["d", "i"] and
|
||||
// e.g. -2^31 = "-2147483648"
|
||||
len =
|
||||
min(float cand |
|
||||
// The first case handles length sub-specifiers
|
||||
// Subtract one in the exponent because one bit is for the sign.
|
||||
// Add 1 to account for the possible sign in the output.
|
||||
cand = 1 + lengthInBase10(2.pow(this.getIntegralDisplayType(n).getSize() * 8 - 1))
|
||||
or
|
||||
// The second case uses range analysis to deduce a length that's shorter than the length
|
||||
// of the number -2^31.
|
||||
exists(Expr arg, float lower, float upper |
|
||||
arg = this.getUse().getConversionArgument(n) and
|
||||
lower = lowerBound(arg.getFullyConverted()) and
|
||||
upper = upperBound(arg.getFullyConverted())
|
||||
|
|
||||
cand =
|
||||
max(int cand0 |
|
||||
// Include the sign bit in the length if it can be negative
|
||||
(
|
||||
if lower < 0
|
||||
then cand0 = 1 + lengthInBase10(lower.abs())
|
||||
else cand0 = lengthInBase10(lower)
|
||||
)
|
||||
or
|
||||
(
|
||||
if upper < 0
|
||||
then cand0 = 1 + lengthInBase10(upper.abs())
|
||||
else cand0 = lengthInBase10(upper)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
exists(int sizeBits |
|
||||
sizeBits =
|
||||
min(int bits |
|
||||
bits = getIntegralDisplayType(n).getSize() * 8
|
||||
or
|
||||
exists(IntegralType t |
|
||||
t = getUse().getConversionArgument(n).getType().getUnderlyingType()
|
||||
|
|
||||
t.isSigned() and bits = t.getSize() * 8
|
||||
)
|
||||
) and
|
||||
len = 1 + ((sizeBits - 1) / 10.0.log2()).ceil()
|
||||
// this calculation is as %u (below) only we take out the sign bit (- 1) and allow a whole
|
||||
// character for it to be expressed as '-'.
|
||||
)
|
||||
or
|
||||
this.getConversionChar(n).toLowerCase() = "u" and
|
||||
// e.g. 2^32 - 1 = "4294967295"
|
||||
len =
|
||||
min(float cand |
|
||||
// The first case handles length sub-specifiers
|
||||
cand = 2.pow(this.getIntegralDisplayType(n).getSize() * 8)
|
||||
or
|
||||
// The second case uses range analysis to deduce a length that's shorter than
|
||||
// the length of the number 2^31 - 1.
|
||||
exists(Expr arg, float lower |
|
||||
arg = this.getUse().getConversionArgument(n) and
|
||||
lower = lowerBound(arg.getFullyConverted())
|
||||
|
|
||||
cand =
|
||||
max(float cand0 |
|
||||
// If lower can be negative we use `(unsigned)-1` as the candidate value.
|
||||
lower < 0 and
|
||||
cand0 = 2.pow(any(IntType t | t.isUnsigned()).getSize() * 8)
|
||||
or
|
||||
cand0 = upperBound(arg.getFullyConverted())
|
||||
)
|
||||
)
|
||||
|
|
||||
lengthInBase10(cand)
|
||||
)
|
||||
exists(int sizeBits |
|
||||
sizeBits =
|
||||
min(int bits |
|
||||
bits = getIntegralDisplayType(n).getSize() * 8
|
||||
or
|
||||
exists(IntegralType t |
|
||||
t = getUse().getConversionArgument(n).getType().getUnderlyingType()
|
||||
|
|
||||
t.isUnsigned() and bits = t.getSize() * 8
|
||||
)
|
||||
) and
|
||||
len = (sizeBits / 10.0.log2()).ceil()
|
||||
// convert the size from bits to decimal characters, and round up as you can't have
|
||||
// fractional characters (10.0.log2() is the number of bits expressed per decimal character)
|
||||
)
|
||||
or
|
||||
this.getConversionChar(n).toLowerCase() = "x" and
|
||||
// e.g. "12345678"
|
||||
exists(int sizeBytes, int baseLen |
|
||||
sizeBytes =
|
||||
min(int bytes |
|
||||
bytes = this.getIntegralDisplayType(n).getSize()
|
||||
bytes = getIntegralDisplayType(n).getSize()
|
||||
or
|
||||
exists(IntegralType t |
|
||||
t = this.getUse().getConversionArgument(n).getType().getUnderlyingType()
|
||||
t = getUse().getConversionArgument(n).getType().getUnderlyingType()
|
||||
|
|
||||
t.isUnsigned() and bytes = t.getSize()
|
||||
)
|
||||
) and
|
||||
baseLen = sizeBytes * 2 and
|
||||
(
|
||||
if this.hasAlternateFlag(n) then len = 2 + baseLen else len = baseLen // "0x"
|
||||
if hasAlternateFlag(n) then len = 2 + baseLen else len = baseLen // "0x"
|
||||
)
|
||||
)
|
||||
or
|
||||
this.getConversionChar(n).toLowerCase() = "p" and
|
||||
exists(PointerType ptrType, int baseLen |
|
||||
ptrType = this.getFullyConverted().getType() and
|
||||
ptrType = getFullyConverted().getType() and
|
||||
baseLen = max(ptrType.getSize() * 2) and // e.g. "0x1234567812345678"; exact format is platform dependent
|
||||
(
|
||||
if this.hasAlternateFlag(n) then len = 2 + baseLen else len = baseLen // "0x"
|
||||
if hasAlternateFlag(n) then len = 2 + baseLen else len = baseLen // "0x"
|
||||
)
|
||||
)
|
||||
or
|
||||
@@ -1151,17 +1102,17 @@ class FormatLiteral extends Literal {
|
||||
exists(int sizeBits, int baseLen |
|
||||
sizeBits =
|
||||
min(int bits |
|
||||
bits = this.getIntegralDisplayType(n).getSize() * 8
|
||||
bits = getIntegralDisplayType(n).getSize() * 8
|
||||
or
|
||||
exists(IntegralType t |
|
||||
t = this.getUse().getConversionArgument(n).getType().getUnderlyingType()
|
||||
t = getUse().getConversionArgument(n).getType().getUnderlyingType()
|
||||
|
|
||||
t.isUnsigned() and bits = t.getSize() * 8
|
||||
)
|
||||
) and
|
||||
baseLen = (sizeBits / 3.0).ceil() and
|
||||
(
|
||||
if this.hasAlternateFlag(n) then len = 1 + baseLen else len = baseLen // "0"
|
||||
if hasAlternateFlag(n) then len = 1 + baseLen else len = baseLen // "0"
|
||||
)
|
||||
)
|
||||
or
|
||||
@@ -1184,8 +1135,8 @@ class FormatLiteral extends Literal {
|
||||
*/
|
||||
int getMaxConvertedLengthLimited(int n) {
|
||||
if this.getConversionChar(n).toLowerCase() = "f"
|
||||
then result = this.getMaxConvertedLength(n).minimum(8)
|
||||
else result = this.getMaxConvertedLength(n)
|
||||
then result = getMaxConvertedLength(n).minimum(8)
|
||||
else result = getMaxConvertedLength(n)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,7 +24,7 @@ abstract class ScanfFunction extends Function {
|
||||
* Holds if the default meaning of `%s` is a `wchar_t*` string
|
||||
* (rather than a `char*`).
|
||||
*/
|
||||
predicate isWideCharDefault() { exists(this.getName().indexOf("wscanf")) }
|
||||
predicate isWideCharDefault() { exists(getName().indexOf("wscanf")) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -34,10 +34,10 @@ class Scanf extends ScanfFunction {
|
||||
Scanf() {
|
||||
this instanceof TopLevelFunction and
|
||||
(
|
||||
this.hasGlobalOrStdOrBslName("scanf") or // scanf(format, args...)
|
||||
this.hasGlobalOrStdOrBslName("wscanf") or // wscanf(format, args...)
|
||||
this.hasGlobalName("_scanf_l") or // _scanf_l(format, locale, args...)
|
||||
this.hasGlobalName("_wscanf_l") // _wscanf_l(format, locale, args...)
|
||||
hasGlobalOrStdOrBslName("scanf") or // scanf(format, args...)
|
||||
hasGlobalOrStdOrBslName("wscanf") or // wscanf(format, args...)
|
||||
hasGlobalName("_scanf_l") or // _scanf_l(format, locale, args...)
|
||||
hasGlobalName("_wscanf_l") // _wscanf_l(format, locale, args...)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -53,10 +53,10 @@ class Fscanf extends ScanfFunction {
|
||||
Fscanf() {
|
||||
this instanceof TopLevelFunction and
|
||||
(
|
||||
this.hasGlobalOrStdOrBslName("fscanf") or // fscanf(src_stream, format, args...)
|
||||
this.hasGlobalOrStdOrBslName("fwscanf") or // fwscanf(src_stream, format, args...)
|
||||
this.hasGlobalName("_fscanf_l") or // _fscanf_l(src_stream, format, locale, args...)
|
||||
this.hasGlobalName("_fwscanf_l") // _fwscanf_l(src_stream, format, locale, args...)
|
||||
hasGlobalOrStdOrBslName("fscanf") or // fscanf(src_stream, format, args...)
|
||||
hasGlobalOrStdOrBslName("fwscanf") or // fwscanf(src_stream, format, args...)
|
||||
hasGlobalName("_fscanf_l") or // _fscanf_l(src_stream, format, locale, args...)
|
||||
hasGlobalName("_fwscanf_l") // _fwscanf_l(src_stream, format, locale, args...)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -72,10 +72,10 @@ class Sscanf extends ScanfFunction {
|
||||
Sscanf() {
|
||||
this instanceof TopLevelFunction and
|
||||
(
|
||||
this.hasGlobalOrStdOrBslName("sscanf") or // sscanf(src_stream, format, args...)
|
||||
this.hasGlobalOrStdOrBslName("swscanf") or // swscanf(src, format, args...)
|
||||
this.hasGlobalName("_sscanf_l") or // _sscanf_l(src, format, locale, args...)
|
||||
this.hasGlobalName("_swscanf_l") // _swscanf_l(src, format, locale, args...)
|
||||
hasGlobalOrStdOrBslName("sscanf") or // sscanf(src_stream, format, args...)
|
||||
hasGlobalOrStdOrBslName("swscanf") or // swscanf(src, format, args...)
|
||||
hasGlobalName("_sscanf_l") or // _sscanf_l(src, format, locale, args...)
|
||||
hasGlobalName("_swscanf_l") // _swscanf_l(src, format, locale, args...)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -91,10 +91,10 @@ class Snscanf extends ScanfFunction {
|
||||
Snscanf() {
|
||||
this instanceof TopLevelFunction and
|
||||
(
|
||||
this.hasGlobalName("_snscanf") or // _snscanf(src, max_amount, format, args...)
|
||||
this.hasGlobalName("_snwscanf") or // _snwscanf(src, max_amount, format, args...)
|
||||
this.hasGlobalName("_snscanf_l") or // _snscanf_l(src, max_amount, format, locale, args...)
|
||||
this.hasGlobalName("_snwscanf_l") // _snwscanf_l(src, max_amount, format, locale, args...)
|
||||
hasGlobalName("_snscanf") or // _snscanf(src, max_amount, format, args...)
|
||||
hasGlobalName("_snwscanf") or // _snwscanf(src, max_amount, format, args...)
|
||||
hasGlobalName("_snscanf_l") or // _snscanf_l(src, max_amount, format, locale, args...)
|
||||
hasGlobalName("_snwscanf_l") // _snwscanf_l(src, max_amount, format, locale, args...)
|
||||
// note that the max_amount is not a limit on the output length, it's an input length
|
||||
// limit used with non null-terminated strings.
|
||||
)
|
||||
@@ -120,18 +120,18 @@ class ScanfFunctionCall extends FunctionCall {
|
||||
/**
|
||||
* Gets the `scanf`-like function that is called.
|
||||
*/
|
||||
ScanfFunction getScanfFunction() { result = this.getTarget() }
|
||||
ScanfFunction getScanfFunction() { result = getTarget() }
|
||||
|
||||
/**
|
||||
* Gets the position at which the input string or stream parameter occurs,
|
||||
* if this function call does not read from standard input.
|
||||
*/
|
||||
int getInputParameterIndex() { result = this.getScanfFunction().getInputParameterIndex() }
|
||||
int getInputParameterIndex() { result = getScanfFunction().getInputParameterIndex() }
|
||||
|
||||
/**
|
||||
* Gets the position at which the format parameter occurs.
|
||||
*/
|
||||
int getFormatParameterIndex() { result = this.getScanfFunction().getFormatParameterIndex() }
|
||||
int getFormatParameterIndex() { result = getScanfFunction().getFormatParameterIndex() }
|
||||
|
||||
/**
|
||||
* Gets the format expression used in this call.
|
||||
@@ -142,7 +142,7 @@ class ScanfFunctionCall extends FunctionCall {
|
||||
* Holds if the default meaning of `%s` is a `wchar_t*` string
|
||||
* (rather than a `char*`).
|
||||
*/
|
||||
predicate isWideCharDefault() { this.getScanfFunction().isWideCharDefault() }
|
||||
predicate isWideCharDefault() { getScanfFunction().isWideCharDefault() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,7 +158,7 @@ class ScanfFormatLiteral extends Expr {
|
||||
ScanfFunctionCall getUse() { result.getFormat() = this }
|
||||
|
||||
/** Holds if the default meaning of `%s` is a `wchar_t*` (rather than a `char*`). */
|
||||
predicate isWideCharDefault() { this.getUse().getTarget().(ScanfFunction).isWideCharDefault() }
|
||||
predicate isWideCharDefault() { getUse().getTarget().(ScanfFunction).isWideCharDefault() }
|
||||
|
||||
/**
|
||||
* Gets the format string itself, transformed as follows:
|
||||
|
||||
@@ -40,8 +40,8 @@ abstract class MutexType extends Type {
|
||||
* Gets a call that locks or tries to lock any mutex of this type.
|
||||
*/
|
||||
FunctionCall getLockAccess() {
|
||||
result = this.getMustlockAccess() or
|
||||
result = this.getTrylockAccess()
|
||||
result = getMustlockAccess() or
|
||||
result = getTrylockAccess()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,22 +63,22 @@ abstract class MutexType extends Type {
|
||||
/**
|
||||
* DEPRECATED: use mustlockAccess(fc, arg) instead.
|
||||
*/
|
||||
deprecated Function getMustlockFunction() { result = this.getMustlockAccess().getTarget() }
|
||||
deprecated Function getMustlockFunction() { result = getMustlockAccess().getTarget() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: use trylockAccess(fc, arg) instead.
|
||||
*/
|
||||
deprecated Function getTrylockFunction() { result = this.getTrylockAccess().getTarget() }
|
||||
deprecated Function getTrylockFunction() { result = getTrylockAccess().getTarget() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: use lockAccess(fc, arg) instead.
|
||||
*/
|
||||
deprecated Function getLockFunction() { result = this.getLockAccess().getTarget() }
|
||||
deprecated Function getLockFunction() { result = getLockAccess().getTarget() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: use unlockAccess(fc, arg) instead.
|
||||
*/
|
||||
deprecated Function getUnlockFunction() { result = this.getUnlockAccess().getTarget() }
|
||||
deprecated Function getUnlockFunction() { result = getUnlockAccess().getTarget() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,17 +155,17 @@ class DefaultMutexType extends MutexType {
|
||||
|
||||
override predicate mustlockAccess(FunctionCall fc, Expr arg) {
|
||||
fc.getTarget() = mustlockCandidate() and
|
||||
this.lockArgType(fc, arg)
|
||||
lockArgType(fc, arg)
|
||||
}
|
||||
|
||||
override predicate trylockAccess(FunctionCall fc, Expr arg) {
|
||||
fc.getTarget() = trylockCandidate() and
|
||||
this.lockArgType(fc, arg)
|
||||
lockArgType(fc, arg)
|
||||
}
|
||||
|
||||
override predicate unlockAccess(FunctionCall fc, Expr arg) {
|
||||
fc.getTarget() = unlockCandidate() and
|
||||
this.lockArgType(fc, arg)
|
||||
lockArgType(fc, arg)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -194,14 +194,14 @@ class BasicBlock extends ControlFlowNodeBase {
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*
|
||||
* Yields no result if this basic block spans multiple source files.
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
this.hasLocationInfoInternal(filepath, startline, startcolumn, filepath, endline, endcolumn)
|
||||
hasLocationInfoInternal(filepath, startline, startcolumn, filepath, endline, endcolumn)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
@@ -276,7 +276,7 @@ class EntryBasicBlock extends BasicBlock {
|
||||
*/
|
||||
class ExitBasicBlock extends BasicBlock {
|
||||
ExitBasicBlock() {
|
||||
this.getEnd() instanceof Function or
|
||||
aborting(this.getEnd())
|
||||
getEnd() instanceof Function or
|
||||
aborting(getEnd())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ class ControlFlowNode extends Locatable, ControlFlowNodeBase {
|
||||
*/
|
||||
ControlFlowNode getATrueSuccessor() {
|
||||
qlCFGTrueSuccessor(this, result) and
|
||||
result = this.getASuccessor()
|
||||
result = getASuccessor()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,7 +75,7 @@ class ControlFlowNode extends Locatable, ControlFlowNodeBase {
|
||||
*/
|
||||
ControlFlowNode getAFalseSuccessor() {
|
||||
qlCFGFalseSuccessor(this, result) and
|
||||
result = this.getASuccessor()
|
||||
result = getASuccessor()
|
||||
}
|
||||
|
||||
/** Gets the `BasicBlock` containing this control-flow node. */
|
||||
|
||||
@@ -25,7 +25,7 @@ predicate definitionUsePair(SemanticStackVariable var, Expr def, Expr use) {
|
||||
* Holds if the definition `def` of some stack variable can reach `node`, which
|
||||
* is a definition or use, without crossing definitions of the same variable.
|
||||
*/
|
||||
predicate definitionReaches(Expr def, Expr node) { def.(Def).reaches(true, _, node) }
|
||||
predicate definitionReaches(Expr def, Expr node) { def.(Def).reaches(true, _, node.(DefOrUse)) }
|
||||
|
||||
private predicate hasAddressOfAccess(SemanticStackVariable var) {
|
||||
var.getAnAccess().isAddressOfAccessNonConst()
|
||||
|
||||
@@ -121,7 +121,7 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition {
|
||||
|
||||
override predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) {
|
||||
exists(boolean testIsTrue |
|
||||
this.comparesLt(left, right, k, isLessThan, testIsTrue) and this.controls(block, testIsTrue)
|
||||
comparesLt(left, right, k, isLessThan, testIsTrue) and this.controls(block, testIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition {
|
||||
|
||||
override predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) {
|
||||
exists(boolean testIsTrue |
|
||||
this.comparesEq(left, right, k, areEqual, testIsTrue) and this.controls(block, testIsTrue)
|
||||
comparesEq(left, right, k, areEqual, testIsTrue) and this.controls(block, testIsTrue)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -147,29 +147,27 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition {
|
||||
private class GuardConditionFromShortCircuitNot extends GuardCondition, NotExpr {
|
||||
GuardConditionFromShortCircuitNot() {
|
||||
not exists(Instruction inst | this.getFullyConverted() = inst.getAST()) and
|
||||
exists(IRGuardCondition ir | this.getOperand() = ir.getAST())
|
||||
exists(IRGuardCondition ir | getOperand() = ir.getAST())
|
||||
}
|
||||
|
||||
override predicate controls(BasicBlock controlled, boolean testIsTrue) {
|
||||
this.getOperand().(GuardCondition).controls(controlled, testIsTrue.booleanNot())
|
||||
getOperand().(GuardCondition).controls(controlled, testIsTrue.booleanNot())
|
||||
}
|
||||
|
||||
override predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) {
|
||||
this.getOperand()
|
||||
.(GuardCondition)
|
||||
.comparesLt(left, right, k, isLessThan, testIsTrue.booleanNot())
|
||||
getOperand().(GuardCondition).comparesLt(left, right, k, isLessThan, testIsTrue.booleanNot())
|
||||
}
|
||||
|
||||
override predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) {
|
||||
this.getOperand().(GuardCondition).ensuresLt(left, right, k, block, isLessThan.booleanNot())
|
||||
getOperand().(GuardCondition).ensuresLt(left, right, k, block, isLessThan.booleanNot())
|
||||
}
|
||||
|
||||
override predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) {
|
||||
this.getOperand().(GuardCondition).comparesEq(left, right, k, areEqual, testIsTrue.booleanNot())
|
||||
getOperand().(GuardCondition).comparesEq(left, right, k, areEqual, testIsTrue.booleanNot())
|
||||
}
|
||||
|
||||
override predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) {
|
||||
this.getOperand().(GuardCondition).ensuresEq(left, right, k, block, areEqual.booleanNot())
|
||||
getOperand().(GuardCondition).ensuresEq(left, right, k, block, areEqual.booleanNot())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,9 +303,9 @@ class IRGuardCondition extends Instruction {
|
||||
cached
|
||||
predicate controlsEdge(IRBlock pred, IRBlock succ, boolean testIsTrue) {
|
||||
pred.getASuccessor() = succ and
|
||||
this.controls(pred, testIsTrue)
|
||||
controls(pred, testIsTrue)
|
||||
or
|
||||
succ = this.getBranchSuccessor(testIsTrue) and
|
||||
succ = getBranchSuccessor(testIsTrue) and
|
||||
branch.getCondition() = this and
|
||||
branch.getBlock() = pred
|
||||
}
|
||||
|
||||
@@ -73,19 +73,19 @@ abstract deprecated class LocalScopeVariableReachability extends string {
|
||||
*/
|
||||
|
||||
exists(BasicBlock bb, int i |
|
||||
this.isSource(source, v) and
|
||||
isSource(source, v) and
|
||||
bb.getNode(i) = source and
|
||||
not bb.isUnreachable()
|
||||
|
|
||||
exists(int j |
|
||||
j > i and
|
||||
sink = bb.getNode(j) and
|
||||
this.isSink(sink, v) and
|
||||
not exists(int k | this.isBarrier(bb.getNode(k), v) | k in [i + 1 .. j - 1])
|
||||
isSink(sink, v) and
|
||||
not exists(int k | isBarrier(bb.getNode(k), v) | k in [i + 1 .. j - 1])
|
||||
)
|
||||
or
|
||||
not exists(int k | this.isBarrier(bb.getNode(k), v) | k > i) and
|
||||
this.bbSuccessorEntryReaches(bb, v, sink, _)
|
||||
not exists(int k | isBarrier(bb.getNode(k), v) | k > i) and
|
||||
bbSuccessorEntryReaches(bb, v, sink, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -97,11 +97,11 @@ abstract deprecated class LocalScopeVariableReachability extends string {
|
||||
bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
|
||||
succSkipsFirstLoopAlwaysTrueUponEntry)
|
||||
|
|
||||
this.bbEntryReachesLocally(succ, v, node) and
|
||||
bbEntryReachesLocally(succ, v, node) and
|
||||
succSkipsFirstLoopAlwaysTrueUponEntry = false
|
||||
or
|
||||
not this.isBarrier(succ.getNode(_), v) and
|
||||
this.bbSuccessorEntryReaches(succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
|
||||
not isBarrier(succ.getNode(_), v) and
|
||||
bbSuccessorEntryReaches(succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ abstract deprecated class LocalScopeVariableReachability extends string {
|
||||
) {
|
||||
exists(int n |
|
||||
node = bb.getNode(n) and
|
||||
this.isSink(node, v)
|
||||
isSink(node, v)
|
||||
|
|
||||
not exists(this.firstBarrierIndexIn(bb, v))
|
||||
or
|
||||
@@ -119,7 +119,7 @@ abstract deprecated class LocalScopeVariableReachability extends string {
|
||||
}
|
||||
|
||||
private int firstBarrierIndexIn(BasicBlock bb, SemanticStackVariable v) {
|
||||
result = min(int m | this.isBarrier(bb.getNode(m), v))
|
||||
result = min(int m | isBarrier(bb.getNode(m), v))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,7 +271,7 @@ abstract deprecated class LocalScopeVariableReachabilityWithReassignment extends
|
||||
* accounts for loops where the condition is provably true upon entry.
|
||||
*/
|
||||
override predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
|
||||
this.reachesTo(source, v, sink, _)
|
||||
reachesTo(source, v, sink, _)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -281,21 +281,21 @@ abstract deprecated class LocalScopeVariableReachabilityWithReassignment extends
|
||||
ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink, SemanticStackVariable v0
|
||||
) {
|
||||
exists(ControlFlowNode def |
|
||||
this.actualSourceReaches(source, v, def, v0) and
|
||||
actualSourceReaches(source, v, def, v0) and
|
||||
LocalScopeVariableReachability.super.reaches(def, v0, sink) and
|
||||
this.isSinkActual(sink, v0)
|
||||
isSinkActual(sink, v0)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate actualSourceReaches(
|
||||
ControlFlowNode source, SemanticStackVariable v, ControlFlowNode def, SemanticStackVariable v0
|
||||
) {
|
||||
this.isSourceActual(source, v) and def = source and v0 = v
|
||||
isSourceActual(source, v) and def = source and v0 = v
|
||||
or
|
||||
exists(ControlFlowNode source1, SemanticStackVariable v1 |
|
||||
this.actualSourceReaches(source, v, source1, v1)
|
||||
actualSourceReaches(source, v, source1, v1)
|
||||
|
|
||||
this.reassignment(source1, v1, def, v0)
|
||||
reassignment(source1, v1, def, v0)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -307,14 +307,14 @@ abstract deprecated class LocalScopeVariableReachabilityWithReassignment extends
|
||||
}
|
||||
|
||||
final override predicate isSource(ControlFlowNode node, LocalScopeVariable v) {
|
||||
this.isSourceActual(node, v)
|
||||
isSourceActual(node, v)
|
||||
or
|
||||
// Reassignment generates a new (non-actual) source
|
||||
this.reassignment(_, _, node, v)
|
||||
reassignment(_, _, node, v)
|
||||
}
|
||||
|
||||
final override predicate isSink(ControlFlowNode node, LocalScopeVariable v) {
|
||||
this.isSinkActual(node, v)
|
||||
isSinkActual(node, v)
|
||||
or
|
||||
// Reassignment generates a new (non-actual) sink
|
||||
exprDefinition(_, node, v.getAnAccess())
|
||||
@@ -347,21 +347,21 @@ abstract deprecated class LocalScopeVariableReachabilityExt extends string {
|
||||
/** See `LocalScopeVariableReachability.reaches`. */
|
||||
predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
|
||||
exists(BasicBlock bb, int i |
|
||||
this.isSource(source, v) and
|
||||
isSource(source, v) and
|
||||
bb.getNode(i) = source and
|
||||
not bb.isUnreachable()
|
||||
|
|
||||
exists(int j |
|
||||
j > i and
|
||||
sink = bb.getNode(j) and
|
||||
this.isSink(sink, v) and
|
||||
not exists(int k | this.isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) |
|
||||
isSink(sink, v) and
|
||||
not exists(int k | isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) |
|
||||
k in [i .. j - 1]
|
||||
)
|
||||
)
|
||||
or
|
||||
not exists(int k | this.isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | k >= i) and
|
||||
this.bbSuccessorEntryReaches(source, bb, v, sink, _)
|
||||
not exists(int k | isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | k >= i) and
|
||||
bbSuccessorEntryReaches(source, bb, v, sink, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -372,22 +372,22 @@ abstract deprecated class LocalScopeVariableReachabilityExt extends string {
|
||||
exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry |
|
||||
bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
|
||||
succSkipsFirstLoopAlwaysTrueUponEntry) and
|
||||
not this.isBarrier(source, bb.getEnd(), succ.getStart(), v)
|
||||
not isBarrier(source, bb.getEnd(), succ.getStart(), v)
|
||||
|
|
||||
this.bbEntryReachesLocally(source, succ, v, node) and
|
||||
bbEntryReachesLocally(source, succ, v, node) and
|
||||
succSkipsFirstLoopAlwaysTrueUponEntry = false
|
||||
or
|
||||
not exists(int k | this.isBarrier(source, succ.getNode(k), succ.getNode(k + 1), v)) and
|
||||
this.bbSuccessorEntryReaches(source, succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
|
||||
not exists(int k | isBarrier(source, succ.getNode(k), succ.getNode(k + 1), v)) and
|
||||
bbSuccessorEntryReaches(source, succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate bbEntryReachesLocally(
|
||||
ControlFlowNode source, BasicBlock bb, SemanticStackVariable v, ControlFlowNode node
|
||||
) {
|
||||
this.isSource(source, v) and
|
||||
exists(int n | node = bb.getNode(n) and this.isSink(node, v) |
|
||||
not exists(int m | m < n | this.isBarrier(source, bb.getNode(m), bb.getNode(m + 1), v))
|
||||
isSource(source, v) and
|
||||
exists(int n | node = bb.getNode(n) and isSink(node, v) |
|
||||
not exists(int m | m < n | isBarrier(source, bb.getNode(m), bb.getNode(m + 1), v))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,10 +59,10 @@ class SsaDefinition extends ControlFlowNodeBase {
|
||||
ControlFlowNode getDefinition() { result = this }
|
||||
|
||||
/** Gets the `BasicBlock` containing this definition. */
|
||||
BasicBlock getBasicBlock() { result.contains(this.getDefinition()) }
|
||||
BasicBlock getBasicBlock() { result.contains(getDefinition()) }
|
||||
|
||||
/** Holds if this definition is a phi node for variable `v`. */
|
||||
predicate isPhiNode(StackVariable v) { exists(StandardSSA x | x.phi_node(v, this)) }
|
||||
predicate isPhiNode(StackVariable v) { exists(StandardSSA x | x.phi_node(v, this.(BasicBlock))) }
|
||||
|
||||
/** Gets the location of this definition. */
|
||||
Location getLocation() { result = this.(ControlFlowNode).getLocation() }
|
||||
|
||||
@@ -292,7 +292,7 @@ library class SSAHelper extends int {
|
||||
*/
|
||||
cached
|
||||
string toString(ControlFlowNode node, StackVariable v) {
|
||||
if phi_node(v, node)
|
||||
if phi_node(v, node.(BasicBlock))
|
||||
then result = "SSA phi(" + v.getName() + ")"
|
||||
else (
|
||||
ssa_defn(v, node, _, _) and result = "SSA def(" + v.getName() + ")"
|
||||
|
||||
@@ -72,19 +72,19 @@ abstract class StackVariableReachability extends string {
|
||||
*/
|
||||
|
||||
exists(BasicBlock bb, int i |
|
||||
this.isSource(source, v) and
|
||||
isSource(source, v) and
|
||||
bb.getNode(i) = source and
|
||||
not bb.isUnreachable()
|
||||
|
|
||||
exists(int j |
|
||||
j > i and
|
||||
sink = bb.getNode(j) and
|
||||
this.isSink(sink, v) and
|
||||
not exists(int k | this.isBarrier(bb.getNode(k), v) | k in [i + 1 .. j - 1])
|
||||
isSink(sink, v) and
|
||||
not exists(int k | isBarrier(bb.getNode(k), v) | k in [i + 1 .. j - 1])
|
||||
)
|
||||
or
|
||||
not exists(int k | this.isBarrier(bb.getNode(k), v) | k > i) and
|
||||
this.bbSuccessorEntryReaches(bb, v, sink, _)
|
||||
not exists(int k | isBarrier(bb.getNode(k), v) | k > i) and
|
||||
bbSuccessorEntryReaches(bb, v, sink, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -96,11 +96,11 @@ abstract class StackVariableReachability extends string {
|
||||
bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
|
||||
succSkipsFirstLoopAlwaysTrueUponEntry)
|
||||
|
|
||||
this.bbEntryReachesLocally(succ, v, node) and
|
||||
bbEntryReachesLocally(succ, v, node) and
|
||||
succSkipsFirstLoopAlwaysTrueUponEntry = false
|
||||
or
|
||||
not this.isBarrier(succ.getNode(_), v) and
|
||||
this.bbSuccessorEntryReaches(succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
|
||||
not isBarrier(succ.getNode(_), v) and
|
||||
bbSuccessorEntryReaches(succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ abstract class StackVariableReachability extends string {
|
||||
) {
|
||||
exists(int n |
|
||||
node = bb.getNode(n) and
|
||||
this.isSink(node, v)
|
||||
isSink(node, v)
|
||||
|
|
||||
not exists(this.firstBarrierIndexIn(bb, v))
|
||||
or
|
||||
@@ -118,7 +118,7 @@ abstract class StackVariableReachability extends string {
|
||||
}
|
||||
|
||||
private int firstBarrierIndexIn(BasicBlock bb, SemanticStackVariable v) {
|
||||
result = min(int m | this.isBarrier(bb.getNode(m), v))
|
||||
result = min(int m | isBarrier(bb.getNode(m), v))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,7 +268,7 @@ abstract class StackVariableReachabilityWithReassignment extends StackVariableRe
|
||||
* accounts for loops where the condition is provably true upon entry.
|
||||
*/
|
||||
override predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
|
||||
this.reachesTo(source, v, sink, _)
|
||||
reachesTo(source, v, sink, _)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -278,21 +278,21 @@ abstract class StackVariableReachabilityWithReassignment extends StackVariableRe
|
||||
ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink, SemanticStackVariable v0
|
||||
) {
|
||||
exists(ControlFlowNode def |
|
||||
this.actualSourceReaches(source, v, def, v0) and
|
||||
actualSourceReaches(source, v, def, v0) and
|
||||
StackVariableReachability.super.reaches(def, v0, sink) and
|
||||
this.isSinkActual(sink, v0)
|
||||
isSinkActual(sink, v0)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate actualSourceReaches(
|
||||
ControlFlowNode source, SemanticStackVariable v, ControlFlowNode def, SemanticStackVariable v0
|
||||
) {
|
||||
this.isSourceActual(source, v) and def = source and v0 = v
|
||||
isSourceActual(source, v) and def = source and v0 = v
|
||||
or
|
||||
exists(ControlFlowNode source1, SemanticStackVariable v1 |
|
||||
this.actualSourceReaches(source, v, source1, v1)
|
||||
actualSourceReaches(source, v, source1, v1)
|
||||
|
|
||||
this.reassignment(source1, v1, def, v0)
|
||||
reassignment(source1, v1, def, v0)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -304,14 +304,14 @@ abstract class StackVariableReachabilityWithReassignment extends StackVariableRe
|
||||
}
|
||||
|
||||
final override predicate isSource(ControlFlowNode node, StackVariable v) {
|
||||
this.isSourceActual(node, v)
|
||||
isSourceActual(node, v)
|
||||
or
|
||||
// Reassignment generates a new (non-actual) source
|
||||
this.reassignment(_, _, node, v)
|
||||
reassignment(_, _, node, v)
|
||||
}
|
||||
|
||||
final override predicate isSink(ControlFlowNode node, StackVariable v) {
|
||||
this.isSinkActual(node, v)
|
||||
isSinkActual(node, v)
|
||||
or
|
||||
// Reassignment generates a new (non-actual) sink
|
||||
exprDefinition(_, node, v.getAnAccess())
|
||||
@@ -342,21 +342,21 @@ abstract class StackVariableReachabilityExt extends string {
|
||||
/** See `StackVariableReachability.reaches`. */
|
||||
predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
|
||||
exists(BasicBlock bb, int i |
|
||||
this.isSource(source, v) and
|
||||
isSource(source, v) and
|
||||
bb.getNode(i) = source and
|
||||
not bb.isUnreachable()
|
||||
|
|
||||
exists(int j |
|
||||
j > i and
|
||||
sink = bb.getNode(j) and
|
||||
this.isSink(sink, v) and
|
||||
not exists(int k | this.isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) |
|
||||
isSink(sink, v) and
|
||||
not exists(int k | isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) |
|
||||
k in [i .. j - 1]
|
||||
)
|
||||
)
|
||||
or
|
||||
not exists(int k | this.isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | k >= i) and
|
||||
this.bbSuccessorEntryReaches(source, bb, v, sink, _)
|
||||
not exists(int k | isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | k >= i) and
|
||||
bbSuccessorEntryReaches(source, bb, v, sink, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -367,22 +367,22 @@ abstract class StackVariableReachabilityExt extends string {
|
||||
exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry |
|
||||
bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
|
||||
succSkipsFirstLoopAlwaysTrueUponEntry) and
|
||||
not this.isBarrier(source, bb.getEnd(), succ.getStart(), v)
|
||||
not isBarrier(source, bb.getEnd(), succ.getStart(), v)
|
||||
|
|
||||
this.bbEntryReachesLocally(source, succ, v, node) and
|
||||
bbEntryReachesLocally(source, succ, v, node) and
|
||||
succSkipsFirstLoopAlwaysTrueUponEntry = false
|
||||
or
|
||||
not exists(int k | this.isBarrier(source, succ.getNode(k), succ.getNode(k + 1), v)) and
|
||||
this.bbSuccessorEntryReaches(source, succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
|
||||
not exists(int k | isBarrier(source, succ.getNode(k), succ.getNode(k + 1), v)) and
|
||||
bbSuccessorEntryReaches(source, succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate bbEntryReachesLocally(
|
||||
ControlFlowNode source, BasicBlock bb, SemanticStackVariable v, ControlFlowNode node
|
||||
) {
|
||||
this.isSource(source, v) and
|
||||
exists(int n | node = bb.getNode(n) and this.isSink(node, v) |
|
||||
not exists(int m | m < n | this.isBarrier(source, bb.getNode(m), bb.getNode(m + 1), v))
|
||||
isSource(source, v) and
|
||||
exists(int n | node = bb.getNode(n) and isSink(node, v) |
|
||||
not exists(int m | m < n | isBarrier(source, bb.getNode(m), bb.getNode(m + 1), v))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ class SubBasicBlock extends ControlFlowNodeBase {
|
||||
* returns a 0-based position, while `getRankInBasicBlock` returns a 1-based
|
||||
* position.
|
||||
*/
|
||||
deprecated int getPosInBasicBlock(BasicBlock bb) { result = this.getRankInBasicBlock(bb) - 1 }
|
||||
deprecated int getPosInBasicBlock(BasicBlock bb) { result = getRankInBasicBlock(bb) - 1 }
|
||||
|
||||
pragma[noinline]
|
||||
private int getIndexInBasicBlock(BasicBlock bb) { this = bb.getNode(result) }
|
||||
@@ -102,7 +102,7 @@ class SubBasicBlock extends ControlFlowNodeBase {
|
||||
exists(BasicBlock bb |
|
||||
exists(int outerIndex |
|
||||
result = bb.getNode(outerIndex) and
|
||||
index = this.outerToInnerIndex(bb, outerIndex)
|
||||
index = outerToInnerIndex(bb, outerIndex)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -231,7 +231,7 @@ private class PostOrderInitializer extends Initializer {
|
||||
or
|
||||
this.getDeclaration() = for.getRangeVariable()
|
||||
or
|
||||
this.getDeclaration() = for.getBeginEndDeclaration().getADeclaration()
|
||||
this.getDeclaration() = for.getBeginEndDeclaration().(DeclStmt).getADeclaration()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1143,7 +1143,7 @@ private class ExceptionSource extends Node {
|
||||
this.reachesParent(mid) and
|
||||
not mid = any(TryStmt try).getStmt() and
|
||||
not mid = any(MicrosoftTryStmt try).getStmt() and
|
||||
parent = mid.getParentNode()
|
||||
parent = mid.(Node).getParentNode()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -344,13 +344,14 @@ private int convertIntToType(int val, IntegralType t) {
|
||||
then if val = 0 then result = 0 else result = 1
|
||||
else
|
||||
if t.isUnsigned()
|
||||
then val >= 0 and val.bitShiftRight(t.getSize() * 8) = 0 and result = val
|
||||
then if val >= 0 and val.bitShiftRight(t.getSize() * 8) = 0 then result = val else none()
|
||||
else
|
||||
if val >= 0 and val.bitShiftRight(t.getSize() * 8 - 1) = 0
|
||||
then result = val
|
||||
else (
|
||||
(-(val + 1)).bitShiftRight(t.getSize() * 8 - 1) = 0 and result = val
|
||||
)
|
||||
else
|
||||
if (-(val + 1)).bitShiftRight(t.getSize() * 8 - 1) = 0
|
||||
then result = val
|
||||
else none()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -385,7 +386,7 @@ library class ExprEvaluator extends int {
|
||||
abstract predicate interesting(Expr e);
|
||||
|
||||
/** Gets the value of (interesting) expression `e`, if any. */
|
||||
int getValue(Expr e) { result = this.getValueInternal(e, e) }
|
||||
int getValue(Expr e) { result = getValueInternal(e, e) }
|
||||
|
||||
/**
|
||||
* When evaluating a syntactic subexpression of `e`, we may
|
||||
@@ -425,9 +426,9 @@ library class ExprEvaluator extends int {
|
||||
* calculates the values bottom-up.
|
||||
*/
|
||||
predicate interestingInternal(Expr e, Expr req, boolean sub) {
|
||||
this.interesting(e) and req = e and sub = true
|
||||
interesting(e) and req = e and sub = true
|
||||
or
|
||||
exists(Expr mid | this.interestingInternal(e, mid, sub) |
|
||||
exists(Expr mid | interestingInternal(e, mid, sub) |
|
||||
req = mid.(NotExpr).getOperand() or
|
||||
req = mid.(BinaryLogicalOperation).getAnOperand() or
|
||||
req = mid.(RelationalOperation).getAnOperand() or
|
||||
@@ -442,36 +443,36 @@ library class ExprEvaluator extends int {
|
||||
)
|
||||
or
|
||||
exists(VariableAccess va, Variable v, boolean sub1 |
|
||||
this.interestingVariableAccess(e, va, v, sub1) and
|
||||
interestingVariableAccess(e, va, v, sub1) and
|
||||
req = v.getAnAssignedValue() and
|
||||
(sub1 = true implies not this.ignoreVariableAssignment(e, v, req)) and
|
||||
(sub1 = true implies not ignoreVariableAssignment(e, v, req)) and
|
||||
sub = false
|
||||
)
|
||||
or
|
||||
exists(Function f |
|
||||
this.interestingFunction(e, f) and
|
||||
interestingFunction(e, f) and
|
||||
returnStmt(f, req) and
|
||||
sub = false
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interestingVariableAccess(Expr e, VariableAccess va, Variable v, boolean sub) {
|
||||
this.interestingInternal(e, va, sub) and
|
||||
interestingInternal(e, va, sub) and
|
||||
v = getVariableTarget(va) and
|
||||
(
|
||||
v.hasInitializer()
|
||||
or
|
||||
sub = true and this.allowVariableWithoutInitializer(e, v)
|
||||
sub = true and allowVariableWithoutInitializer(e, v)
|
||||
) and
|
||||
tractableVariable(v) and
|
||||
forall(StmtParent def | nonAnalyzableVariableDefinition(v, def) |
|
||||
sub = true and
|
||||
this.ignoreNonAnalyzableVariableDefinition(e, v, def)
|
||||
ignoreNonAnalyzableVariableDefinition(e, v, def)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interestingFunction(Expr e, Function f) {
|
||||
exists(FunctionCall fc | this.interestingInternal(e, fc, _) |
|
||||
exists(FunctionCall fc | interestingInternal(e, fc, _) |
|
||||
f = fc.getTarget() and
|
||||
not obviouslyNonConstant(f) and
|
||||
not f.getUnspecifiedType() instanceof VoidType
|
||||
@@ -481,10 +482,10 @@ library class ExprEvaluator extends int {
|
||||
/** Gets the value of subexpressions `req` for expression `e`, if any. */
|
||||
private int getValueInternal(Expr e, Expr req) {
|
||||
(
|
||||
this.interestingInternal(e, req, true) and
|
||||
interestingInternal(e, req, true) and
|
||||
(
|
||||
result = req.(CompileTimeConstantInt).getIntValue() or
|
||||
result = this.getCompoundValue(e, req)
|
||||
result = getCompoundValue(e, req.(CompileTimeVariableExpr))
|
||||
) and
|
||||
(
|
||||
req.getUnderlyingType().(IntegralType).isSigned() or
|
||||
@@ -495,126 +496,109 @@ library class ExprEvaluator extends int {
|
||||
|
||||
/** Gets the value of compound subexpressions `val` for expression `e`, if any. */
|
||||
private int getCompoundValue(Expr e, CompileTimeVariableExpr val) {
|
||||
this.interestingInternal(e, val, true) and
|
||||
interestingInternal(e, val, true) and
|
||||
(
|
||||
exists(NotExpr req | req = val |
|
||||
result = 1 and this.getValueInternal(e, req.getOperand()) = 0
|
||||
result = 1 and getValueInternal(e, req.getOperand()) = 0
|
||||
or
|
||||
result = 0 and this.getValueInternal(e, req.getOperand()) != 0
|
||||
result = 0 and getValueInternal(e, req.getOperand()) != 0
|
||||
)
|
||||
or
|
||||
exists(LogicalAndExpr req | req = val |
|
||||
result = 1 and
|
||||
this.getValueInternal(e, req.getLeftOperand()) != 0 and
|
||||
this.getValueInternal(e, req.getRightOperand()) != 0
|
||||
getValueInternal(e, req.getLeftOperand()) != 0 and
|
||||
getValueInternal(e, req.getRightOperand()) != 0
|
||||
or
|
||||
result = 0 and this.getValueInternal(e, req.getAnOperand()) = 0
|
||||
result = 0 and getValueInternal(e, req.getAnOperand()) = 0
|
||||
)
|
||||
or
|
||||
exists(LogicalOrExpr req | req = val |
|
||||
result = 1 and this.getValueInternal(e, req.getAnOperand()) != 0
|
||||
result = 1 and getValueInternal(e, req.getAnOperand()) != 0
|
||||
or
|
||||
result = 0 and
|
||||
this.getValueInternal(e, req.getLeftOperand()) = 0 and
|
||||
this.getValueInternal(e, req.getRightOperand()) = 0
|
||||
getValueInternal(e, req.getLeftOperand()) = 0 and
|
||||
getValueInternal(e, req.getRightOperand()) = 0
|
||||
)
|
||||
or
|
||||
exists(LTExpr req | req = val |
|
||||
result = 1 and
|
||||
this.getValueInternal(e, req.getLeftOperand()) <
|
||||
this.getValueInternal(e, req.getRightOperand())
|
||||
getValueInternal(e, req.getLeftOperand()) < getValueInternal(e, req.getRightOperand())
|
||||
or
|
||||
result = 0 and
|
||||
this.getValueInternal(e, req.getLeftOperand()) >=
|
||||
this.getValueInternal(e, req.getRightOperand())
|
||||
getValueInternal(e, req.getLeftOperand()) >= getValueInternal(e, req.getRightOperand())
|
||||
)
|
||||
or
|
||||
exists(GTExpr req | req = val |
|
||||
result = 1 and
|
||||
this.getValueInternal(e, req.getLeftOperand()) >
|
||||
this.getValueInternal(e, req.getRightOperand())
|
||||
getValueInternal(e, req.getLeftOperand()) > getValueInternal(e, req.getRightOperand())
|
||||
or
|
||||
result = 0 and
|
||||
this.getValueInternal(e, req.getLeftOperand()) <=
|
||||
this.getValueInternal(e, req.getRightOperand())
|
||||
getValueInternal(e, req.getLeftOperand()) <= getValueInternal(e, req.getRightOperand())
|
||||
)
|
||||
or
|
||||
exists(LEExpr req | req = val |
|
||||
result = 1 and
|
||||
this.getValueInternal(e, req.getLeftOperand()) <=
|
||||
this.getValueInternal(e, req.getRightOperand())
|
||||
getValueInternal(e, req.getLeftOperand()) <= getValueInternal(e, req.getRightOperand())
|
||||
or
|
||||
result = 0 and
|
||||
this.getValueInternal(e, req.getLeftOperand()) >
|
||||
this.getValueInternal(e, req.getRightOperand())
|
||||
getValueInternal(e, req.getLeftOperand()) > getValueInternal(e, req.getRightOperand())
|
||||
)
|
||||
or
|
||||
exists(GEExpr req | req = val |
|
||||
result = 1 and
|
||||
this.getValueInternal(e, req.getLeftOperand()) >=
|
||||
this.getValueInternal(e, req.getRightOperand())
|
||||
getValueInternal(e, req.getLeftOperand()) >= getValueInternal(e, req.getRightOperand())
|
||||
or
|
||||
result = 0 and
|
||||
this.getValueInternal(e, req.getLeftOperand()) <
|
||||
this.getValueInternal(e, req.getRightOperand())
|
||||
getValueInternal(e, req.getLeftOperand()) < getValueInternal(e, req.getRightOperand())
|
||||
)
|
||||
or
|
||||
exists(EQExpr req | req = val |
|
||||
result = 1 and
|
||||
this.getValueInternal(e, req.getLeftOperand()) =
|
||||
this.getValueInternal(e, req.getRightOperand())
|
||||
getValueInternal(e, req.getLeftOperand()) = getValueInternal(e, req.getRightOperand())
|
||||
or
|
||||
result = 0 and
|
||||
this.getValueInternal(e, req.getLeftOperand()) !=
|
||||
this.getValueInternal(e, req.getRightOperand())
|
||||
getValueInternal(e, req.getLeftOperand()) != getValueInternal(e, req.getRightOperand())
|
||||
)
|
||||
or
|
||||
exists(NEExpr req | req = val |
|
||||
result = 0 and
|
||||
this.getValueInternal(e, req.getLeftOperand()) =
|
||||
this.getValueInternal(e, req.getRightOperand())
|
||||
getValueInternal(e, req.getLeftOperand()) = getValueInternal(e, req.getRightOperand())
|
||||
or
|
||||
result = 1 and
|
||||
this.getValueInternal(e, req.getLeftOperand()) !=
|
||||
this.getValueInternal(e, req.getRightOperand())
|
||||
getValueInternal(e, req.getLeftOperand()) != getValueInternal(e, req.getRightOperand())
|
||||
)
|
||||
or
|
||||
exists(AddExpr req | req = val |
|
||||
result =
|
||||
this.getValueInternal(e, req.getLeftOperand()) +
|
||||
this.getValueInternal(e, req.getRightOperand())
|
||||
getValueInternal(e, req.getLeftOperand()) + getValueInternal(e, req.getRightOperand())
|
||||
)
|
||||
or
|
||||
exists(SubExpr req | req = val |
|
||||
result =
|
||||
this.getValueInternal(e, req.getLeftOperand()) -
|
||||
this.getValueInternal(e, req.getRightOperand())
|
||||
getValueInternal(e, req.getLeftOperand()) - getValueInternal(e, req.getRightOperand())
|
||||
)
|
||||
or
|
||||
exists(MulExpr req | req = val |
|
||||
result =
|
||||
this.getValueInternal(e, req.getLeftOperand()) *
|
||||
this.getValueInternal(e, req.getRightOperand())
|
||||
getValueInternal(e, req.getLeftOperand()) * getValueInternal(e, req.getRightOperand())
|
||||
)
|
||||
or
|
||||
exists(RemExpr req | req = val |
|
||||
result =
|
||||
this.getValueInternal(e, req.getLeftOperand()) %
|
||||
this.getValueInternal(e, req.getRightOperand())
|
||||
getValueInternal(e, req.getLeftOperand()) % getValueInternal(e, req.getRightOperand())
|
||||
)
|
||||
or
|
||||
exists(DivExpr req | req = val |
|
||||
result =
|
||||
this.getValueInternal(e, req.getLeftOperand()) /
|
||||
this.getValueInternal(e, req.getRightOperand())
|
||||
getValueInternal(e, req.getLeftOperand()) / getValueInternal(e, req.getRightOperand())
|
||||
)
|
||||
or
|
||||
exists(AssignExpr req | req = val | result = this.getValueInternal(e, req.getRValue()))
|
||||
exists(AssignExpr req | req = val | result = getValueInternal(e, req.getRValue()))
|
||||
or
|
||||
result = this.getVariableValue(e, val)
|
||||
result = getVariableValue(e, val.(VariableAccess))
|
||||
or
|
||||
exists(FunctionCall call | call = val and not callWithMultipleTargets(call) |
|
||||
result = this.getFunctionValue(call.getTarget())
|
||||
result = getFunctionValue(call.getTarget())
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -622,13 +606,13 @@ library class ExprEvaluator extends int {
|
||||
language[monotonicAggregates]
|
||||
private int getVariableValue(Expr e, VariableAccess va) {
|
||||
exists(Variable v |
|
||||
this.interestingVariableAccess(e, va, v, true) and
|
||||
interestingVariableAccess(e, va, v, true) and
|
||||
// All assignments must have the same int value
|
||||
result =
|
||||
unique(Expr value |
|
||||
value = v.getAnAssignedValue() and not this.ignoreVariableAssignment(e, v, value)
|
||||
value = v.getAnAssignedValue() and not ignoreVariableAssignment(e, v, value)
|
||||
|
|
||||
this.getValueInternalNonSubExpr(value)
|
||||
getValueInternalNonSubExpr(value)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -636,16 +620,14 @@ library class ExprEvaluator extends int {
|
||||
/** Holds if the function `f` is considered by the analysis and may return `ret`. */
|
||||
pragma[noinline]
|
||||
private predicate interestingReturnValue(Function f, Expr ret) {
|
||||
this.interestingFunction(_, f) and
|
||||
interestingFunction(_, f) and
|
||||
returnStmt(f, ret)
|
||||
}
|
||||
|
||||
private int getFunctionValue(Function f) {
|
||||
// All returns must have the same int value
|
||||
// And it must have at least one return
|
||||
forex(Expr ret | this.interestingReturnValue(f, ret) |
|
||||
result = this.getValueInternalNonSubExpr(ret)
|
||||
)
|
||||
forex(Expr ret | interestingReturnValue(f, ret) | result = getValueInternalNonSubExpr(ret))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -660,10 +642,10 @@ library class ExprEvaluator extends int {
|
||||
* omitted).
|
||||
*/
|
||||
private int getValueInternalNonSubExpr(Expr req) {
|
||||
this.interestingInternal(_, req, false) and
|
||||
interestingInternal(_, req, false) and
|
||||
(
|
||||
result = req.(CompileTimeConstantInt).getIntValue() or
|
||||
result = this.getCompoundValueNonSubExpr(req)
|
||||
result = getCompoundValueNonSubExpr(req.(CompileTimeVariableExpr))
|
||||
) and
|
||||
(
|
||||
req.getUnderlyingType().(IntegralType).isSigned() or
|
||||
@@ -674,131 +656,131 @@ library class ExprEvaluator extends int {
|
||||
private int getCompoundValueNonSubExpr(CompileTimeVariableExpr val) {
|
||||
(
|
||||
exists(NotExpr req | req = val |
|
||||
result = 1 and this.getValueInternalNonSubExpr(req.getOperand()) = 0
|
||||
result = 1 and getValueInternalNonSubExpr(req.getOperand()) = 0
|
||||
or
|
||||
result = 0 and this.getValueInternalNonSubExpr(req.getOperand()) != 0
|
||||
result = 0 and getValueInternalNonSubExpr(req.getOperand()) != 0
|
||||
)
|
||||
or
|
||||
exists(LogicalAndExpr req | req = val |
|
||||
result = 1 and
|
||||
this.getValueInternalNonSubExpr(req.getLeftOperand()) != 0 and
|
||||
this.getValueInternalNonSubExpr(req.getRightOperand()) != 0
|
||||
getValueInternalNonSubExpr(req.getLeftOperand()) != 0 and
|
||||
getValueInternalNonSubExpr(req.getRightOperand()) != 0
|
||||
or
|
||||
result = 0 and this.getValueInternalNonSubExpr(req.getAnOperand()) = 0
|
||||
result = 0 and getValueInternalNonSubExpr(req.getAnOperand()) = 0
|
||||
)
|
||||
or
|
||||
exists(LogicalOrExpr req | req = val |
|
||||
result = 1 and this.getValueInternalNonSubExpr(req.getAnOperand()) != 0
|
||||
result = 1 and getValueInternalNonSubExpr(req.getAnOperand()) != 0
|
||||
or
|
||||
result = 0 and
|
||||
this.getValueInternalNonSubExpr(req.getLeftOperand()) = 0 and
|
||||
this.getValueInternalNonSubExpr(req.getRightOperand()) = 0
|
||||
getValueInternalNonSubExpr(req.getLeftOperand()) = 0 and
|
||||
getValueInternalNonSubExpr(req.getRightOperand()) = 0
|
||||
)
|
||||
or
|
||||
exists(LTExpr req | req = val |
|
||||
result = 1 and
|
||||
this.getValueInternalNonSubExpr(req.getLeftOperand()) <
|
||||
this.getValueInternalNonSubExpr(req.getRightOperand())
|
||||
getValueInternalNonSubExpr(req.getLeftOperand()) <
|
||||
getValueInternalNonSubExpr(req.getRightOperand())
|
||||
or
|
||||
result = 0 and
|
||||
this.getValueInternalNonSubExpr(req.getLeftOperand()) >=
|
||||
this.getValueInternalNonSubExpr(req.getRightOperand())
|
||||
getValueInternalNonSubExpr(req.getLeftOperand()) >=
|
||||
getValueInternalNonSubExpr(req.getRightOperand())
|
||||
)
|
||||
or
|
||||
exists(GTExpr req | req = val |
|
||||
result = 1 and
|
||||
this.getValueInternalNonSubExpr(req.getLeftOperand()) >
|
||||
this.getValueInternalNonSubExpr(req.getRightOperand())
|
||||
getValueInternalNonSubExpr(req.getLeftOperand()) >
|
||||
getValueInternalNonSubExpr(req.getRightOperand())
|
||||
or
|
||||
result = 0 and
|
||||
this.getValueInternalNonSubExpr(req.getLeftOperand()) <=
|
||||
this.getValueInternalNonSubExpr(req.getRightOperand())
|
||||
getValueInternalNonSubExpr(req.getLeftOperand()) <=
|
||||
getValueInternalNonSubExpr(req.getRightOperand())
|
||||
)
|
||||
or
|
||||
exists(LEExpr req | req = val |
|
||||
result = 1 and
|
||||
this.getValueInternalNonSubExpr(req.getLeftOperand()) <=
|
||||
this.getValueInternalNonSubExpr(req.getRightOperand())
|
||||
getValueInternalNonSubExpr(req.getLeftOperand()) <=
|
||||
getValueInternalNonSubExpr(req.getRightOperand())
|
||||
or
|
||||
result = 0 and
|
||||
this.getValueInternalNonSubExpr(req.getLeftOperand()) >
|
||||
this.getValueInternalNonSubExpr(req.getRightOperand())
|
||||
getValueInternalNonSubExpr(req.getLeftOperand()) >
|
||||
getValueInternalNonSubExpr(req.getRightOperand())
|
||||
)
|
||||
or
|
||||
exists(GEExpr req | req = val |
|
||||
result = 1 and
|
||||
this.getValueInternalNonSubExpr(req.getLeftOperand()) >=
|
||||
this.getValueInternalNonSubExpr(req.getRightOperand())
|
||||
getValueInternalNonSubExpr(req.getLeftOperand()) >=
|
||||
getValueInternalNonSubExpr(req.getRightOperand())
|
||||
or
|
||||
result = 0 and
|
||||
this.getValueInternalNonSubExpr(req.getLeftOperand()) <
|
||||
this.getValueInternalNonSubExpr(req.getRightOperand())
|
||||
getValueInternalNonSubExpr(req.getLeftOperand()) <
|
||||
getValueInternalNonSubExpr(req.getRightOperand())
|
||||
)
|
||||
or
|
||||
exists(EQExpr req | req = val |
|
||||
result = 1 and
|
||||
this.getValueInternalNonSubExpr(req.getLeftOperand()) =
|
||||
this.getValueInternalNonSubExpr(req.getRightOperand())
|
||||
getValueInternalNonSubExpr(req.getLeftOperand()) =
|
||||
getValueInternalNonSubExpr(req.getRightOperand())
|
||||
or
|
||||
result = 0 and
|
||||
this.getValueInternalNonSubExpr(req.getLeftOperand()) !=
|
||||
this.getValueInternalNonSubExpr(req.getRightOperand())
|
||||
getValueInternalNonSubExpr(req.getLeftOperand()) !=
|
||||
getValueInternalNonSubExpr(req.getRightOperand())
|
||||
)
|
||||
or
|
||||
exists(NEExpr req | req = val |
|
||||
result = 0 and
|
||||
this.getValueInternalNonSubExpr(req.getLeftOperand()) =
|
||||
this.getValueInternalNonSubExpr(req.getRightOperand())
|
||||
getValueInternalNonSubExpr(req.getLeftOperand()) =
|
||||
getValueInternalNonSubExpr(req.getRightOperand())
|
||||
or
|
||||
result = 1 and
|
||||
this.getValueInternalNonSubExpr(req.getLeftOperand()) !=
|
||||
this.getValueInternalNonSubExpr(req.getRightOperand())
|
||||
getValueInternalNonSubExpr(req.getLeftOperand()) !=
|
||||
getValueInternalNonSubExpr(req.getRightOperand())
|
||||
)
|
||||
or
|
||||
exists(AddExpr req | req = val |
|
||||
result =
|
||||
this.getValueInternalNonSubExpr(req.getLeftOperand()) +
|
||||
this.getValueInternalNonSubExpr(req.getRightOperand())
|
||||
getValueInternalNonSubExpr(req.getLeftOperand()) +
|
||||
getValueInternalNonSubExpr(req.getRightOperand())
|
||||
)
|
||||
or
|
||||
exists(SubExpr req | req = val |
|
||||
result =
|
||||
this.getValueInternalNonSubExpr(req.getLeftOperand()) -
|
||||
this.getValueInternalNonSubExpr(req.getRightOperand())
|
||||
getValueInternalNonSubExpr(req.getLeftOperand()) -
|
||||
getValueInternalNonSubExpr(req.getRightOperand())
|
||||
)
|
||||
or
|
||||
exists(MulExpr req | req = val |
|
||||
result =
|
||||
this.getValueInternalNonSubExpr(req.getLeftOperand()) *
|
||||
this.getValueInternalNonSubExpr(req.getRightOperand())
|
||||
getValueInternalNonSubExpr(req.getLeftOperand()) *
|
||||
getValueInternalNonSubExpr(req.getRightOperand())
|
||||
)
|
||||
or
|
||||
exists(RemExpr req | req = val |
|
||||
result =
|
||||
this.getValueInternalNonSubExpr(req.getLeftOperand()) %
|
||||
this.getValueInternalNonSubExpr(req.getRightOperand())
|
||||
getValueInternalNonSubExpr(req.getLeftOperand()) %
|
||||
getValueInternalNonSubExpr(req.getRightOperand())
|
||||
)
|
||||
or
|
||||
exists(DivExpr req | req = val |
|
||||
result =
|
||||
this.getValueInternalNonSubExpr(req.getLeftOperand()) /
|
||||
this.getValueInternalNonSubExpr(req.getRightOperand())
|
||||
getValueInternalNonSubExpr(req.getLeftOperand()) /
|
||||
getValueInternalNonSubExpr(req.getRightOperand())
|
||||
)
|
||||
or
|
||||
exists(AssignExpr req | req = val | result = this.getValueInternalNonSubExpr(req.getRValue()))
|
||||
exists(AssignExpr req | req = val | result = getValueInternalNonSubExpr(req.getRValue()))
|
||||
or
|
||||
result = this.getVariableValueNonSubExpr(val)
|
||||
result = getVariableValueNonSubExpr(val.(VariableAccess))
|
||||
or
|
||||
exists(FunctionCall call | call = val and not callWithMultipleTargets(call) |
|
||||
result = this.getFunctionValue(call.getTarget())
|
||||
result = getFunctionValue(call.getTarget())
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private int getVariableValueNonSubExpr(VariableAccess va) {
|
||||
// All assignments must have the same int value
|
||||
result = this.getMinVariableValueNonSubExpr(va) and
|
||||
result = this.getMaxVariableValueNonSubExpr(va)
|
||||
result = getMinVariableValueNonSubExpr(va) and
|
||||
result = getMaxVariableValueNonSubExpr(va)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -809,9 +791,8 @@ library class ExprEvaluator extends int {
|
||||
pragma[noopt]
|
||||
private int getMinVariableValueNonSubExpr(VariableAccess va) {
|
||||
exists(Variable v |
|
||||
this.interestingVariableAccess(_, va, v, false) and
|
||||
result =
|
||||
min(Expr value | value = v.getAnAssignedValue() | this.getValueInternalNonSubExpr(value))
|
||||
interestingVariableAccess(_, va, v, false) and
|
||||
result = min(Expr value | value = v.getAnAssignedValue() | getValueInternalNonSubExpr(value))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -823,9 +804,8 @@ library class ExprEvaluator extends int {
|
||||
pragma[noopt]
|
||||
private int getMaxVariableValueNonSubExpr(VariableAccess va) {
|
||||
exists(Variable v |
|
||||
this.interestingVariableAccess(_, va, v, false) and
|
||||
result =
|
||||
max(Expr value | value = v.getAnAssignedValue() | this.getValueInternalNonSubExpr(value))
|
||||
interestingVariableAccess(_, va, v, false) and
|
||||
result = max(Expr value | value = v.getAnAssignedValue() | getValueInternalNonSubExpr(value))
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -988,9 +968,9 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
|
||||
abstract predicate isLoopBody(Expr e, StmtParent s);
|
||||
|
||||
private predicate isLoopBodyDescendant(Expr e, StmtParent s) {
|
||||
this.isLoopBody(e, s)
|
||||
isLoopBody(e, s)
|
||||
or
|
||||
exists(StmtParent mid | this.isLoopBodyDescendant(e, mid) |
|
||||
exists(StmtParent mid | isLoopBodyDescendant(e, mid) |
|
||||
s = mid.(Stmt).getAChild() or
|
||||
s = mid.(Expr).getAChild()
|
||||
)
|
||||
@@ -998,13 +978,13 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
|
||||
|
||||
// Same as `interestingInternal(e, sub, true)` but avoids negative recursion
|
||||
private predicate interestingSubExpr(Expr e, Expr sub) {
|
||||
this.interesting(e) and e = sub
|
||||
interesting(e) and e = sub
|
||||
or
|
||||
exists(Expr mid | this.interestingSubExpr(e, mid) and sub = mid.getAChild())
|
||||
exists(Expr mid | interestingSubExpr(e, mid) and sub = mid.getAChild())
|
||||
}
|
||||
|
||||
private predicate maybeInterestingVariable(Expr e, Variable v) {
|
||||
exists(VariableAccess va | this.interestingSubExpr(e, va) | va.getTarget() = v)
|
||||
exists(VariableAccess va | interestingSubExpr(e, va) | va.getTarget() = v)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1016,9 +996,9 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
|
||||
* definition of `v`.
|
||||
*/
|
||||
private predicate reachesLoopEntryFromLoopBody(Expr e, Variable v, StmtParent valueOrDef) {
|
||||
this.maybeInterestingVariable(e, v) and
|
||||
maybeInterestingVariable(e, v) and
|
||||
(valueOrDef = v.getAnAssignedValue() or nonAnalyzableVariableDefinition(v, valueOrDef)) and
|
||||
this.isLoopBodyDescendant(e, valueOrDef) and
|
||||
isLoopBodyDescendant(e, valueOrDef) and
|
||||
/*
|
||||
* Use primitive basic blocks in reachability analysis for better performance.
|
||||
* This is similar to the pattern used in e.g. `DefinitionsAndUses` and
|
||||
@@ -1028,16 +1008,16 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
|
||||
exists(PrimitiveBasicBlock bb1, int pos1 | bb1.getNode(pos1) = valueOrDef |
|
||||
// Reaches in same basic block
|
||||
exists(int pos2 |
|
||||
this.loopEntryAt(bb1, pos2, e) and
|
||||
loopEntryAt(bb1, pos2, e) and
|
||||
pos2 > pos1 and
|
||||
not exists(int k | this.assignmentAt(bb1, k, v) | k in [pos1 + 1 .. pos2 - 1])
|
||||
not exists(int k | assignmentAt(bb1, k, v) | k in [pos1 + 1 .. pos2 - 1])
|
||||
)
|
||||
or
|
||||
// Reaches in a successor block
|
||||
exists(PrimitiveBasicBlock bb2 |
|
||||
bb2 = bb1.getASuccessor() and
|
||||
not exists(int pos3 | this.assignmentAt(bb1, pos3, v) and pos3 > pos1) and
|
||||
this.bbReachesLoopEntry(bb2, e, v)
|
||||
not exists(int pos3 | assignmentAt(bb1, pos3, v) and pos3 > pos1) and
|
||||
bbReachesLoopEntry(bb2, e, v)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -1045,12 +1025,12 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
|
||||
private predicate loopEntryAt(PrimitiveBasicBlock bb, int pos, Expr e) {
|
||||
exists(Node cfn |
|
||||
bb.getNode(pos) = cfn and
|
||||
this.isLoopEntry(e, cfn)
|
||||
isLoopEntry(e, cfn)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate assignmentAt(PrimitiveBasicBlock bb, int pos, Variable v) {
|
||||
this.maybeInterestingVariable(_, v) and
|
||||
maybeInterestingVariable(_, v) and
|
||||
bb.getNode(pos) = v.getAnAssignedValue()
|
||||
}
|
||||
|
||||
@@ -1059,19 +1039,19 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
|
||||
* the loop belonging to `e` without crossing an assignment to `v`.
|
||||
*/
|
||||
private predicate bbReachesLoopEntry(PrimitiveBasicBlock bb, Expr e, Variable v) {
|
||||
this.bbReachesLoopEntryLocally(bb, e, v)
|
||||
bbReachesLoopEntryLocally(bb, e, v)
|
||||
or
|
||||
exists(PrimitiveBasicBlock succ | succ = bb.getASuccessor() |
|
||||
this.bbReachesLoopEntry(succ, e, v) and
|
||||
not this.assignmentAt(bb, _, v)
|
||||
bbReachesLoopEntry(succ, e, v) and
|
||||
not assignmentAt(bb, _, v)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate bbReachesLoopEntryLocally(PrimitiveBasicBlock bb, Expr e, Variable v) {
|
||||
exists(int pos |
|
||||
this.loopEntryAt(bb, pos, e) and
|
||||
this.maybeInterestingVariable(e, v) and
|
||||
not exists(int pos1 | this.assignmentAt(bb, pos1, v) | pos1 < pos)
|
||||
loopEntryAt(bb, pos, e) and
|
||||
maybeInterestingVariable(e, v) and
|
||||
not exists(int pos1 | assignmentAt(bb, pos1, v) | pos1 < pos)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1105,10 +1085,10 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
|
||||
* ```
|
||||
*/
|
||||
override predicate ignoreNonAnalyzableVariableDefinition(Expr e, Variable v, StmtParent def) {
|
||||
this.maybeInterestingVariable(e, v) and
|
||||
maybeInterestingVariable(e, v) and
|
||||
nonAnalyzableVariableDefinition(v, def) and
|
||||
this.isLoopBodyDescendant(e, def) and
|
||||
not this.reachesLoopEntryFromLoopBody(e, v, def)
|
||||
isLoopBodyDescendant(e, def) and
|
||||
not reachesLoopEntryFromLoopBody(e, v, def)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1141,10 +1121,10 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
|
||||
* ```
|
||||
*/
|
||||
override predicate ignoreVariableAssignment(Expr e, Variable v, Expr value) {
|
||||
this.maybeInterestingVariable(e, v) and
|
||||
maybeInterestingVariable(e, v) and
|
||||
value = v.getAnAssignedValue() and
|
||||
this.isLoopBodyDescendant(e, value) and
|
||||
not this.reachesLoopEntryFromLoopBody(e, v, value)
|
||||
isLoopBodyDescendant(e, value) and
|
||||
not reachesLoopEntryFromLoopBody(e, v, value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
private import cpp
|
||||
private import semmle.code.cpp.dataflow.internal.DataFlowPrivate
|
||||
private import semmle.code.cpp.dataflow.internal.DataFlowUtil
|
||||
|
||||
/**
|
||||
* Gets a function that might be called by `call`.
|
||||
@@ -65,17 +63,3 @@ predicate mayBenefitFromCallContext(Call call, Function f) { none() }
|
||||
* restricted to those `call`s for which a context might make a difference.
|
||||
*/
|
||||
Function viableImplInCallContext(Call call, Call ctx) { none() }
|
||||
|
||||
/** A parameter position represented by an integer. */
|
||||
class ParameterPosition extends int {
|
||||
ParameterPosition() { any(ParameterNode p).isParameterOf(_, this) }
|
||||
}
|
||||
|
||||
/** An argument position represented by an integer. */
|
||||
class ArgumentPosition extends int {
|
||||
ArgumentPosition() { any(ArgumentNode a).argumentOf(_, this) }
|
||||
}
|
||||
|
||||
/** Holds if arguments at position `apos` match parameters at position `ppos`. */
|
||||
pragma[inline]
|
||||
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos }
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -2,42 +2,6 @@ private import DataFlowImplSpecific::Private
|
||||
private import DataFlowImplSpecific::Public
|
||||
import Cached
|
||||
|
||||
module DataFlowImplCommonPublic {
|
||||
private newtype TFlowFeature =
|
||||
TFeatureHasSourceCallContext() or
|
||||
TFeatureHasSinkCallContext() or
|
||||
TFeatureEqualSourceSinkCallContext()
|
||||
|
||||
/** A flow configuration feature for use in `Configuration::getAFeature()`. */
|
||||
class FlowFeature extends TFlowFeature {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A flow configuration feature that implies that sources have some existing
|
||||
* call context.
|
||||
*/
|
||||
class FeatureHasSourceCallContext extends FlowFeature, TFeatureHasSourceCallContext {
|
||||
override string toString() { result = "FeatureHasSourceCallContext" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A flow configuration feature that implies that sinks have some existing
|
||||
* call context.
|
||||
*/
|
||||
class FeatureHasSinkCallContext extends FlowFeature, TFeatureHasSinkCallContext {
|
||||
override string toString() { result = "FeatureHasSinkCallContext" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A flow configuration feature that implies that source-sink pairs have some
|
||||
* shared existing call context.
|
||||
*/
|
||||
class FeatureEqualSourceSinkCallContext extends FlowFeature, TFeatureEqualSourceSinkCallContext {
|
||||
override string toString() { result = "FeatureEqualSourceSinkCallContext" }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The cost limits for the `AccessPathFront` to `AccessPathApprox` expansion.
|
||||
*
|
||||
@@ -62,18 +26,6 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
|
||||
tupleLimit = 1000
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `arg` is an argument of `call` with an argument position that matches
|
||||
* parameter position `ppos`.
|
||||
*/
|
||||
pragma[noinline]
|
||||
predicate argumentPositionMatch(DataFlowCall call, ArgNode arg, ParameterPosition ppos) {
|
||||
exists(ArgumentPosition apos |
|
||||
arg.argumentOf(call, apos) and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a simple data-flow analysis for resolving lambda calls. The analysis
|
||||
* currently excludes read-steps, store-steps, and flow-through.
|
||||
@@ -83,27 +35,25 @@ predicate argumentPositionMatch(DataFlowCall call, ArgNode arg, ParameterPositio
|
||||
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
|
||||
*/
|
||||
private module LambdaFlow {
|
||||
pragma[noinline]
|
||||
private predicate viableParamNonLambda(DataFlowCall call, ParameterPosition ppos, ParamNode p) {
|
||||
p.isParameterOf(viableCallable(call), ppos)
|
||||
private predicate viableParamNonLambda(DataFlowCall call, int i, ParamNode p) {
|
||||
p.isParameterOf(viableCallable(call), i)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate viableParamLambda(DataFlowCall call, ParameterPosition ppos, ParamNode p) {
|
||||
p.isParameterOf(viableCallableLambda(call, _), ppos)
|
||||
private predicate viableParamLambda(DataFlowCall call, int i, ParamNode p) {
|
||||
p.isParameterOf(viableCallableLambda(call, _), i)
|
||||
}
|
||||
|
||||
private predicate viableParamArgNonLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
|
||||
exists(ParameterPosition ppos |
|
||||
viableParamNonLambda(call, ppos, p) and
|
||||
argumentPositionMatch(call, arg, ppos)
|
||||
exists(int i |
|
||||
viableParamNonLambda(call, i, p) and
|
||||
arg.argumentOf(call, i)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate viableParamArgLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
|
||||
exists(ParameterPosition ppos |
|
||||
viableParamLambda(call, ppos, p) and
|
||||
argumentPositionMatch(call, arg, ppos)
|
||||
exists(int i |
|
||||
viableParamLambda(call, i, p) and
|
||||
arg.argumentOf(call, i)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -301,7 +251,7 @@ private module Cached {
|
||||
predicate forceCachingInSameStage() { any() }
|
||||
|
||||
cached
|
||||
predicate nodeEnclosingCallable(Node n, DataFlowCallable c) { c = nodeGetEnclosingCallable(n) }
|
||||
predicate nodeEnclosingCallable(Node n, DataFlowCallable c) { c = n.getEnclosingCallable() }
|
||||
|
||||
cached
|
||||
predicate callEnclosingCallable(DataFlowCall call, DataFlowCallable c) {
|
||||
@@ -336,7 +286,7 @@ private module Cached {
|
||||
or
|
||||
exists(ArgNode arg |
|
||||
result.(PostUpdateNode).getPreUpdateNode() = arg and
|
||||
arg.argumentOf(call, k.(ParamUpdateReturnKind).getAMatchingArgumentPosition())
|
||||
arg.argumentOf(call, k.(ParamUpdateReturnKind).getPosition())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -344,7 +294,7 @@ private module Cached {
|
||||
predicate returnNodeExt(Node n, ReturnKindExt k) {
|
||||
k = TValueReturn(n.(ReturnNode).getKind())
|
||||
or
|
||||
exists(ParamNode p, ParameterPosition pos |
|
||||
exists(ParamNode p, int pos |
|
||||
parameterValueFlowsToPreUpdate(p, n) and
|
||||
p.isParameterOf(_, pos) and
|
||||
k = TParamUpdate(pos)
|
||||
@@ -366,13 +316,13 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
predicate parameterNode(Node p, DataFlowCallable c, ParameterPosition pos) {
|
||||
isParameterNode(p, c, pos)
|
||||
predicate parameterNode(Node n, DataFlowCallable c, int i) {
|
||||
n.(ParameterNode).isParameterOf(c, i)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate argumentNode(Node n, DataFlowCall call, ArgumentPosition pos) {
|
||||
isArgumentNode(n, call, pos)
|
||||
predicate argumentNode(Node n, DataFlowCall call, int pos) {
|
||||
n.(ArgumentNode).argumentOf(call, pos)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -390,12 +340,12 @@ private module Cached {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `p` is the parameter of a viable dispatch target of `call`,
|
||||
* and `p` has position `ppos`.
|
||||
* Holds if `p` is the `i`th parameter of a viable dispatch target of `call`.
|
||||
* The instance parameter is considered to have index `-1`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate viableParam(DataFlowCall call, ParameterPosition ppos, ParamNode p) {
|
||||
p.isParameterOf(viableCallableExt(call), ppos)
|
||||
private predicate viableParam(DataFlowCall call, int i, ParamNode p) {
|
||||
p.isParameterOf(viableCallableExt(call), i)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -404,9 +354,9 @@ private module Cached {
|
||||
*/
|
||||
cached
|
||||
predicate viableParamArg(DataFlowCall call, ParamNode p, ArgNode arg) {
|
||||
exists(ParameterPosition ppos |
|
||||
viableParam(call, ppos, p) and
|
||||
argumentPositionMatch(call, arg, ppos) and
|
||||
exists(int i |
|
||||
viableParam(call, i, p) and
|
||||
arg.argumentOf(call, i) and
|
||||
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p))
|
||||
)
|
||||
}
|
||||
@@ -851,9 +801,6 @@ private module Cached {
|
||||
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call))
|
||||
}
|
||||
|
||||
cached
|
||||
predicate allowParameterReturnInSelfCached(ParamNode p) { allowParameterReturnInSelf(p) }
|
||||
|
||||
cached
|
||||
newtype TCallContext =
|
||||
TAnyCallContext() or
|
||||
@@ -878,7 +825,7 @@ private module Cached {
|
||||
cached
|
||||
newtype TReturnKindExt =
|
||||
TValueReturn(ReturnKind kind) or
|
||||
TParamUpdate(ParameterPosition pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
|
||||
TParamUpdate(int pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
|
||||
|
||||
cached
|
||||
newtype TBooleanOption =
|
||||
@@ -990,7 +937,7 @@ class CallContextSpecificCall extends CallContextCall, TSpecificCall {
|
||||
}
|
||||
|
||||
override predicate relevantFor(DataFlowCallable callable) {
|
||||
recordDataFlowCallSite(this.getCall(), callable)
|
||||
recordDataFlowCallSite(getCall(), callable)
|
||||
}
|
||||
|
||||
override predicate matchesCall(DataFlowCall call) { call = this.getCall() }
|
||||
@@ -1070,9 +1017,9 @@ class ParamNode extends Node {
|
||||
|
||||
/**
|
||||
* Holds if this node is the parameter of callable `c` at the specified
|
||||
* position.
|
||||
* (zero-based) position.
|
||||
*/
|
||||
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { parameterNode(this, c, pos) }
|
||||
predicate isParameterOf(DataFlowCallable c, int i) { parameterNode(this, c, i) }
|
||||
}
|
||||
|
||||
/** A data-flow node that represents a call argument. */
|
||||
@@ -1080,9 +1027,7 @@ class ArgNode extends Node {
|
||||
ArgNode() { argumentNode(this, _, _) }
|
||||
|
||||
/** Holds if this argument occurs at the given position in the given call. */
|
||||
final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
|
||||
argumentNode(this, call, pos)
|
||||
}
|
||||
final predicate argumentOf(DataFlowCall call, int pos) { argumentNode(this, call, pos) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1128,14 +1073,11 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
|
||||
}
|
||||
|
||||
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
||||
private ParameterPosition pos;
|
||||
private int pos;
|
||||
|
||||
ParamUpdateReturnKind() { this = TParamUpdate(pos) }
|
||||
|
||||
ParameterPosition getPosition() { result = pos }
|
||||
|
||||
pragma[nomagic]
|
||||
ArgumentPosition getAMatchingArgumentPosition() { parameterMatch(pos, result) }
|
||||
int getPosition() { result = pos }
|
||||
|
||||
override string toString() { result = "param update " + pos }
|
||||
}
|
||||
@@ -1294,13 +1236,6 @@ class TypedContent extends MkTypedContent {
|
||||
|
||||
/** Gets a textual representation of this content. */
|
||||
string toString() { result = c.toString() }
|
||||
|
||||
/**
|
||||
* Holds if access paths with this `TypedContent` at their head always should
|
||||
* be tracked at high precision. This disables adaptive access path precision
|
||||
* for such access paths.
|
||||
*/
|
||||
predicate forceHighPrecision() { forceHighPrecision(c) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1315,7 +1250,7 @@ abstract class AccessPathFront extends TAccessPathFront {
|
||||
|
||||
TypedContent getHead() { this = TFrontHead(result) }
|
||||
|
||||
predicate isClearedAt(Node n) { clearsContentCached(n, this.getHead().getContent()) }
|
||||
predicate isClearedAt(Node n) { clearsContentCached(n, getHead().getContent()) }
|
||||
}
|
||||
|
||||
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
|
||||
|
||||
@@ -9,19 +9,6 @@ private import tainttracking1.TaintTrackingParameter::Private
|
||||
private import tainttracking1.TaintTrackingParameter::Public
|
||||
|
||||
module Consistency {
|
||||
private newtype TConsistencyConfiguration = MkConsistencyConfiguration()
|
||||
|
||||
/** A class for configuring the consistency queries. */
|
||||
class ConsistencyConfiguration extends TConsistencyConfiguration {
|
||||
string toString() { none() }
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `postWithInFlow`. */
|
||||
predicate postWithInFlowExclude(Node n) { none() }
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `argHasPostUpdate`. */
|
||||
predicate argHasPostUpdateExclude(ArgumentNode n) { none() }
|
||||
}
|
||||
|
||||
private class RelevantNode extends Node {
|
||||
RelevantNode() {
|
||||
this instanceof ArgumentNode or
|
||||
@@ -44,7 +31,7 @@ module Consistency {
|
||||
query predicate uniqueEnclosingCallable(Node n, string msg) {
|
||||
exists(int c |
|
||||
n instanceof RelevantNode and
|
||||
c = count(nodeGetEnclosingCallable(n)) and
|
||||
c = count(n.getEnclosingCallable()) and
|
||||
c != 1 and
|
||||
msg = "Node should have one enclosing callable but has " + c + "."
|
||||
)
|
||||
@@ -98,13 +85,13 @@ module Consistency {
|
||||
}
|
||||
|
||||
query predicate parameterCallable(ParameterNode p, string msg) {
|
||||
exists(DataFlowCallable c | isParameterNode(p, c, _) and c != nodeGetEnclosingCallable(p)) and
|
||||
exists(DataFlowCallable c | p.isParameterOf(c, _) and c != p.getEnclosingCallable()) and
|
||||
msg = "Callable mismatch for parameter."
|
||||
}
|
||||
|
||||
query predicate localFlowIsLocal(Node n1, Node n2, string msg) {
|
||||
simpleLocalFlowStep(n1, n2) and
|
||||
nodeGetEnclosingCallable(n1) != nodeGetEnclosingCallable(n2) and
|
||||
n1.getEnclosingCallable() != n2.getEnclosingCallable() and
|
||||
msg = "Local flow step does not preserve enclosing callable."
|
||||
}
|
||||
|
||||
@@ -119,7 +106,7 @@ module Consistency {
|
||||
query predicate unreachableNodeCCtx(Node n, DataFlowCall call, string msg) {
|
||||
isUnreachableInCall(n, call) and
|
||||
exists(DataFlowCallable c |
|
||||
c = nodeGetEnclosingCallable(n) and
|
||||
c = n.getEnclosingCallable() and
|
||||
not viableCallable(call) = c
|
||||
) and
|
||||
msg = "Call context for isUnreachableInCall is inconsistent with call graph."
|
||||
@@ -133,7 +120,7 @@ module Consistency {
|
||||
n.(ArgumentNode).argumentOf(call, _) and
|
||||
msg = "ArgumentNode and call does not share enclosing callable."
|
||||
) and
|
||||
nodeGetEnclosingCallable(n) != call.getEnclosingCallable()
|
||||
n.getEnclosingCallable() != call.getEnclosingCallable()
|
||||
}
|
||||
|
||||
// This predicate helps the compiler forget that in some languages
|
||||
@@ -164,7 +151,7 @@ module Consistency {
|
||||
}
|
||||
|
||||
query predicate postIsInSameCallable(PostUpdateNode n, string msg) {
|
||||
nodeGetEnclosingCallable(n) != nodeGetEnclosingCallable(n.getPreUpdateNode()) and
|
||||
n.getEnclosingCallable() != n.getPreUpdateNode().getEnclosingCallable() and
|
||||
msg = "PostUpdateNode does not share callable with its pre-update node."
|
||||
}
|
||||
|
||||
@@ -177,7 +164,7 @@ module Consistency {
|
||||
|
||||
query predicate argHasPostUpdate(ArgumentNode n, string msg) {
|
||||
not hasPost(n) and
|
||||
not any(ConsistencyConfiguration c).argHasPostUpdateExclude(n) and
|
||||
not isImmutableOrUnobservable(n) and
|
||||
msg = "ArgumentNode is missing PostUpdateNode."
|
||||
}
|
||||
|
||||
@@ -188,9 +175,7 @@ module Consistency {
|
||||
|
||||
query predicate postWithInFlow(Node n, string msg) {
|
||||
isPostUpdateNode(n) and
|
||||
not clearsContent(n, _) and
|
||||
simpleLocalFlowStep(_, n) and
|
||||
not any(ConsistencyConfiguration c).postWithInFlowExclude(n) and
|
||||
msg = "PostUpdateNode should not be the target of local flow."
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,20 +2,6 @@ private import cpp
|
||||
private import DataFlowUtil
|
||||
private import DataFlowDispatch
|
||||
private import FlowVar
|
||||
private import DataFlowImplConsistency
|
||||
|
||||
/** Gets the callable in which this node occurs. */
|
||||
DataFlowCallable nodeGetEnclosingCallable(Node n) { result = n.getEnclosingCallable() }
|
||||
|
||||
/** Holds if `p` is a `ParameterNode` of `c` with position `pos`. */
|
||||
predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos) {
|
||||
p.isParameterOf(c, pos)
|
||||
}
|
||||
|
||||
/** Holds if `arg` is an `ArgumentNode` of `c` with position `pos`. */
|
||||
predicate isArgumentNode(ArgumentNode arg, DataFlowCall c, ArgumentPosition pos) {
|
||||
arg.argumentOf(c, pos)
|
||||
}
|
||||
|
||||
/** Gets the instance argument of a non-static call. */
|
||||
private Node getInstanceArgument(Call call) {
|
||||
@@ -233,13 +219,15 @@ class DataFlowExpr = Expr;
|
||||
class DataFlowType = Type;
|
||||
|
||||
/** A function call relevant for data flow. */
|
||||
class DataFlowCall extends Expr instanceof Call {
|
||||
class DataFlowCall extends Expr {
|
||||
DataFlowCall() { this instanceof Call }
|
||||
|
||||
/**
|
||||
* Gets the nth argument for this call.
|
||||
*
|
||||
* The range of `n` is from `0` to `getNumberOfArguments() - 1`.
|
||||
*/
|
||||
Expr getArgument(int n) { result = super.getArgument(n) }
|
||||
Expr getArgument(int n) { result = this.(Call).getArgument(n) }
|
||||
|
||||
/** Gets the data flow node corresponding to this call. */
|
||||
ExprNode getNode() { result.getExpr() = this }
|
||||
@@ -252,12 +240,6 @@ predicate isUnreachableInCall(Node n, DataFlowCall call) { none() } // stub impl
|
||||
|
||||
int accessPathLimit() { result = 5 }
|
||||
|
||||
/**
|
||||
* 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) { none() }
|
||||
|
||||
/** The unit type. */
|
||||
private newtype TUnit = TMkUnit()
|
||||
|
||||
@@ -267,6 +249,27 @@ class Unit extends TUnit {
|
||||
string toString() { result = "unit" }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` does not require a `PostUpdateNode` as it either cannot be
|
||||
* modified or its modification cannot be observed, for example if it is a
|
||||
* freshly created object that is not saved in a variable.
|
||||
*
|
||||
* This predicate is only used for consistency checks.
|
||||
*/
|
||||
predicate isImmutableOrUnobservable(Node n) {
|
||||
// Is the null pointer (or something that's not really a pointer)
|
||||
exists(n.asExpr().getValue())
|
||||
or
|
||||
// Isn't a pointer or is a pointer to const
|
||||
forall(DerivedType dt | dt = n.asExpr().getActualType() |
|
||||
dt.getBaseType().isConst()
|
||||
or
|
||||
dt.getBaseType() instanceof RoutineType
|
||||
)
|
||||
// The above list of cases isn't exhaustive, but it narrows down the
|
||||
// consistency alerts enough that most of them are interesting.
|
||||
}
|
||||
|
||||
/** Holds if `n` should be hidden from path explanations. */
|
||||
predicate nodeIsHidden(Node n) { none() }
|
||||
|
||||
@@ -280,28 +283,3 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { no
|
||||
|
||||
/** Extra data-flow steps needed for lambda flow analysis. */
|
||||
predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() }
|
||||
|
||||
/**
|
||||
* Holds if flow is allowed to pass from parameter `p` and back to itself as a
|
||||
* side-effect, resulting in a summary from `p` to itself.
|
||||
*
|
||||
* One example would be to allow flow like `p.foo = p.bar;`, which is disallowed
|
||||
* by default as a heuristic.
|
||||
*/
|
||||
predicate allowParameterReturnInSelf(ParameterNode p) { none() }
|
||||
|
||||
private class MyConsistencyConfiguration extends Consistency::ConsistencyConfiguration {
|
||||
override predicate argHasPostUpdateExclude(ArgumentNode n) {
|
||||
// Is the null pointer (or something that's not really a pointer)
|
||||
exists(n.asExpr().getValue())
|
||||
or
|
||||
// Isn't a pointer or is a pointer to const
|
||||
forall(DerivedType dt | dt = n.asExpr().getActualType() |
|
||||
dt.getBaseType().isConst()
|
||||
or
|
||||
dt.getBaseType() instanceof RoutineType
|
||||
)
|
||||
// The above list of cases isn't exhaustive, but it narrows down the
|
||||
// consistency alerts enough that most of them are interesting.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,18 +101,18 @@ class Node extends TNode {
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an upper bound on the type of this node.
|
||||
*/
|
||||
Type getTypeBound() { result = this.getType() }
|
||||
Type getTypeBound() { result = getType() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -293,11 +293,11 @@ abstract class PostUpdateNode extends Node {
|
||||
*/
|
||||
abstract Node getPreUpdateNode();
|
||||
|
||||
override Function getFunction() { result = this.getPreUpdateNode().getFunction() }
|
||||
override Function getFunction() { result = getPreUpdateNode().getFunction() }
|
||||
|
||||
override Type getType() { result = this.getPreUpdateNode().getType() }
|
||||
override Type getType() { result = getPreUpdateNode().getType() }
|
||||
|
||||
override Location getLocation() { result = this.getPreUpdateNode().getLocation() }
|
||||
override Location getLocation() { result = getPreUpdateNode().getLocation() }
|
||||
}
|
||||
|
||||
abstract private class PartialDefinitionNode extends PostUpdateNode, TPartialDefinitionNode {
|
||||
@@ -309,7 +309,7 @@ abstract private class PartialDefinitionNode extends PostUpdateNode, TPartialDef
|
||||
|
||||
PartialDefinition getPartialDefinition() { result = pd }
|
||||
|
||||
override string toString() { result = this.getPreUpdateNode().toString() + " [post update]" }
|
||||
override string toString() { result = getPreUpdateNode().toString() + " [post update]" }
|
||||
}
|
||||
|
||||
private class VariablePartialDefinitionNode extends PartialDefinitionNode {
|
||||
@@ -380,13 +380,13 @@ private class ObjectInitializerNode extends PostUpdateNode, TExprNode {
|
||||
class PreObjectInitializerNode extends Node, TPreObjectInitializerNode {
|
||||
Expr getExpr() { this = TPreObjectInitializerNode(result) }
|
||||
|
||||
override Function getFunction() { result = this.getExpr().getEnclosingFunction() }
|
||||
override Function getFunction() { result = getExpr().getEnclosingFunction() }
|
||||
|
||||
override Type getType() { result = this.getExpr().getType() }
|
||||
override Type getType() { result = getExpr().getType() }
|
||||
|
||||
override Location getLocation() { result = this.getExpr().getLocation() }
|
||||
override Location getLocation() { result = getExpr().getLocation() }
|
||||
|
||||
override string toString() { result = this.getExpr().toString() + " [pre init]" }
|
||||
override string toString() { result = getExpr().toString() + " [pre init]" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -401,7 +401,7 @@ private class PostConstructorInitThis extends PostUpdateNode, TPostConstructorIn
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
result = this.getPreUpdateNode().getConstructorFieldInit().toString() + " [post-this]"
|
||||
result = getPreUpdateNode().getConstructorFieldInit().toString() + " [post-this]"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,17 +416,15 @@ private class PostConstructorInitThis extends PostUpdateNode, TPostConstructorIn
|
||||
class PreConstructorInitThis extends Node, TPreConstructorInitThis {
|
||||
ConstructorFieldInit getConstructorFieldInit() { this = TPreConstructorInitThis(result) }
|
||||
|
||||
override Constructor getFunction() {
|
||||
result = this.getConstructorFieldInit().getEnclosingFunction()
|
||||
}
|
||||
override Constructor getFunction() { result = getConstructorFieldInit().getEnclosingFunction() }
|
||||
|
||||
override PointerType getType() {
|
||||
result.getBaseType() = this.getConstructorFieldInit().getEnclosingFunction().getDeclaringType()
|
||||
result.getBaseType() = getConstructorFieldInit().getEnclosingFunction().getDeclaringType()
|
||||
}
|
||||
|
||||
override Location getLocation() { result = this.getConstructorFieldInit().getLocation() }
|
||||
override Location getLocation() { result = getConstructorFieldInit().getLocation() }
|
||||
|
||||
override string toString() { result = this.getConstructorFieldInit().toString() + " [pre-this]" }
|
||||
override string toString() { result = getConstructorFieldInit().toString() + " [pre-this]" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -354,7 +354,7 @@ module FlowVar_internal {
|
||||
result = def.getAUse(v)
|
||||
or
|
||||
exists(SsaDefinition descendentDef |
|
||||
this.getASuccessorSsaVar+() = TSsaVar(descendentDef, _) and
|
||||
getASuccessorSsaVar+() = TSsaVar(descendentDef, _) and
|
||||
result = descendentDef.getAUse(v)
|
||||
)
|
||||
)
|
||||
@@ -515,7 +515,7 @@ module FlowVar_internal {
|
||||
this.bbInLoopCondition(bbInside) and
|
||||
not this.bbInLoop(bbOutside) and
|
||||
bbOutside = bbInside.getASuccessor() and
|
||||
not this.reachesWithoutAssignment(bbInside, v)
|
||||
not reachesWithoutAssignment(bbInside, v)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -546,7 +546,7 @@ module FlowVar_internal {
|
||||
private predicate bbInLoop(BasicBlock bb) {
|
||||
bbDominates(this.(Loop).getStmt(), bb)
|
||||
or
|
||||
this.bbInLoopCondition(bb)
|
||||
bbInLoopCondition(bb)
|
||||
}
|
||||
|
||||
/** Holds if `sbb` is inside this loop. */
|
||||
@@ -563,7 +563,7 @@ module FlowVar_internal {
|
||||
bb = this.(Loop).getStmt() and
|
||||
v = this.getARelevantVariable()
|
||||
or
|
||||
this.reachesWithoutAssignment(bb.getAPredecessor(), v) and
|
||||
reachesWithoutAssignment(bb.getAPredecessor(), v) and
|
||||
this.bbInLoop(bb)
|
||||
) and
|
||||
not assignsToVar(bb, v)
|
||||
|
||||
@@ -80,7 +80,7 @@ class SubBasicBlock extends ControlFlowNodeBase {
|
||||
* returns a 0-based position, while `getRankInBasicBlock` returns a 1-based
|
||||
* position.
|
||||
*/
|
||||
deprecated int getPosInBasicBlock(BasicBlock bb) { result = this.getRankInBasicBlock(bb) - 1 }
|
||||
deprecated int getPosInBasicBlock(BasicBlock bb) { result = getRankInBasicBlock(bb) - 1 }
|
||||
|
||||
pragma[noinline]
|
||||
private int getIndexInBasicBlock(BasicBlock bb) { this = bb.getNode(result) }
|
||||
@@ -102,7 +102,7 @@ class SubBasicBlock extends ControlFlowNodeBase {
|
||||
exists(BasicBlock bb |
|
||||
exists(int outerIndex |
|
||||
result = bb.getNode(outerIndex) and
|
||||
index = this.outerToInnerIndex(bb, outerIndex)
|
||||
index = outerToInnerIndex(bb, outerIndex)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -75,26 +75,24 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
predicate isSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrier(DataFlow::Node node) {
|
||||
this.isSanitizer(node) or
|
||||
isSanitizer(node) or
|
||||
defaultTaintSanitizer(node)
|
||||
}
|
||||
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) }
|
||||
|
||||
/** Holds if taint propagation out of `node` is prohibited. */
|
||||
predicate isSanitizerOut(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) }
|
||||
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard)
|
||||
}
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) }
|
||||
|
||||
/**
|
||||
* Holds if the additional taint propagation step from `node1` to `node2`
|
||||
@@ -103,7 +101,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
|
||||
|
||||
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
this.isAdditionalTaintStep(node1, node2) or
|
||||
isAdditionalTaintStep(node1, node2) or
|
||||
defaultAdditionalTaintStep(node1, node2)
|
||||
}
|
||||
|
||||
|
||||
@@ -75,26 +75,24 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
predicate isSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrier(DataFlow::Node node) {
|
||||
this.isSanitizer(node) or
|
||||
isSanitizer(node) or
|
||||
defaultTaintSanitizer(node)
|
||||
}
|
||||
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) }
|
||||
|
||||
/** Holds if taint propagation out of `node` is prohibited. */
|
||||
predicate isSanitizerOut(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) }
|
||||
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard)
|
||||
}
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) }
|
||||
|
||||
/**
|
||||
* Holds if the additional taint propagation step from `node1` to `node2`
|
||||
@@ -103,7 +101,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
|
||||
|
||||
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
this.isAdditionalTaintStep(node1, node2) or
|
||||
isAdditionalTaintStep(node1, node2) or
|
||||
defaultAdditionalTaintStep(node1, node2)
|
||||
}
|
||||
|
||||
|
||||
@@ -203,7 +203,7 @@ class PointerFieldAccess extends FieldAccess {
|
||||
|
||||
PointerFieldAccess() {
|
||||
exists(PointerType t |
|
||||
t = this.getQualifier().getFullyConverted().getUnspecifiedType() and
|
||||
t = getQualifier().getFullyConverted().getUnspecifiedType() and
|
||||
t.getBaseType() instanceof Class
|
||||
)
|
||||
}
|
||||
@@ -218,9 +218,7 @@ class PointerFieldAccess extends FieldAccess {
|
||||
class DotFieldAccess extends FieldAccess {
|
||||
override string getAPrimaryQlClass() { result = "DotFieldAccess" }
|
||||
|
||||
DotFieldAccess() {
|
||||
exists(Class c | c = this.getQualifier().getFullyConverted().getUnspecifiedType())
|
||||
}
|
||||
DotFieldAccess() { exists(Class c | c = getQualifier().getFullyConverted().getUnspecifiedType()) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -148,7 +148,7 @@ class PostfixIncrExpr extends IncrementOperation, PostfixCrementOperation, @post
|
||||
|
||||
override int getPrecedence() { result = 17 }
|
||||
|
||||
override string toString() { result = "... " + this.getOperator() }
|
||||
override string toString() { result = "... " + getOperator() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -166,7 +166,7 @@ class PostfixDecrExpr extends DecrementOperation, PostfixCrementOperation, @post
|
||||
|
||||
override int getPrecedence() { result = 17 }
|
||||
|
||||
override string toString() { result = "... " + this.getOperator() }
|
||||
override string toString() { result = "... " + getOperator() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,12 +35,12 @@ class BuiltInVarArgsStart extends VarArgsExpr, @vastartexpr {
|
||||
/**
|
||||
* Gets the `va_list` argument.
|
||||
*/
|
||||
final Expr getVAList() { result = this.getChild(0) }
|
||||
final Expr getVAList() { result = getChild(0) }
|
||||
|
||||
/**
|
||||
* Gets the argument that specifies the last named parameter before the ellipsis.
|
||||
*/
|
||||
final VariableAccess getLastNamedParameter() { result = this.getChild(1) }
|
||||
final VariableAccess getLastNamedParameter() { result = getChild(1) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,7 +60,7 @@ class BuiltInVarArgsEnd extends VarArgsExpr, @vaendexpr {
|
||||
/**
|
||||
* Gets the `va_list` argument.
|
||||
*/
|
||||
final Expr getVAList() { result = this.getChild(0) }
|
||||
final Expr getVAList() { result = getChild(0) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,7 +78,7 @@ class BuiltInVarArg extends VarArgsExpr, @vaargexpr {
|
||||
/**
|
||||
* Gets the `va_list` argument.
|
||||
*/
|
||||
final Expr getVAList() { result = this.getChild(0) }
|
||||
final Expr getVAList() { result = getChild(0) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,12 +98,12 @@ class BuiltInVarArgCopy extends VarArgsExpr, @vacopyexpr {
|
||||
/**
|
||||
* Gets the destination `va_list` argument.
|
||||
*/
|
||||
final Expr getDestinationVAList() { result = this.getChild(0) }
|
||||
final Expr getDestinationVAList() { result = getChild(0) }
|
||||
|
||||
/**
|
||||
* Gets the the source `va_list` argument.
|
||||
*/
|
||||
final Expr getSourceVAList() { result = this.getChild(1) }
|
||||
final Expr getSourceVAList() { result = getChild(1) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -71,10 +71,10 @@ class Call extends Expr, NameQualifiableElement, TCall {
|
||||
* at index 2, respectively.
|
||||
*/
|
||||
Expr getAnArgumentSubExpr(int index) {
|
||||
result = this.getArgument(index)
|
||||
result = getArgument(index)
|
||||
or
|
||||
exists(Expr mid |
|
||||
mid = this.getAnArgumentSubExpr(index) and
|
||||
mid = getAnArgumentSubExpr(index) and
|
||||
not mid instanceof Call and
|
||||
not mid instanceof SizeofOperator and
|
||||
result = mid.getAChild()
|
||||
@@ -167,27 +167,27 @@ class FunctionCall extends Call, @funbindexpr {
|
||||
override string getAPrimaryQlClass() { result = "FunctionCall" }
|
||||
|
||||
/** Gets an explicit template argument for this call. */
|
||||
Locatable getAnExplicitTemplateArgument() { result = this.getExplicitTemplateArgument(_) }
|
||||
Locatable getAnExplicitTemplateArgument() { result = getExplicitTemplateArgument(_) }
|
||||
|
||||
/** Gets an explicit template argument value for this call. */
|
||||
Locatable getAnExplicitTemplateArgumentKind() { result = this.getExplicitTemplateArgumentKind(_) }
|
||||
Locatable getAnExplicitTemplateArgumentKind() { result = getExplicitTemplateArgumentKind(_) }
|
||||
|
||||
/** Gets a template argument for this call. */
|
||||
Locatable getATemplateArgument() { result = this.getTarget().getATemplateArgument() }
|
||||
Locatable getATemplateArgument() { result = getTarget().getATemplateArgument() }
|
||||
|
||||
/** Gets a template argument value for this call. */
|
||||
Locatable getATemplateArgumentKind() { result = this.getTarget().getATemplateArgumentKind() }
|
||||
Locatable getATemplateArgumentKind() { result = getTarget().getATemplateArgumentKind() }
|
||||
|
||||
/** Gets the nth explicit template argument for this call. */
|
||||
Locatable getExplicitTemplateArgument(int n) {
|
||||
n < this.getNumberOfExplicitTemplateArguments() and
|
||||
result = this.getTemplateArgument(n)
|
||||
n < getNumberOfExplicitTemplateArguments() and
|
||||
result = getTemplateArgument(n)
|
||||
}
|
||||
|
||||
/** Gets the nth explicit template argument value for this call. */
|
||||
Locatable getExplicitTemplateArgumentKind(int n) {
|
||||
n < this.getNumberOfExplicitTemplateArguments() and
|
||||
result = this.getTemplateArgumentKind(n)
|
||||
n < getNumberOfExplicitTemplateArguments() and
|
||||
result = getTemplateArgumentKind(n)
|
||||
}
|
||||
|
||||
/** Gets the number of explicit template arguments for this call. */
|
||||
@@ -198,19 +198,19 @@ class FunctionCall extends Call, @funbindexpr {
|
||||
}
|
||||
|
||||
/** Gets the number of template arguments for this call. */
|
||||
int getNumberOfTemplateArguments() { result = count(int i | exists(this.getTemplateArgument(i))) }
|
||||
int getNumberOfTemplateArguments() { result = count(int i | exists(getTemplateArgument(i))) }
|
||||
|
||||
/** Gets the nth template argument for this call (indexed from 0). */
|
||||
Locatable getTemplateArgument(int n) { result = this.getTarget().getTemplateArgument(n) }
|
||||
Locatable getTemplateArgument(int n) { result = getTarget().getTemplateArgument(n) }
|
||||
|
||||
/** Gets the nth template argument value for this call (indexed from 0). */
|
||||
Locatable getTemplateArgumentKind(int n) { result = this.getTarget().getTemplateArgumentKind(n) }
|
||||
Locatable getTemplateArgumentKind(int n) { result = getTarget().getTemplateArgumentKind(n) }
|
||||
|
||||
/** Holds if any template arguments for this call are implicit / deduced. */
|
||||
predicate hasImplicitTemplateArguments() {
|
||||
exists(int i |
|
||||
exists(this.getTemplateArgument(i)) and
|
||||
not exists(this.getExplicitTemplateArgument(i))
|
||||
exists(getTemplateArgument(i)) and
|
||||
not exists(getExplicitTemplateArgument(i))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -233,9 +233,9 @@ class FunctionCall extends Call, @funbindexpr {
|
||||
* visible at the call site.
|
||||
*/
|
||||
Type getExpectedReturnType() {
|
||||
if this.getTargetType() instanceof RoutineType
|
||||
then result = this.getTargetType().(RoutineType).getReturnType()
|
||||
else result = this.getTarget().getType()
|
||||
if getTargetType() instanceof RoutineType
|
||||
then result = getTargetType().(RoutineType).getReturnType()
|
||||
else result = getTarget().getType()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -247,9 +247,9 @@ class FunctionCall extends Call, @funbindexpr {
|
||||
* was visible at the call site.
|
||||
*/
|
||||
Type getExpectedParameterType(int n) {
|
||||
if this.getTargetType() instanceof RoutineType
|
||||
then result = this.getTargetType().(RoutineType).getParameterType(n)
|
||||
else result = this.getTarget().getParameter(n).getType()
|
||||
if getTargetType() instanceof RoutineType
|
||||
then result = getTargetType().(RoutineType).getParameterType(n)
|
||||
else result = getTarget().getParameter(n).getType()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -263,7 +263,7 @@ class FunctionCall extends Call, @funbindexpr {
|
||||
/**
|
||||
* Gets the type of this expression, that is, the return type of the function being called.
|
||||
*/
|
||||
override Type getType() { result = this.getExpectedReturnType() }
|
||||
override Type getType() { result = getExpectedReturnType() }
|
||||
|
||||
/**
|
||||
* Holds if this is a call to a virtual function.
|
||||
@@ -280,7 +280,7 @@ class FunctionCall extends Call, @funbindexpr {
|
||||
|
||||
/** Gets a textual representation of this function call. */
|
||||
override string toString() {
|
||||
if exists(this.getTarget())
|
||||
if exists(getTarget())
|
||||
then result = "call to " + this.getTarget().getName()
|
||||
else result = "call to unknown function"
|
||||
}
|
||||
@@ -288,15 +288,15 @@ class FunctionCall extends Call, @funbindexpr {
|
||||
override predicate mayBeImpure() {
|
||||
this.getChild(_).mayBeImpure() or
|
||||
this.getTarget().mayHaveSideEffects() or
|
||||
this.isVirtual() or
|
||||
this.getTarget().getAnAttribute().getName() = "weak"
|
||||
isVirtual() or
|
||||
getTarget().getAnAttribute().getName() = "weak"
|
||||
}
|
||||
|
||||
override predicate mayBeGloballyImpure() {
|
||||
this.getChild(_).mayBeGloballyImpure() or
|
||||
this.getTarget().mayHaveSideEffects() or
|
||||
this.isVirtual() or
|
||||
this.getTarget().getAnAttribute().getName() = "weak"
|
||||
isVirtual() or
|
||||
getTarget().getAnAttribute().getName() = "weak"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,7 +367,7 @@ class OverloadedPointerDereferenceExpr extends FunctionCall {
|
||||
* ```
|
||||
*/
|
||||
class OverloadedArrayExpr extends FunctionCall {
|
||||
OverloadedArrayExpr() { this.getTarget().hasName("operator[]") }
|
||||
OverloadedArrayExpr() { getTarget().hasName("operator[]") }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "OverloadedArrayExpr" }
|
||||
|
||||
@@ -585,7 +585,7 @@ class ConstructorFieldInit extends ConstructorInit, @ctorfieldinit {
|
||||
*/
|
||||
Expr getExpr() { result = this.getChild(0) }
|
||||
|
||||
override string toString() { result = "constructor init of field " + this.getTarget().getName() }
|
||||
override string toString() { result = "constructor init of field " + getTarget().getName() }
|
||||
|
||||
override predicate mayBeImpure() { this.getExpr().mayBeImpure() }
|
||||
|
||||
|
||||
@@ -188,8 +188,8 @@ private predicate isPointerToMemberOrNullPointer(Type type) {
|
||||
class ArithmeticConversion extends Cast {
|
||||
ArithmeticConversion() {
|
||||
conversionkinds(underlyingElement(this), 0) and
|
||||
isArithmeticOrEnum(this.getUnspecifiedType()) and
|
||||
isArithmeticOrEnum(this.getExpr().getUnspecifiedType())
|
||||
isArithmeticOrEnum(getUnspecifiedType()) and
|
||||
isArithmeticOrEnum(getExpr().getUnspecifiedType())
|
||||
}
|
||||
|
||||
override string getSemanticConversionString() { result = "arithmetic conversion" }
|
||||
@@ -204,8 +204,8 @@ class ArithmeticConversion extends Cast {
|
||||
*/
|
||||
class IntegralConversion extends ArithmeticConversion {
|
||||
IntegralConversion() {
|
||||
isIntegralOrEnum(this.getUnspecifiedType()) and
|
||||
isIntegralOrEnum(this.getExpr().getUnspecifiedType())
|
||||
isIntegralOrEnum(getUnspecifiedType()) and
|
||||
isIntegralOrEnum(getExpr().getUnspecifiedType())
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() {
|
||||
@@ -224,8 +224,8 @@ class IntegralConversion extends ArithmeticConversion {
|
||||
*/
|
||||
class FloatingPointConversion extends ArithmeticConversion {
|
||||
FloatingPointConversion() {
|
||||
this.getUnspecifiedType() instanceof FloatingPointType and
|
||||
this.getExpr().getUnspecifiedType() instanceof FloatingPointType
|
||||
getUnspecifiedType() instanceof FloatingPointType and
|
||||
getExpr().getUnspecifiedType() instanceof FloatingPointType
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() {
|
||||
@@ -244,8 +244,8 @@ class FloatingPointConversion extends ArithmeticConversion {
|
||||
*/
|
||||
class FloatingPointToIntegralConversion extends ArithmeticConversion {
|
||||
FloatingPointToIntegralConversion() {
|
||||
isIntegralOrEnum(this.getUnspecifiedType()) and
|
||||
this.getExpr().getUnspecifiedType() instanceof FloatingPointType
|
||||
isIntegralOrEnum(getUnspecifiedType()) and
|
||||
getExpr().getUnspecifiedType() instanceof FloatingPointType
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() {
|
||||
@@ -264,8 +264,8 @@ class FloatingPointToIntegralConversion extends ArithmeticConversion {
|
||||
*/
|
||||
class IntegralToFloatingPointConversion extends ArithmeticConversion {
|
||||
IntegralToFloatingPointConversion() {
|
||||
this.getUnspecifiedType() instanceof FloatingPointType and
|
||||
isIntegralOrEnum(this.getExpr().getUnspecifiedType())
|
||||
getUnspecifiedType() instanceof FloatingPointType and
|
||||
isIntegralOrEnum(getExpr().getUnspecifiedType())
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() {
|
||||
@@ -290,8 +290,8 @@ class IntegralToFloatingPointConversion extends ArithmeticConversion {
|
||||
class PointerConversion extends Cast {
|
||||
PointerConversion() {
|
||||
conversionkinds(underlyingElement(this), 0) and
|
||||
isPointerOrNullPointer(this.getUnspecifiedType()) and
|
||||
isPointerOrNullPointer(this.getExpr().getUnspecifiedType())
|
||||
isPointerOrNullPointer(getUnspecifiedType()) and
|
||||
isPointerOrNullPointer(getExpr().getUnspecifiedType())
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { not exists(qlCast(this)) and result = "PointerConversion" }
|
||||
@@ -315,8 +315,8 @@ class PointerToMemberConversion extends Cast {
|
||||
PointerToMemberConversion() {
|
||||
conversionkinds(underlyingElement(this), 0) and
|
||||
exists(Type fromType, Type toType |
|
||||
fromType = this.getExpr().getUnspecifiedType() and
|
||||
toType = this.getUnspecifiedType() and
|
||||
fromType = getExpr().getUnspecifiedType() and
|
||||
toType = getUnspecifiedType() and
|
||||
isPointerToMemberOrNullPointer(fromType) and
|
||||
isPointerToMemberOrNullPointer(toType) and
|
||||
// A conversion from nullptr to nullptr is a `PointerConversion`, not a
|
||||
@@ -345,8 +345,8 @@ class PointerToMemberConversion extends Cast {
|
||||
class PointerToIntegralConversion extends Cast {
|
||||
PointerToIntegralConversion() {
|
||||
conversionkinds(underlyingElement(this), 0) and
|
||||
isIntegralOrEnum(this.getUnspecifiedType()) and
|
||||
isPointerOrNullPointer(this.getExpr().getUnspecifiedType())
|
||||
isIntegralOrEnum(getUnspecifiedType()) and
|
||||
isPointerOrNullPointer(getExpr().getUnspecifiedType())
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() {
|
||||
@@ -366,8 +366,8 @@ class PointerToIntegralConversion extends Cast {
|
||||
class IntegralToPointerConversion extends Cast {
|
||||
IntegralToPointerConversion() {
|
||||
conversionkinds(underlyingElement(this), 0) and
|
||||
isPointerOrNullPointer(this.getUnspecifiedType()) and
|
||||
isIntegralOrEnum(this.getExpr().getUnspecifiedType())
|
||||
isPointerOrNullPointer(getUnspecifiedType()) and
|
||||
isIntegralOrEnum(getExpr().getUnspecifiedType())
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() {
|
||||
@@ -403,7 +403,7 @@ class BoolConversion extends Cast {
|
||||
class VoidConversion extends Cast {
|
||||
VoidConversion() {
|
||||
conversionkinds(underlyingElement(this), 0) and
|
||||
this.getUnspecifiedType() instanceof VoidType
|
||||
getUnspecifiedType() instanceof VoidType
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { not exists(qlCast(this)) and result = "VoidConversion" }
|
||||
@@ -434,8 +434,8 @@ class InheritanceConversion extends Cast {
|
||||
* conversion is to an indirect virtual base class.
|
||||
*/
|
||||
final ClassDerivation getDerivation() {
|
||||
result.getBaseClass() = this.getBaseClass() and
|
||||
result.getDerivedClass() = this.getDerivedClass()
|
||||
result.getBaseClass() = getBaseClass() and
|
||||
result.getDerivedClass() = getDerivedClass()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -490,12 +490,12 @@ class BaseClassConversion extends InheritanceConversion {
|
||||
|
||||
override Class getBaseClass() { result = getConversionClass(this) }
|
||||
|
||||
override Class getDerivedClass() { result = getConversionClass(this.getExpr()) }
|
||||
override Class getDerivedClass() { result = getConversionClass(getExpr()) }
|
||||
|
||||
/**
|
||||
* Holds if this conversion is to a virtual base class.
|
||||
*/
|
||||
predicate isVirtual() { this.getDerivation().isVirtual() or not exists(this.getDerivation()) }
|
||||
predicate isVirtual() { getDerivation().isVirtual() or not exists(getDerivation()) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -515,7 +515,7 @@ class DerivedClassConversion extends InheritanceConversion {
|
||||
|
||||
override string getSemanticConversionString() { result = "derived class conversion" }
|
||||
|
||||
override Class getBaseClass() { result = getConversionClass(this.getExpr()) }
|
||||
override Class getBaseClass() { result = getConversionClass(getExpr()) }
|
||||
|
||||
override Class getDerivedClass() { result = getConversionClass(this) }
|
||||
}
|
||||
@@ -637,8 +637,8 @@ class DynamicCast extends Cast, @dynamic_cast {
|
||||
*/
|
||||
class UuidofOperator extends Expr, @uuidof {
|
||||
override string toString() {
|
||||
if exists(this.getTypeOperand())
|
||||
then result = "__uuidof(" + this.getTypeOperand().getName() + ")"
|
||||
if exists(getTypeOperand())
|
||||
then result = "__uuidof(" + getTypeOperand().getName() + ")"
|
||||
else result = "__uuidof(0)"
|
||||
}
|
||||
|
||||
|
||||
@@ -26,12 +26,12 @@ class Expr extends StmtParent, @expr {
|
||||
Function getEnclosingFunction() { result = exprEnclosingElement(this) }
|
||||
|
||||
/** Gets the nearest enclosing set of curly braces around this expression in the source, if any. */
|
||||
BlockStmt getEnclosingBlock() { result = this.getEnclosingStmt().getEnclosingBlock() }
|
||||
BlockStmt getEnclosingBlock() { result = getEnclosingStmt().getEnclosingBlock() }
|
||||
|
||||
override Stmt getEnclosingStmt() {
|
||||
result = this.getParent().(Expr).getEnclosingStmt()
|
||||
or
|
||||
result = this.getParent()
|
||||
result = this.getParent().(Stmt)
|
||||
or
|
||||
exists(Expr other | result = other.getEnclosingStmt() and other.getConversion() = this)
|
||||
or
|
||||
@@ -219,13 +219,13 @@ class Expr extends StmtParent, @expr {
|
||||
* Holds if this expression is a _glvalue_. A _glvalue_ is either an _lvalue_ or an
|
||||
* _xvalue_.
|
||||
*/
|
||||
predicate isGLValueCategory() { this.isLValueCategory() or this.isXValueCategory() }
|
||||
predicate isGLValueCategory() { isLValueCategory() or isXValueCategory() }
|
||||
|
||||
/**
|
||||
* Holds if this expression is an _rvalue_. An _rvalue_ is either a _prvalue_ or an
|
||||
* _xvalue_.
|
||||
*/
|
||||
predicate isRValueCategory() { this.isPRValueCategory() or this.isXValueCategory() }
|
||||
predicate isRValueCategory() { isPRValueCategory() or isXValueCategory() }
|
||||
|
||||
/**
|
||||
* Gets a string representation of the value category of the expression.
|
||||
@@ -240,15 +240,15 @@ class Expr extends StmtParent, @expr {
|
||||
* `hasLValueToRvalueConversion()` holds.
|
||||
*/
|
||||
string getValueCategoryString() {
|
||||
this.isLValueCategory() and
|
||||
isLValueCategory() and
|
||||
result = "lvalue"
|
||||
or
|
||||
this.isXValueCategory() and
|
||||
isXValueCategory() and
|
||||
result = "xvalue"
|
||||
or
|
||||
(
|
||||
this.isPRValueCategory() and
|
||||
if this.hasLValueToRValueConversion() then result = "prvalue(load)" else result = "prvalue"
|
||||
isPRValueCategory() and
|
||||
if hasLValueToRValueConversion() then result = "prvalue(load)" else result = "prvalue"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -263,7 +263,7 @@ class Expr extends StmtParent, @expr {
|
||||
* such as an expression inside a sizeof.
|
||||
*/
|
||||
predicate isUnevaluated() {
|
||||
exists(Element e | e = this.getParentWithConversions+() |
|
||||
exists(Element e | e = getParentWithConversions+() |
|
||||
e instanceof SizeofOperator
|
||||
or
|
||||
exists(Expr e2 |
|
||||
@@ -279,7 +279,7 @@ class Expr extends StmtParent, @expr {
|
||||
e instanceof AlignofOperator
|
||||
)
|
||||
or
|
||||
exists(Decltype d | d.getExpr() = this.getParentWithConversions*())
|
||||
exists(Decltype d | d.getExpr() = getParentWithConversions*())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -725,7 +725,7 @@ class PointerDereferenceExpr extends UnaryOperation, @indirect {
|
||||
*
|
||||
* Gets the expression that is being dereferenced.
|
||||
*/
|
||||
deprecated Expr getExpr() { result = this.getOperand() }
|
||||
deprecated Expr getExpr() { result = getOperand() }
|
||||
|
||||
override string getOperator() { result = "*" }
|
||||
|
||||
@@ -780,15 +780,15 @@ class NewOrNewArrayExpr extends Expr, @any_new_expr {
|
||||
* Gets the alignment argument passed to the allocation function, if any.
|
||||
*/
|
||||
Expr getAlignmentArgument() {
|
||||
this.hasAlignedAllocation() and
|
||||
hasAlignedAllocation() and
|
||||
(
|
||||
// If we have an allocator call, the alignment is the second argument to
|
||||
// that call.
|
||||
result = this.getAllocatorCall().getArgument(1)
|
||||
result = getAllocatorCall().getArgument(1)
|
||||
or
|
||||
// Otherwise, the alignment winds up as child number 3 of the `new`
|
||||
// itself.
|
||||
result = this.getChild(3)
|
||||
result = getChild(3)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -916,7 +916,7 @@ class NewArrayExpr extends NewOrNewArrayExpr, @new_array_expr {
|
||||
* Gets the element type of the array being allocated.
|
||||
*/
|
||||
Type getAllocatedElementType() {
|
||||
result = this.getType().getUnderlyingType().(PointerType).getBaseType()
|
||||
result = getType().getUnderlyingType().(PointerType).getBaseType()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -946,12 +946,7 @@ class DeleteExpr extends Expr, @delete_expr {
|
||||
*/
|
||||
Type getDeletedObjectType() {
|
||||
result =
|
||||
this.getExpr()
|
||||
.getFullyConverted()
|
||||
.getType()
|
||||
.stripTopLevelSpecifiers()
|
||||
.(PointerType)
|
||||
.getBaseType()
|
||||
getExpr().getFullyConverted().getType().stripTopLevelSpecifiers().(PointerType).getBaseType()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -962,7 +957,7 @@ class DeleteExpr extends Expr, @delete_expr {
|
||||
/**
|
||||
* Gets the destructor to be called to destroy the object, if any.
|
||||
*/
|
||||
Destructor getDestructor() { result = this.getDestructorCall().getTarget() }
|
||||
Destructor getDestructor() { result = getDestructorCall().getTarget() }
|
||||
|
||||
/**
|
||||
* Gets the `operator delete` that deallocates storage. Does not hold
|
||||
@@ -1025,12 +1020,7 @@ class DeleteArrayExpr extends Expr, @delete_array_expr {
|
||||
*/
|
||||
Type getDeletedElementType() {
|
||||
result =
|
||||
this.getExpr()
|
||||
.getFullyConverted()
|
||||
.getType()
|
||||
.stripTopLevelSpecifiers()
|
||||
.(PointerType)
|
||||
.getBaseType()
|
||||
getExpr().getFullyConverted().getType().stripTopLevelSpecifiers().(PointerType).getBaseType()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1044,7 +1034,7 @@ class DeleteArrayExpr extends Expr, @delete_array_expr {
|
||||
/**
|
||||
* Gets the destructor to be called to destroy each element in the array, if any.
|
||||
*/
|
||||
Destructor getDestructor() { result = this.getDestructorCall().getTarget() }
|
||||
Destructor getDestructor() { result = getDestructorCall().getTarget() }
|
||||
|
||||
/**
|
||||
* Gets the `operator delete[]` that deallocates storage.
|
||||
@@ -1111,7 +1101,7 @@ class StmtExpr extends Expr, @expr_stmt {
|
||||
* x = ({ dosomething(); a+b; });
|
||||
* ```
|
||||
*/
|
||||
Expr getResultExpr() { result = getStmtResultExpr(this.getStmt()) }
|
||||
Expr getResultExpr() { result = getStmtResultExpr(getStmt()) }
|
||||
}
|
||||
|
||||
/** Get the result expression of a statement. (Helper function for StmtExpr.) */
|
||||
@@ -1240,20 +1230,20 @@ class FoldExpr extends Expr, @foldexpr {
|
||||
predicate isRightFold() { fold(underlyingElement(this), _, false) }
|
||||
|
||||
/** Holds if this is a unary fold expression. */
|
||||
predicate isUnaryFold() { this.getNumChild() = 1 }
|
||||
predicate isUnaryFold() { getNumChild() = 1 }
|
||||
|
||||
/** Holds if this is a binary fold expression. */
|
||||
predicate isBinaryFold() { this.getNumChild() = 2 }
|
||||
predicate isBinaryFold() { getNumChild() = 2 }
|
||||
|
||||
/**
|
||||
* Gets the child expression containing the unexpanded parameter pack.
|
||||
*/
|
||||
Expr getPackExpr() {
|
||||
this.isUnaryFold() and
|
||||
result = this.getChild(0)
|
||||
result = getChild(0)
|
||||
or
|
||||
this.isBinaryFold() and
|
||||
if this.isRightFold() then result = this.getChild(0) else result = this.getChild(1)
|
||||
if this.isRightFold() then result = getChild(0) else result = getChild(1)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1261,7 +1251,7 @@ class FoldExpr extends Expr, @foldexpr {
|
||||
*/
|
||||
Expr getInitExpr() {
|
||||
this.isBinaryFold() and
|
||||
if this.isRightFold() then result = this.getChild(1) else result = this.getChild(0)
|
||||
if this.isRightFold() then result = getChild(1) else result = getChild(0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ class LambdaExpression extends Expr, @lambdaexpr {
|
||||
/**
|
||||
* Gets an implicitly or explicitly captured value of this lambda expression.
|
||||
*/
|
||||
LambdaCapture getACapture() { result = this.getCapture(_) }
|
||||
LambdaCapture getACapture() { result = getCapture(_) }
|
||||
|
||||
/**
|
||||
* Gets the nth implicitly or explicitly captured value of this lambda expression.
|
||||
@@ -58,13 +58,13 @@ class LambdaExpression extends Expr, @lambdaexpr {
|
||||
* - The return type.
|
||||
* - The statements comprising the lambda body.
|
||||
*/
|
||||
Operator getLambdaFunction() { result = this.getType().(Closure).getLambdaFunction() }
|
||||
Operator getLambdaFunction() { result = getType().(Closure).getLambdaFunction() }
|
||||
|
||||
/**
|
||||
* Gets the initializer that initializes the captured variables in the closure, if any.
|
||||
* A lambda that does not capture any variables will not have an initializer.
|
||||
*/
|
||||
ClassAggregateLiteral getInitializer() { result = this.getChild(0) }
|
||||
ClassAggregateLiteral getInitializer() { result = getChild(0) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,7 +103,7 @@ class Closure extends Class {
|
||||
* ```
|
||||
*/
|
||||
class LambdaCapture extends Locatable, @lambdacapture {
|
||||
override string toString() { result = this.getField().getName() }
|
||||
override string toString() { result = getField().getName() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LambdaCapture" }
|
||||
|
||||
|
||||
@@ -60,12 +60,12 @@ class TextLiteral extends Literal {
|
||||
|
||||
/** Gets a hex escape sequence that appears in the character or string literal (see [lex.ccon] in the C++ Standard). */
|
||||
string getAHexEscapeSequence(int occurrence, int offset) {
|
||||
result = this.getValueText().regexpFind("(?<!\\\\)\\\\x[0-9a-fA-F]+", occurrence, offset)
|
||||
result = getValueText().regexpFind("(?<!\\\\)\\\\x[0-9a-fA-F]+", occurrence, offset)
|
||||
}
|
||||
|
||||
/** Gets an octal escape sequence that appears in the character or string literal (see [lex.ccon] in the C++ Standard). */
|
||||
string getAnOctalEscapeSequence(int occurrence, int offset) {
|
||||
result = this.getValueText().regexpFind("(?<!\\\\)\\\\[0-7]{1,3}", occurrence, offset)
|
||||
result = getValueText().regexpFind("(?<!\\\\)\\\\[0-7]{1,3}", occurrence, offset)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,27 +75,27 @@ class TextLiteral extends Literal {
|
||||
string getANonStandardEscapeSequence(int occurrence, int offset) {
|
||||
// Find all single character escape sequences (ignoring the start of octal escape sequences),
|
||||
// together with anything starting like a hex escape sequence but not followed by a hex digit.
|
||||
result = this.getValueText().regexpFind("\\\\[^x0-7\\s]|\\\\x[^0-9a-fA-F]", occurrence, offset) and
|
||||
result = getValueText().regexpFind("\\\\[^x0-7\\s]|\\\\x[^0-9a-fA-F]", occurrence, offset) and
|
||||
// From these, exclude all standard escape sequences.
|
||||
not result = this.getAStandardEscapeSequence(_, _)
|
||||
not result = getAStandardEscapeSequence(_, _)
|
||||
}
|
||||
|
||||
/** Gets a simple escape sequence that appears in the char or string literal (see [lex.ccon] in the C++ Standard). */
|
||||
string getASimpleEscapeSequence(int occurrence, int offset) {
|
||||
result = this.getValueText().regexpFind("\\\\['\"?\\\\abfnrtv]", occurrence, offset)
|
||||
result = getValueText().regexpFind("\\\\['\"?\\\\abfnrtv]", occurrence, offset)
|
||||
}
|
||||
|
||||
/** Gets a standard escape sequence that appears in the char or string literal (see [lex.ccon] in the C++ Standard). */
|
||||
string getAStandardEscapeSequence(int occurrence, int offset) {
|
||||
result = this.getASimpleEscapeSequence(occurrence, offset) or
|
||||
result = this.getAnOctalEscapeSequence(occurrence, offset) or
|
||||
result = this.getAHexEscapeSequence(occurrence, offset)
|
||||
result = getASimpleEscapeSequence(occurrence, offset) or
|
||||
result = getAnOctalEscapeSequence(occurrence, offset) or
|
||||
result = getAHexEscapeSequence(occurrence, offset)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the length of the string literal (including null) before escape sequences added by the extractor.
|
||||
*/
|
||||
int getOriginalLength() { result = this.getValue().length() + 1 }
|
||||
int getOriginalLength() { result = getValue().length() + 1 }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -216,7 +216,7 @@ class ClassAggregateLiteral extends AggregateLiteral {
|
||||
(
|
||||
// If the field has an explicit initializer expression, then the field is
|
||||
// initialized.
|
||||
exists(this.getFieldExpr(field))
|
||||
exists(getFieldExpr(field))
|
||||
or
|
||||
// If the type is not a union, all fields without initializers are value
|
||||
// initialized.
|
||||
@@ -224,7 +224,7 @@ class ClassAggregateLiteral extends AggregateLiteral {
|
||||
or
|
||||
// If the type is a union, and there are no explicit initializers, then
|
||||
// the first declared field is value initialized.
|
||||
not exists(this.getAChild()) and
|
||||
not exists(getAChild()) and
|
||||
field.getInitializationOrder() = 0
|
||||
)
|
||||
}
|
||||
@@ -239,8 +239,8 @@ class ClassAggregateLiteral extends AggregateLiteral {
|
||||
*/
|
||||
pragma[inline]
|
||||
predicate isValueInitialized(Field field) {
|
||||
this.isInitialized(field) and
|
||||
not exists(this.getFieldExpr(field))
|
||||
isInitialized(field) and
|
||||
not exists(getFieldExpr(field))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,7 +285,7 @@ class ArrayOrVectorAggregateLiteral extends AggregateLiteral {
|
||||
bindingset[elementIndex]
|
||||
predicate isInitialized(int elementIndex) {
|
||||
elementIndex >= 0 and
|
||||
elementIndex < this.getArraySize()
|
||||
elementIndex < getArraySize()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -298,8 +298,8 @@ class ArrayOrVectorAggregateLiteral extends AggregateLiteral {
|
||||
*/
|
||||
bindingset[elementIndex]
|
||||
predicate isValueInitialized(int elementIndex) {
|
||||
this.isInitialized(elementIndex) and
|
||||
not exists(this.getElementExpr(elementIndex))
|
||||
isInitialized(elementIndex) and
|
||||
not exists(getElementExpr(elementIndex))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ private predicate addressConstantVariable(Variable v) {
|
||||
private predicate constantAddressLValue(Expr lvalue) {
|
||||
lvalue.(VariableAccess).getTarget() =
|
||||
any(Variable v |
|
||||
v.isStatic()
|
||||
v.(Variable).isStatic()
|
||||
or
|
||||
v instanceof GlobalOrNamespaceVariable
|
||||
)
|
||||
|
||||
@@ -173,7 +173,7 @@ class LocalVariable extends LocalScopeVariable, @localvariable { }
|
||||
class VariableDeclarationEntry extends @var_decl {
|
||||
string toString() { result = "QualifiedName DeclarationEntry" }
|
||||
|
||||
Variable getDeclaration() { result = this.getVariable() }
|
||||
Variable getDeclaration() { result = getVariable() }
|
||||
|
||||
/**
|
||||
* Gets the variable which is being declared or defined.
|
||||
|
||||
@@ -4,7 +4,7 @@ private import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
|
||||
private import semmle.code.cpp.ir.dataflow.DataFlow3
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.ir.dataflow.ResolveCall
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowDispatch as Dispatch
|
||||
private import semmle.code.cpp.controlflow.IRGuards
|
||||
private import semmle.code.cpp.models.interfaces.Taint
|
||||
private import semmle.code.cpp.models.interfaces.DataFlow
|
||||
@@ -355,6 +355,20 @@ predicate taintedIncludingGlobalVars(Expr source, Element tainted, string global
|
||||
*/
|
||||
GlobalOrNamespaceVariable globalVarFromId(string id) { id = result.getQualifiedName() }
|
||||
|
||||
/**
|
||||
* Resolve potential target function(s) for `call`.
|
||||
*
|
||||
* If `call` is a call through a function pointer (`ExprCall`) or
|
||||
* targets a virtual method, simple data flow analysis is performed
|
||||
* in order to identify target(s).
|
||||
*/
|
||||
Function resolveCall(Call call) {
|
||||
exists(CallInstruction callInstruction |
|
||||
callInstruction.getAST() = call and
|
||||
result = Dispatch::viableCallable(callInstruction)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides definitions for augmenting source/sink pairs with data-flow paths
|
||||
* between them. From a `@kind path-problem` query, import this module in the
|
||||
@@ -465,7 +479,7 @@ module TaintedWithPath {
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
@@ -474,25 +488,6 @@ module TaintedWithPath {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
module Private {
|
||||
/** Gets a predecessor `PathNode` of `pathNode`, if any. */
|
||||
PathNode getAPredecessor(PathNode pathNode) { edges(result, pathNode) }
|
||||
|
||||
/** Gets the element that `pathNode` wraps, if any. */
|
||||
Element getElementFromPathNode(PathNode pathNode) {
|
||||
exists(DataFlow::Node node | node = pathNode.(WrapPathNode).inner().getNode() |
|
||||
result = node.asInstruction().getAST()
|
||||
or
|
||||
result = node.asOperand().getDef().getAST()
|
||||
)
|
||||
or
|
||||
result = pathNode.(EndpointPathNode).inner()
|
||||
}
|
||||
}
|
||||
|
||||
private class WrapPathNode extends PathNode, TWrapPathNode {
|
||||
DataFlow3::PathNode inner() { this = TWrapPathNode(result) }
|
||||
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/**
|
||||
* Provides a predicate for non-contextual virtual dispatch and function
|
||||
* pointer resolution.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
private import semmle.code.cpp.ir.ValueNumbering
|
||||
private import internal.DataFlowDispatch
|
||||
private import semmle.code.cpp.ir.IR
|
||||
|
||||
/**
|
||||
* Resolve potential target function(s) for `call`.
|
||||
*
|
||||
* If `call` is a call through a function pointer (`ExprCall`) or its target is
|
||||
* a virtual member function, simple data flow analysis is performed in order
|
||||
* to identify the possible target(s).
|
||||
*/
|
||||
Function resolveCall(Call call) {
|
||||
exists(CallInstruction callInstruction |
|
||||
callInstruction.getAST() = call and
|
||||
result = viableCallable(callInstruction)
|
||||
)
|
||||
}
|
||||
@@ -2,7 +2,6 @@ private import cpp
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
|
||||
private import DataFlowImplCommon as DataFlowImplCommon
|
||||
|
||||
/**
|
||||
@@ -64,10 +63,8 @@ private module VirtualDispatch {
|
||||
|
|
||||
// Call argument
|
||||
exists(DataFlowCall call, int i |
|
||||
other
|
||||
.(DataFlow::ParameterNode)
|
||||
.isParameterOf(pragma[only_bind_into](call).getStaticCallTarget(), i) and
|
||||
src.(ArgumentNode).argumentOf(call, pragma[only_bind_into](pragma[only_bind_out](i)))
|
||||
other.(DataFlow::ParameterNode).isParameterOf(call.getStaticCallTarget(), i) and
|
||||
src.(ArgumentNode).argumentOf(call, i)
|
||||
) and
|
||||
allowOtherFromArg = true and
|
||||
allowFromArg = true
|
||||
@@ -131,7 +128,6 @@ private module VirtualDispatch {
|
||||
*
|
||||
* Used to fix a join ordering issue in flowsFrom.
|
||||
*/
|
||||
pragma[noinline]
|
||||
private predicate returnNodeWithKindAndEnclosingCallable(
|
||||
ReturnNode node, ReturnKind kind, DataFlowCallable callable
|
||||
) {
|
||||
@@ -267,17 +263,3 @@ Function viableImplInCallContext(CallInstruction call, CallInstruction ctx) {
|
||||
result = ctx.getArgument(i).getUnconvertedResultExpression().(FunctionAccess).getTarget()
|
||||
)
|
||||
}
|
||||
|
||||
/** A parameter position represented by an integer. */
|
||||
class ParameterPosition extends int {
|
||||
ParameterPosition() { any(ParameterNode p).isParameterOf(_, this) }
|
||||
}
|
||||
|
||||
/** An argument position represented by an integer. */
|
||||
class ArgumentPosition extends int {
|
||||
ArgumentPosition() { any(ArgumentNode a).argumentOf(_, this) }
|
||||
}
|
||||
|
||||
/** Holds if arguments at position `apos` match parameters at position `ppos`. */
|
||||
pragma[inline]
|
||||
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos }
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user