mirror of
https://github.com/github/codeql.git
synced 2026-03-06 15:49:08 +01:00
Merge branch 'main' into redsun82/bazel-cmake
This commit is contained in:
8
.bazelrc
8
.bazelrc
@@ -1,4 +1,12 @@
|
||||
common --enable_platform_specific_config
|
||||
common --enable_bzlmod
|
||||
# because we use --override_module with `%workspace%`, the lock file is not stable
|
||||
common --lockfile_mode=off
|
||||
|
||||
# when building from this repository in isolation, the internal repository will not be found at ..
|
||||
# where `MODULE.bazel` looks for it. The following will get us past the module loading phase, so
|
||||
# that we can build things that do not rely on that
|
||||
common --override_module=semmle_code=%workspace%/misc/bazel/semmle_code_stub
|
||||
|
||||
build --repo_env=CC=clang --repo_env=CXX=clang++
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
6.3.1
|
||||
7.0.2
|
||||
|
||||
4
.gitattributes
vendored
4
.gitattributes
vendored
@@ -74,3 +74,7 @@ javascript/ql/experimental/adaptivethreatmodeling/test/endpoint_large_scale/auto
|
||||
|
||||
# Auto-generated modeling for Python
|
||||
python/ql/lib/semmle/python/frameworks/data/internal/subclass-capture/*.yml linguist-generated=true
|
||||
|
||||
# auto-generated bazel lock file
|
||||
ruby/extractor/cargo-bazel-lock.json linguist-generated=true
|
||||
ruby/extractor/cargo-bazel-lock.json -merge
|
||||
|
||||
3
.github/workflows/check-change-note.yml
vendored
3
.github/workflows/check-change-note.yml
vendored
@@ -1,5 +1,8 @@
|
||||
name: Check change note
|
||||
|
||||
permissions:
|
||||
pull-requests: read
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [labeled, unlabeled, opened, synchronize, reopened, ready_for_review]
|
||||
|
||||
3
.github/workflows/check-implicit-this.yml
vendored
3
.github/workflows/check-implicit-this.yml
vendored
@@ -9,6 +9,9 @@ on:
|
||||
- main
|
||||
- "rc/*"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
3
.github/workflows/check-qldoc.yml
vendored
3
.github/workflows/check-qldoc.yml
vendored
@@ -10,6 +10,9 @@ on:
|
||||
- main
|
||||
- "rc/*"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
qldoc:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
3
.github/workflows/check-query-ids.yml
vendored
3
.github/workflows/check-query-ids.yml
vendored
@@ -11,6 +11,9 @@ on:
|
||||
- "rc/*"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
check:
|
||||
name: Check query IDs
|
||||
|
||||
3
.github/workflows/close-stale.yml
vendored
3
.github/workflows/close-stale.yml
vendored
@@ -5,6 +5,9 @@ on:
|
||||
schedule:
|
||||
- cron: "30 1 * * *"
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
if: github.repository == 'github/codeql'
|
||||
|
||||
6
.github/workflows/compile-queries.yml
vendored
6
.github/workflows/compile-queries.yml
vendored
@@ -8,8 +8,12 @@ on:
|
||||
- "codeql-cli-*"
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
compile-queries:
|
||||
if: github.repository_owner == 'github'
|
||||
runs-on: ubuntu-latest-xl
|
||||
|
||||
steps:
|
||||
@@ -24,7 +28,7 @@ jobs:
|
||||
with:
|
||||
key: all-queries
|
||||
- name: check formatting
|
||||
run: find */ql -type f \( -name "*.qll" -o -name "*.ql" \) -print0 | xargs -0 -n 3000 -P 10 codeql query format -q --check-only
|
||||
run: find shared */ql -type f \( -name "*.qll" -o -name "*.ql" \) -print0 | xargs -0 -n 3000 -P 10 codeql query format -q --check-only
|
||||
- name: compile queries - check-only
|
||||
# run with --check-only if running in a PR (github.sha != main)
|
||||
if : ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
4
.github/workflows/csharp-qltest.yml
vendored
4
.github/workflows/csharp-qltest.yml
vendored
@@ -25,6 +25,9 @@ defaults:
|
||||
run:
|
||||
working-directory: csharp
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
qlupgrade:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -46,6 +49,7 @@ jobs:
|
||||
xargs codeql execute upgrades testdb
|
||||
diff -q testdb/semmlecode.csharp.dbscheme downgrades/initial/semmlecode.csharp.dbscheme
|
||||
qltest:
|
||||
if: github.repository_owner == 'github'
|
||||
runs-on: ubuntu-latest-xl
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
4
.github/workflows/csv-coverage-metrics.yml
vendored
4
.github/workflows/csv-coverage-metrics.yml
vendored
@@ -14,6 +14,10 @@ on:
|
||||
- ".github/workflows/csv-coverage-metrics.yml"
|
||||
- ".github/actions/fetch-codeql/action.yml"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
jobs:
|
||||
publish-java:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -19,6 +19,10 @@ on:
|
||||
- main
|
||||
- "rc/*"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
jobs:
|
||||
generate:
|
||||
name: Generate framework coverage artifacts
|
||||
|
||||
@@ -6,6 +6,10 @@ on:
|
||||
types:
|
||||
- completed
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
check:
|
||||
name: Check framework coverage differences and comment
|
||||
|
||||
@@ -3,6 +3,9 @@ name: Build framework coverage timeseries reports
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
4
.github/workflows/csv-coverage-update.yml
vendored
4
.github/workflows/csv-coverage-update.yml
vendored
@@ -5,6 +5,10 @@ on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
update:
|
||||
name: Update framework coverage report
|
||||
|
||||
3
.github/workflows/csv-coverage.yml
vendored
3
.github/workflows/csv-coverage.yml
vendored
@@ -7,6 +7,9 @@ on:
|
||||
description: "github/codeql repo SHA used for looking up the CSV models"
|
||||
required: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
5
.github/workflows/fast-forward.yml
vendored
5
.github/workflows/fast-forward.yml
vendored
@@ -7,13 +7,14 @@ name: Fast-forward tracking branch for selected CodeQL version
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
fast-forward:
|
||||
name: Fast-forward tracking branch for selected CodeQL version
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'github/codeql'
|
||||
permissions:
|
||||
contents: write
|
||||
env:
|
||||
BRANCH_NAME: 'lgtm.com'
|
||||
steps:
|
||||
|
||||
9
.github/workflows/go-tests-other-os.yml
vendored
9
.github/workflows/go-tests-other-os.yml
vendored
@@ -8,7 +8,11 @@ on:
|
||||
- .github/actions/**
|
||||
- codeql-workspace.yml
|
||||
env:
|
||||
GO_VERSION: '~1.21.0'
|
||||
GO_VERSION: '~1.22.0'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test-mac:
|
||||
name: Test MacOS
|
||||
@@ -18,6 +22,7 @@ jobs:
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache: false
|
||||
id: go
|
||||
|
||||
- name: Check out code
|
||||
@@ -46,6 +51,7 @@ jobs:
|
||||
make test cache="${{ steps.query-cache.outputs.cache-dir }}"
|
||||
|
||||
test-win:
|
||||
if: github.repository_owner == 'github'
|
||||
name: Test Windows
|
||||
runs-on: windows-latest-xl
|
||||
steps:
|
||||
@@ -53,6 +59,7 @@ jobs:
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache: false
|
||||
id: go
|
||||
|
||||
- name: Check out code
|
||||
|
||||
9
.github/workflows/go-tests.yml
vendored
9
.github/workflows/go-tests.yml
vendored
@@ -15,10 +15,16 @@ on:
|
||||
- .github/workflows/go-tests.yml
|
||||
- .github/actions/**
|
||||
- codeql-workspace.yml
|
||||
|
||||
env:
|
||||
GO_VERSION: '~1.21.0'
|
||||
GO_VERSION: '~1.22.0'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test-linux:
|
||||
if: github.repository_owner == 'github'
|
||||
name: Test Linux (Ubuntu)
|
||||
runs-on: ubuntu-latest-xl
|
||||
steps:
|
||||
@@ -26,6 +32,7 @@ jobs:
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache: false
|
||||
id: go
|
||||
|
||||
- name: Check out code
|
||||
|
||||
7
.github/workflows/labeler.yml
vendored
7
.github/workflows/labeler.yml
vendored
@@ -2,11 +2,12 @@ name: "Pull Request Labeler"
|
||||
on:
|
||||
- pull_request_target
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
triage:
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/labeler@v4
|
||||
|
||||
3
.github/workflows/mad_regenerate-models.yml
vendored
3
.github/workflows/mad_regenerate-models.yml
vendored
@@ -11,6 +11,9 @@ on:
|
||||
- ".github/workflows/mad_regenerate-models.yml"
|
||||
- ".github/actions/fetch-codeql/action.yml"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
regenerate-models:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
2
.github/workflows/qhelp-pr-preview.yml
vendored
2
.github/workflows/qhelp-pr-preview.yml
vendored
@@ -77,7 +77,7 @@ jobs:
|
||||
done < "${RUNNER_TEMP}/paths.txt" >> comment_body.txt
|
||||
exit "${EXIT_CODE}"
|
||||
|
||||
- if: always()
|
||||
- if: ${{ !cancelled() }}
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: comment
|
||||
|
||||
9
.github/workflows/ql-for-ql-build.yml
vendored
9
.github/workflows/ql-for-ql-build.yml
vendored
@@ -9,8 +9,13 @@ on:
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
if: github.repository_owner == 'github'
|
||||
runs-on: ubuntu-latest-xl
|
||||
steps:
|
||||
### Build the queries ###
|
||||
@@ -19,7 +24,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
- name: Find codeql
|
||||
id: find-codeql
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@main
|
||||
with:
|
||||
languages: javascript # does not matter
|
||||
- uses: ./.github/actions/os-version
|
||||
@@ -65,7 +70,7 @@ jobs:
|
||||
exclude:*/ql/lib/upgrades/
|
||||
exclude:java/ql/integration-tests
|
||||
- name: Upload sarif to code-scanning
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
uses: github/codeql-action/upload-sarif@main
|
||||
with:
|
||||
sarif_file: ql-for-ql.sarif
|
||||
category: ql-for-ql
|
||||
|
||||
@@ -11,6 +11,10 @@ on:
|
||||
- ql/ql/src/ql.dbscheme
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
security-events: read
|
||||
|
||||
jobs:
|
||||
measure:
|
||||
env:
|
||||
@@ -25,7 +29,7 @@ jobs:
|
||||
|
||||
- name: Find codeql
|
||||
id: find-codeql
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@main
|
||||
with:
|
||||
languages: javascript # does not matter
|
||||
- uses: ./.github/actions/os-version
|
||||
|
||||
7
.github/workflows/ql-for-ql-tests.yml
vendored
7
.github/workflows/ql-for-ql-tests.yml
vendored
@@ -17,6 +17,9 @@ on:
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
qltest:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -24,7 +27,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Find codeql
|
||||
id: find-codeql
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@main
|
||||
with:
|
||||
languages: javascript # does not matter
|
||||
- uses: ./.github/actions/os-version
|
||||
@@ -69,7 +72,7 @@ jobs:
|
||||
echo "/usr/local/opt/gnu-tar/libexec/gnubin" >> $GITHUB_PATH
|
||||
- name: Find codeql
|
||||
id: find-codeql
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@main
|
||||
with:
|
||||
languages: javascript # does not matter
|
||||
- uses: ./.github/actions/os-version
|
||||
|
||||
3
.github/workflows/query-list.yml
vendored
3
.github/workflows/query-list.yml
vendored
@@ -13,6 +13,9 @@ on:
|
||||
- '.github/actions/fetch-codeql/action.yml'
|
||||
- 'misc/scripts/generate-code-scanning-query-list.py'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
|
||||
77
.github/workflows/ruby-build.yml
vendored
77
.github/workflows/ruby-build.yml
vendored
@@ -32,6 +32,9 @@ defaults:
|
||||
run:
|
||||
working-directory: ruby
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
@@ -48,9 +51,11 @@ jobs:
|
||||
run: |
|
||||
brew install gnu-tar
|
||||
echo "/usr/local/opt/gnu-tar/libexec/gnubin" >> $GITHUB_PATH
|
||||
- name: Install cargo-cross
|
||||
if: runner.os == 'Linux'
|
||||
run: cargo install cross --version 0.2.5
|
||||
- name: Prepare Windows
|
||||
if: runner.os == 'Windows'
|
||||
shell: powershell
|
||||
run: |
|
||||
git config --global core.longpaths true
|
||||
- uses: ./.github/actions/os-version
|
||||
id: os_version
|
||||
- name: Cache entire extractor
|
||||
@@ -79,16 +84,8 @@ jobs:
|
||||
- name: Run tests
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
run: cd extractor && cargo test --verbose
|
||||
# On linux, build the extractor via cross in a centos7 container.
|
||||
# This ensures we don't depend on glibc > 2.17.
|
||||
- name: Release build (linux)
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true' && runner.os == 'Linux'
|
||||
run: |
|
||||
cd extractor
|
||||
cross build --release
|
||||
mv target/x86_64-unknown-linux-gnu/release/codeql-extractor-ruby target/release/
|
||||
- name: Release build (windows and macos)
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true' && runner.os != 'Linux'
|
||||
- name: Release build
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
run: cd extractor && cargo build --release
|
||||
- name: Generate dbscheme
|
||||
if: ${{ matrix.os == 'ubuntu-latest' && steps.cache-extractor.outputs.cache-hit != 'true'}}
|
||||
@@ -111,6 +108,7 @@ jobs:
|
||||
ruby/extractor/target/release/codeql-extractor-ruby.exe
|
||||
retention-days: 1
|
||||
compile-queries:
|
||||
if: github.repository_owner == 'github'
|
||||
runs-on: ubuntu-latest-xl
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -119,7 +117,7 @@ jobs:
|
||||
- name: Cache compilation cache
|
||||
id: query-cache
|
||||
uses: ./.github/actions/cache-query-compilation
|
||||
with:
|
||||
with:
|
||||
key: ruby-build
|
||||
- name: Build Query Pack
|
||||
run: |
|
||||
@@ -231,54 +229,3 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
codeql database analyze --search-path "${{ runner.temp }}/ruby-bundle" --format=sarifv2.1.0 --output=out.sarif ../database ruby-code-scanning.qls
|
||||
|
||||
# This is a copy of the 'test' job that runs in a centos7 container.
|
||||
# This tests that the extractor works correctly on systems with an old glibc.
|
||||
test-centos7:
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ github.workspace }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: centos:centos7
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
needs: [package]
|
||||
steps:
|
||||
- name: Install gh cli
|
||||
run: |
|
||||
yum-config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo
|
||||
# fetch-codeql requires unzip and jq
|
||||
# jq is available in epel-release (https://docs.fedoraproject.org/en-US/epel/)
|
||||
yum install -y gh unzip epel-release
|
||||
yum install -y jq
|
||||
- uses: actions/checkout@v3
|
||||
- name: Fetch CodeQL
|
||||
uses: ./.github/actions/fetch-codeql
|
||||
|
||||
# Due to a bug in Actions, we can't use runner.temp in the run blocks here.
|
||||
# https://github.com/actions/runner/issues/2185
|
||||
|
||||
- name: Download Ruby bundle
|
||||
uses: actions/download-artifact@v3
|
||||
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: Run QL test
|
||||
shell: bash
|
||||
run: |
|
||||
codeql test run --search-path "$RUNNER_TEMP"/ruby-bundle --additional-packs "$RUNNER_TEMP"/ruby-bundle ruby/ql/test/library-tests/ast/constants/
|
||||
- name: Create database
|
||||
shell: bash
|
||||
run: |
|
||||
codeql database create --search-path "$RUNNER_TEMP"/ruby-bundle --language ruby --source-root ruby/ql/test/library-tests/ast/constants/ ../database
|
||||
- name: Analyze database
|
||||
shell: bash
|
||||
run: |
|
||||
codeql database analyze --search-path "$RUNNER_TEMP"/ruby-bundle --format=sarifv2.1.0 --output=out.sarif ../database ruby-code-scanning.qls
|
||||
|
||||
3
.github/workflows/ruby-dataset-measure.yml
vendored
3
.github/workflows/ruby-dataset-measure.yml
vendored
@@ -17,6 +17,9 @@ on:
|
||||
- .github/workflows/ruby-dataset-measure.yml
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
measure:
|
||||
env:
|
||||
|
||||
4
.github/workflows/ruby-qltest.yml
vendored
4
.github/workflows/ruby-qltest.yml
vendored
@@ -29,6 +29,9 @@ defaults:
|
||||
run:
|
||||
working-directory: ruby
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
qlupgrade:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -50,6 +53,7 @@ jobs:
|
||||
xargs codeql execute upgrades testdb
|
||||
diff -q testdb/ruby.dbscheme downgrades/initial/ruby.dbscheme
|
||||
qltest:
|
||||
if: github.repository_owner == 'github'
|
||||
runs-on: ubuntu-latest-xl
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
11
.github/workflows/swift.yml
vendored
11
.github/workflows/swift.yml
vendored
@@ -33,40 +33,47 @@ on:
|
||||
- rc/*
|
||||
- codeql-cli-*
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
# not using a matrix as you cannot depend on a specific job in a matrix, and we want to start linux checks
|
||||
# without waiting for the macOS build
|
||||
build-and-test-macos:
|
||||
if: github.repository_owner == 'github'
|
||||
runs-on: macos-12-xl
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./swift/actions/build-and-test
|
||||
build-and-test-linux:
|
||||
if: github.repository_owner == 'github'
|
||||
runs-on: ubuntu-latest-xl
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./swift/actions/build-and-test
|
||||
qltests-linux:
|
||||
if: github.repository_owner == 'github'
|
||||
needs: build-and-test-linux
|
||||
runs-on: ubuntu-latest-xl
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./swift/actions/run-ql-tests
|
||||
qltests-macos:
|
||||
if : ${{ github.event_name == 'pull_request' }}
|
||||
if: ${{ github.repository_owner == 'github' && github.event_name == 'pull_request' }}
|
||||
needs: build-and-test-macos
|
||||
runs-on: macos-12-xl
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./swift/actions/run-ql-tests
|
||||
integration-tests-linux:
|
||||
if: github.repository_owner == 'github'
|
||||
needs: build-and-test-linux
|
||||
runs-on: ubuntu-latest-xl
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./swift/actions/run-integration-tests
|
||||
integration-tests-macos:
|
||||
if : ${{ github.event_name == 'pull_request' }}
|
||||
if: ${{ github.repository_owner == 'github' && github.event_name == 'pull_request' }}
|
||||
needs: build-and-test-macos
|
||||
runs-on: macos-12-xl
|
||||
timeout-minutes: 60
|
||||
|
||||
3
.github/workflows/sync-files.yml
vendored
3
.github/workflows/sync-files.yml
vendored
@@ -10,6 +10,9 @@ on:
|
||||
- main
|
||||
- 'rc/*'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -23,6 +23,9 @@ defaults:
|
||||
run:
|
||||
working-directory: shared/tree-sitter-extractor
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
3
.github/workflows/validate-change-notes.yml
vendored
3
.github/workflows/validate-change-notes.yml
vendored
@@ -15,6 +15,9 @@ on:
|
||||
- ".github/workflows/validate-change-notes.yml"
|
||||
- ".github/actions/fetch-codeql/action.yml"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
check-change-note:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
# Bazel (excluding BUILD.bazel files)
|
||||
WORKSPACE.bazel @github/codeql-ci-reviewers
|
||||
MODULE.bazel @github/codeql-ci-reviewers
|
||||
.bazelversion @github/codeql-ci-reviewers
|
||||
.bazelrc @github/codeql-ci-reviewers
|
||||
**/*.bzl @github/codeql-ci-reviewers
|
||||
|
||||
53
MODULE.bazel
Normal file
53
MODULE.bazel
Normal file
@@ -0,0 +1,53 @@
|
||||
module(
|
||||
name = "codeql",
|
||||
version = "0.0",
|
||||
)
|
||||
|
||||
# this points to our internal repository when `codeql` is checked out as a submodule thereof
|
||||
# when building things from `codeql` independently this is stubbed out in `.bazelrc`
|
||||
bazel_dep(name = "semmle_code", version = "0.0")
|
||||
local_path_override(
|
||||
module_name = "semmle_code",
|
||||
path = "..",
|
||||
)
|
||||
|
||||
# see https://registry.bazel.build/ for a list of available packages
|
||||
|
||||
bazel_dep(name = "platforms", version = "0.0.8")
|
||||
bazel_dep(name = "rules_pkg", version = "0.9.1")
|
||||
bazel_dep(name = "rules_nodejs", version = "6.0.3")
|
||||
bazel_dep(name = "rules_python", version = "0.31.0")
|
||||
bazel_dep(name = "bazel_skylib", version = "1.5.0")
|
||||
bazel_dep(name = "abseil-cpp", version = "20240116.0", repo_name = "absl")
|
||||
bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json")
|
||||
bazel_dep(name = "fmt", version = "10.0.0")
|
||||
|
||||
pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
|
||||
pip.parse(
|
||||
hub_name = "codegen_deps",
|
||||
python_version = "3.11",
|
||||
requirements_lock = "//misc/codegen:requirements_lock.txt",
|
||||
)
|
||||
use_repo(pip, "codegen_deps")
|
||||
|
||||
swift_deps = use_extension("//swift/third_party:load.bzl", "swift_deps")
|
||||
use_repo(
|
||||
swift_deps,
|
||||
"binlog",
|
||||
"picosha2",
|
||||
"swift_prebuilt_darwin_x86_64",
|
||||
"swift_prebuilt_linux",
|
||||
"swift_toolchain_linux",
|
||||
"swift_toolchain_macos",
|
||||
)
|
||||
|
||||
node = use_extension("@rules_nodejs//nodejs:extensions.bzl", "node")
|
||||
node.toolchain(
|
||||
name = "nodejs",
|
||||
node_version = "18.15.0",
|
||||
)
|
||||
use_repo(node, "nodejs", "nodejs_toolchains")
|
||||
|
||||
register_toolchains(
|
||||
"@nodejs_toolchains//:all",
|
||||
)
|
||||
@@ -1,12 +1,2 @@
|
||||
# Please notice that any bazel targets and definitions in this repository are currently experimental
|
||||
# and for internal use only.
|
||||
|
||||
workspace(name = "codeql")
|
||||
|
||||
load("//misc/bazel:workspace.bzl", "codeql_workspace")
|
||||
|
||||
codeql_workspace()
|
||||
|
||||
load("//misc/bazel:workspace_deps.bzl", "codeql_workspace_deps")
|
||||
|
||||
codeql_workspace_deps()
|
||||
# please use MODULE.bazel to add dependencies
|
||||
# this empty file is required by internal repositories, don't remove it
|
||||
|
||||
@@ -431,13 +431,6 @@
|
||||
"java/ql/src/experimental/Security/CWE/CWE-400/LocalThreadResourceAbuse.qhelp",
|
||||
"java/ql/src/experimental/Security/CWE/CWE-400/ThreadResourceAbuse.qhelp"
|
||||
],
|
||||
"IDE Contextual Queries": [
|
||||
"cpp/ql/lib/IDEContextual.qll",
|
||||
"csharp/ql/lib/IDEContextual.qll",
|
||||
"java/ql/lib/IDEContextual.qll",
|
||||
"javascript/ql/lib/IDEContextual.qll",
|
||||
"python/ql/lib/analysis/IDEContextual.qll"
|
||||
],
|
||||
"CryptoAlgorithms Python/JS/Ruby": [
|
||||
"javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll",
|
||||
"python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll",
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
class Element extends @element {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Expr extends @expr {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Stmt extends @stmt {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
predicate isStmtWithInitializer(Stmt stmt) { exists(int kind | stmts(stmt, kind, _) | kind = 29) }
|
||||
|
||||
from Expr child, int index, int index_new, Element parent
|
||||
where
|
||||
exprparents(child, index, parent) and
|
||||
if isStmtWithInitializer(parent) then index_new = index - 1 else index_new = index
|
||||
select child, index_new, parent
|
||||
@@ -0,0 +1,9 @@
|
||||
class Stmt extends @stmt {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
from Stmt f, Stmt i
|
||||
where
|
||||
for_initialization(f, i) and
|
||||
f instanceof @stmt_for
|
||||
select f, i
|
||||
2244
cpp/downgrades/298438feb146335af824002589cd6d4e96e5dbf9/old.dbscheme
Normal file
2244
cpp/downgrades/298438feb146335af824002589cd6d4e96e5dbf9/old.dbscheme
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,20 @@
|
||||
class Element extends @element {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Stmt extends @stmt {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
predicate isStmtWithInitializer(Stmt stmt) { exists(int kind | stmts(stmt, kind, _) | kind = 29) }
|
||||
|
||||
from Stmt child, int index, int index_new, Element parent
|
||||
where
|
||||
stmtparents(child, index, parent) and
|
||||
(
|
||||
not isStmtWithInitializer(parent)
|
||||
or
|
||||
index > 0
|
||||
) and
|
||||
if isStmtWithInitializer(parent) then index_new = index - 1 else index_new = index
|
||||
select child, index_new, parent
|
||||
@@ -0,0 +1,5 @@
|
||||
description: Support C++20 range-based for initializers
|
||||
compatibility: partial
|
||||
exprparents.rel: run exprparents.qlo
|
||||
stmtparents.rel: run stmtparents.qlo
|
||||
for_initialization.rel: run for_initialization.qlo
|
||||
@@ -1,3 +1,16 @@
|
||||
## 0.12.6
|
||||
|
||||
### New Features
|
||||
|
||||
* A `getInitialization` predicate was added to the `RangeBasedForStmt` class that yields the C++20-style initializer of the range-based `for` statement when it exists.
|
||||
|
||||
## 0.12.5
|
||||
|
||||
### New Features
|
||||
|
||||
* Added the `PreprocBlock.qll` library to this repository. This library offers a view of `#if`, `#elif`, `#else` and similar directives as a tree with navigable parent-child relationships.
|
||||
* Added a new `ThrowingFunction` abstract class that can be used to model an external function that may throw an exception.
|
||||
|
||||
## 0.12.4
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
import semmle.files.FileSystem
|
||||
private import codeql.util.FileSystem
|
||||
|
||||
/**
|
||||
* Returns the `File` matching the given source file name as encoded by the VS
|
||||
@@ -10,13 +11,5 @@ import semmle.files.FileSystem
|
||||
*/
|
||||
cached
|
||||
File getFileBySourceArchiveName(string name) {
|
||||
// The name provided for a file in the source archive by the VS Code extension
|
||||
// has some differences from the absolute path in the database:
|
||||
// 1. colons are replaced by underscores
|
||||
// 2. there's a leading slash, even for Windows paths: "C:/foo/bar" ->
|
||||
// "/C_/foo/bar"
|
||||
// 3. double slashes in UNC prefixes are replaced with a single slash
|
||||
// We can handle 2 and 3 together by unconditionally adding a leading slash
|
||||
// before replacing double slashes.
|
||||
name = ("/" + result.getAbsolutePath().replaceAll(":", "_")).replaceAll("//", "/")
|
||||
result = IdeContextual<File>::getFileBySourceArchiveName(name)
|
||||
}
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Added a new `ThrowingFunction` abstract class that can be used to model an external function that may throw an exception.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added destructors for named objects to the intermediate representation.
|
||||
@@ -1,4 +1,6 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
## 0.12.5
|
||||
|
||||
### New Features
|
||||
|
||||
* Added the `PreprocBlock.qll` library to this repository. This library offers a view of `#if`, `#elif`, `#else` and similar directives as a tree with navigable parent-child relationships.
|
||||
* Added a new `ThrowingFunction` abstract class that can be used to model an external function that may throw an exception.
|
||||
5
cpp/ql/lib/change-notes/released/0.12.6.md
Normal file
5
cpp/ql/lib/change-notes/released/0.12.6.md
Normal file
@@ -0,0 +1,5 @@
|
||||
## 0.12.6
|
||||
|
||||
### New Features
|
||||
|
||||
* A `getInitialization` predicate was added to the `RangeBasedForStmt` class that yields the C++20-style initializer of the range-based `for` statement when it exists.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.12.4
|
||||
lastReleaseVersion: 0.12.6
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.12.5-dev
|
||||
version: 0.12.7-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -60,4 +60,6 @@ Element exprEnclosingElement(Expr e) {
|
||||
)
|
||||
else result = de.getDeclaration()
|
||||
)
|
||||
or
|
||||
result.(Stmt).getAnImplicitDestructorCall() = e
|
||||
}
|
||||
|
||||
@@ -735,7 +735,9 @@ private predicate namedStmtChildPredicates(Locatable s, Element e, string pred)
|
||||
or
|
||||
s.(ForStmt).getStmt() = e and pred = "getStmt()"
|
||||
or
|
||||
s.(RangeBasedForStmt).getChild(0) = e and pred = "getChild(0)"
|
||||
s.(RangeBasedForStmt).getInitialization() = e and pred = "getInitialization()"
|
||||
or
|
||||
s.(RangeBasedForStmt).getChild(1) = e and pred = "getChild(1)"
|
||||
or
|
||||
s.(RangeBasedForStmt).getBeginEndDeclaration() = e and pred = "getBeginEndDeclaration()"
|
||||
or
|
||||
@@ -743,7 +745,7 @@ private predicate namedStmtChildPredicates(Locatable s, Element e, string pred)
|
||||
or
|
||||
s.(RangeBasedForStmt).getUpdate() = e and pred = "getUpdate()"
|
||||
or
|
||||
s.(RangeBasedForStmt).getChild(4) = e and pred = "getChild(4)"
|
||||
s.(RangeBasedForStmt).getChild(5) = e and pred = "getChild(5)"
|
||||
or
|
||||
s.(RangeBasedForStmt).getStmt() = e and pred = "getStmt()"
|
||||
or
|
||||
@@ -835,7 +837,11 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
|
||||
or
|
||||
expr.(OverloadedArrayExpr).getArrayOffset() = ele and pred = "getArrayOffset()"
|
||||
or
|
||||
expr.(OverloadedPointerDereferenceExpr).getExpr() = ele and pred = "getExpr()"
|
||||
// OverloadedPointerDereferenceExpr::getExpr/0 also considers qualifiers, which are already handled above for all Call classes.
|
||||
not expr.(OverloadedPointerDereferenceExpr).getQualifier() =
|
||||
expr.(OverloadedPointerDereferenceExpr).getExpr() and
|
||||
expr.(OverloadedPointerDereferenceExpr).getExpr() = ele and
|
||||
pred = "getExpr()"
|
||||
or
|
||||
expr.(CommaExpr).getLeftOperand() = ele and pred = "getLeftOperand()"
|
||||
or
|
||||
|
||||
@@ -234,7 +234,16 @@ class VariableDeclarationEntry extends DeclarationEntry, @var_decl {
|
||||
* int f(int y) { return y; }
|
||||
* ```
|
||||
*/
|
||||
override string getName() { var_decls(underlyingElement(this), _, _, result, _) and result != "" }
|
||||
override string getName() {
|
||||
exists(string name |
|
||||
var_decls(underlyingElement(this), _, _, name, _) and
|
||||
(
|
||||
name != "" and result = name
|
||||
or
|
||||
name = "" and result = this.getVariable().(LocalVariable).getName()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of the variable which is being declared or defined.
|
||||
|
||||
@@ -203,30 +203,42 @@ private class GuardConditionFromIR extends GuardCondition {
|
||||
* `&&` and `||`. See the detailed explanation on predicate `controls`.
|
||||
*/
|
||||
private predicate controlsBlock(BasicBlock controlled, boolean testIsTrue) {
|
||||
exists(IRBlock irb, Instruction instr |
|
||||
exists(IRBlock irb |
|
||||
ir.controls(irb, testIsTrue) and
|
||||
instr = irb.getAnInstruction() and
|
||||
instr.getAst().(ControlFlowNode).getBasicBlock() = controlled and
|
||||
not isUnreachedBlock(irb) and
|
||||
not this.excludeAsControlledInstruction(instr)
|
||||
nonExcludedIRAndBasicBlock(irb, controlled) and
|
||||
not isUnreachedBlock(irb)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate excludeAsControlledInstruction(Instruction instr) {
|
||||
// Exclude the temporaries generated by a ternary expression.
|
||||
exists(TranslatedConditionalExpr tce |
|
||||
instr = tce.getInstruction(ConditionValueFalseStoreTag())
|
||||
or
|
||||
instr = tce.getInstruction(ConditionValueTrueStoreTag())
|
||||
or
|
||||
instr = tce.getInstruction(ConditionValueTrueTempAddressTag())
|
||||
or
|
||||
instr = tce.getInstruction(ConditionValueFalseTempAddressTag())
|
||||
)
|
||||
private predicate excludeAsControlledInstruction(Instruction instr) {
|
||||
// Exclude the temporaries generated by a ternary expression.
|
||||
exists(TranslatedConditionalExpr tce |
|
||||
instr = tce.getInstruction(ConditionValueFalseStoreTag())
|
||||
or
|
||||
// Exclude unreached instructions, as their AST is the whole function and not a block.
|
||||
instr instanceof UnreachedInstruction
|
||||
}
|
||||
instr = tce.getInstruction(ConditionValueTrueStoreTag())
|
||||
or
|
||||
instr = tce.getInstruction(ConditionValueTrueTempAddressTag())
|
||||
or
|
||||
instr = tce.getInstruction(ConditionValueFalseTempAddressTag())
|
||||
)
|
||||
or
|
||||
// Exclude unreached instructions, as their AST is the whole function and not a block.
|
||||
instr instanceof UnreachedInstruction
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `irb` is the `IRBlock` corresponding to the AST basic block
|
||||
* `controlled`, and `irb` does not contain any instruction(s) that should make
|
||||
* the `irb` be ignored.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate nonExcludedIRAndBasicBlock(IRBlock irb, BasicBlock controlled) {
|
||||
exists(Instruction instr |
|
||||
instr = irb.getAnInstruction() and
|
||||
instr.getAst().(ControlFlowNode).getBasicBlock() = controlled and
|
||||
not excludeAsControlledInstruction(instr)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// NOTE: There are two copies of this file, and they must be kept identical:
|
||||
// - semmle/code/cpp/controlflow/SubBasicBlocks.qll
|
||||
// - semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll
|
||||
// - semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll [now DEPRECATED]
|
||||
//
|
||||
// The second one is a private copy of the `SubBasicBlocks` library for
|
||||
// internal use by the data flow library. Having an extra copy prevents
|
||||
|
||||
@@ -637,8 +637,10 @@ private predicate straightLineSparse(Node scope, int i, Node ni, Spec spec) {
|
||||
any(RangeBasedForStmt for |
|
||||
i = -1 and ni = for and spec.isAt()
|
||||
or
|
||||
i = 0 and ni = for.getInitialization() and spec.isAround()
|
||||
or
|
||||
exists(DeclStmt s | s.getADeclaration() = for.getRangeVariable() |
|
||||
i = 0 and ni = s and spec.isAround()
|
||||
i = 1 and ni = s and spec.isAround()
|
||||
)
|
||||
or
|
||||
exists(DeclStmt s |
|
||||
@@ -649,22 +651,22 @@ private predicate straightLineSparse(Node scope, int i, Node ni, Spec spec) {
|
||||
// DeclStmt in that case.
|
||||
exists(s.getADeclaration())
|
||||
|
|
||||
i = 1 and ni = s and spec.isAround()
|
||||
i = 2 and ni = s and spec.isAround()
|
||||
)
|
||||
or
|
||||
i = 2 and ni = for.getCondition() and spec.isBefore()
|
||||
i = 3 and ni = for.getCondition() and spec.isBefore()
|
||||
or
|
||||
i = 3 and /* BARRIER */ ni = for and spec.isBarrier()
|
||||
i = 4 and /* BARRIER */ ni = for and spec.isBarrier()
|
||||
or
|
||||
exists(DeclStmt declStmt | declStmt.getADeclaration() = for.getVariable() |
|
||||
i = 4 and ni = declStmt and spec.isAfter()
|
||||
i = 5 and ni = declStmt and spec.isAfter()
|
||||
)
|
||||
or
|
||||
i = 5 and ni = for.getStmt() and spec.isAround()
|
||||
i = 6 and ni = for.getStmt() and spec.isAround()
|
||||
or
|
||||
i = 6 and ni = for.getUpdate() and spec.isAround()
|
||||
i = 7 and ni = for.getUpdate() and spec.isAround()
|
||||
or
|
||||
i = 7 and ni = for.getCondition() and spec.isBefore()
|
||||
i = 8 and ni = for.getCondition() and spec.isBefore()
|
||||
)
|
||||
or
|
||||
scope =
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*
|
||||
* Provides a local analysis for identifying where a variable address
|
||||
* is effectively taken. Array-like offsets are allowed to pass through but
|
||||
* not field-like offsets.
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*/
|
||||
|
||||
private import cpp
|
||||
private import DataFlowPrivate
|
||||
private import DataFlowUtil
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*/
|
||||
|
||||
private import DataFlowImplSpecific
|
||||
private import codeql.dataflow.internal.DataFlowImpl
|
||||
import MakeImpl<CppOldDataFlow>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*/
|
||||
|
||||
private import DataFlowImplSpecific
|
||||
private import codeql.dataflow.internal.DataFlowImplCommon
|
||||
import MakeImplCommon<CppOldDataFlow>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*
|
||||
* Provides consistency queries for checking invariants in the language-specific
|
||||
* data-flow classes and predicates.
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*
|
||||
* Provides C++-specific definitions for use in the data flow library.
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*/
|
||||
|
||||
private import cpp
|
||||
private import DataFlowUtil
|
||||
private import DataFlowDispatch
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*
|
||||
* Provides C++-specific definitions for use in the data flow library.
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*
|
||||
* Provides a class for handling variables in the data flow analysis.
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// NOTE: There are two copies of this file, and they must be kept identical:
|
||||
// - semmle/code/cpp/controlflow/SubBasicBlocks.qll
|
||||
// - semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll
|
||||
// - semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll [now DEPRECATED]
|
||||
//
|
||||
// The second one is a private copy of the `SubBasicBlocks` library for
|
||||
// internal use by the data flow library. Having an extra copy prevents
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*
|
||||
* Provides C++-specific definitions for use in the taint tracking library.
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*
|
||||
* Provides classes for performing local (intra-procedural) and
|
||||
* global (inter-procedural) taint-tracking analyses.
|
||||
*
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* DEPRECATED: Use `Global` and `GlobalWithState` instead.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.dataflow.internal.TaintTrackingUtil as Public
|
||||
|
||||
module Private {
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* DEPRECATED: Use `Global` and `GlobalWithState` instead.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.dataflow.internal.TaintTrackingUtil as Public
|
||||
|
||||
module Private {
|
||||
|
||||
@@ -244,9 +244,15 @@ class ConditionDeclExpr extends Expr, @condition_decl {
|
||||
|
||||
/**
|
||||
* Gets the compiler-generated variable access that conceptually occurs after
|
||||
* the initialization of the declared variable.
|
||||
* the initialization of the declared variable, if any.
|
||||
*/
|
||||
VariableAccess getVariableAccess() { result = this.getChild(0) }
|
||||
VariableAccess getVariableAccess() { result = this.getExpr() }
|
||||
|
||||
/**
|
||||
* Gets the expression that is evaluated after the initialization of the declared
|
||||
* variable.
|
||||
*/
|
||||
Expr getExpr() { result = this.getChild(0) }
|
||||
|
||||
/**
|
||||
* Gets the expression that initializes the declared variable. This predicate
|
||||
|
||||
@@ -34,7 +34,7 @@ private import Node0ToString
|
||||
cached
|
||||
private newtype TIRDataFlowNode =
|
||||
TNode0(Node0Impl node) { DataFlowImplCommon::forceCachingInSameStage() } or
|
||||
TVariableNode(Variable var, int indirectionIndex) {
|
||||
TGlobalLikeVariableNode(GlobalLikeVariable var, int indirectionIndex) {
|
||||
indirectionIndex =
|
||||
[getMinIndirectionsForType(var.getUnspecifiedType()) .. Ssa::getMaxIndirectionsForType(var.getUnspecifiedType())]
|
||||
} or
|
||||
@@ -55,29 +55,12 @@ private newtype TIRDataFlowNode =
|
||||
TFinalParameterNode(Parameter p, int indirectionIndex) {
|
||||
exists(Ssa::FinalParameterUse use |
|
||||
use.getParameter() = p and
|
||||
use.getIndirectionIndex() = indirectionIndex and
|
||||
parameterIsRedefined(p)
|
||||
use.getIndirectionIndex() = indirectionIndex
|
||||
)
|
||||
} or
|
||||
TFinalGlobalValue(Ssa::GlobalUse globalUse) or
|
||||
TInitialGlobalValue(Ssa::GlobalDef globalUse)
|
||||
|
||||
/**
|
||||
* Holds if the value of `*p` (or `**p`, `***p`, etc.) is redefined somewhere in the body
|
||||
* of the enclosing function of `p`.
|
||||
*
|
||||
* Only parameters satisfying this predicate will generate a `FinalParameterNode` transferring
|
||||
* flow out of the function.
|
||||
*/
|
||||
private predicate parameterIsRedefined(Parameter p) {
|
||||
exists(Ssa::Def def |
|
||||
def.getSourceVariable().getBaseVariable().(Ssa::BaseIRVariable).getIRVariable().getAst() = p and
|
||||
def.getIndirectionIndex() = 0 and
|
||||
def.getIndirection() > 1 and
|
||||
not def.getValue().asInstruction() instanceof InitializeParameterInstruction
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* An operand that is defined by a `FieldAddressInstruction`.
|
||||
*/
|
||||
@@ -413,7 +396,7 @@ class Node extends TIRDataFlowNode {
|
||||
* modeling flow in and out of global variables.
|
||||
*/
|
||||
Variable asVariable() {
|
||||
this = TVariableNode(result, getMinIndirectionsForType(result.getUnspecifiedType()))
|
||||
this = TGlobalLikeVariableNode(result, getMinIndirectionsForType(result.getUnspecifiedType()))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -423,7 +406,7 @@ class Node extends TIRDataFlowNode {
|
||||
*/
|
||||
Variable asIndirectVariable(int indirectionIndex) {
|
||||
indirectionIndex > getMinIndirectionsForType(result.getUnspecifiedType()) and
|
||||
this = TVariableNode(result, indirectionIndex)
|
||||
this = TGlobalLikeVariableNode(result, indirectionIndex)
|
||||
}
|
||||
|
||||
/** Gets an indirection of this node's underlying variable, if any. */
|
||||
@@ -709,7 +692,7 @@ class FinalGlobalValue extends Node, TFinalGlobalValue {
|
||||
override DataFlowType getType() {
|
||||
exists(int indirectionIndex |
|
||||
indirectionIndex = globalUse.getIndirectionIndex() and
|
||||
result = getTypeImpl(globalUse.getUnspecifiedType(), indirectionIndex - 1)
|
||||
result = getTypeImpl(globalUse.getUnderlyingType(), indirectionIndex - 1)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -740,7 +723,7 @@ class InitialGlobalValue extends Node, TInitialGlobalValue {
|
||||
|
||||
override DataFlowType getType() {
|
||||
exists(DataFlowType type |
|
||||
type = globalDef.getUnspecifiedType() and
|
||||
type = globalDef.getUnderlyingType() and
|
||||
if this.isGLValue()
|
||||
then result = type
|
||||
else result = getTypeImpl(type, globalDef.getIndirectionIndex() - 1)
|
||||
@@ -943,10 +926,13 @@ private Type getTypeImpl0(Type t, int indirectionIndex) {
|
||||
indirectionIndex > 0 and
|
||||
exists(Type stripped |
|
||||
stripped = stripPointer(t.stripTopLevelSpecifiers()) and
|
||||
// We need to avoid the case where `stripPointer(t) = t` (which can happen on
|
||||
// iterators that specify a `value_type` that is the iterator itself). Such a type
|
||||
// would create an infinite loop otherwise. For these cases we simply don't produce
|
||||
// a result for `getTypeImpl`.
|
||||
// We need to avoid the case where `stripPointer(t) = t` (which can happen
|
||||
// on iterators that specify a `value_type` that is the iterator itself).
|
||||
// Such a type would create an infinite loop otherwise. For these cases we
|
||||
// simply don't produce a result for `getTypeImpl`.
|
||||
// To be on the safe side, we check whether the _unspecified_ type has
|
||||
// changed since this also prevents an infinite loop when `stripped` and
|
||||
// `t` only differ by const'ness or volatile'ness.
|
||||
stripped.getUnspecifiedType() != t.getUnspecifiedType() and
|
||||
result = getTypeImpl0(stripped, indirectionIndex - 1)
|
||||
)
|
||||
@@ -996,12 +982,14 @@ private module RawIndirectNodes {
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
override predicate isGLValue() { this.getOperand().isGLValue() }
|
||||
|
||||
override DataFlowType getType() {
|
||||
exists(int sub, DataFlowType type, boolean isGLValue |
|
||||
type = getOperandType(this.getOperand(), isGLValue) and
|
||||
if isGLValue = true then sub = 1 else sub = 0
|
||||
|
|
||||
result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub)
|
||||
result = getTypeImpl(type.getUnderlyingType(), indirectionIndex - sub)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1038,12 +1026,14 @@ private module RawIndirectNodes {
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
override predicate isGLValue() { this.getInstruction().isGLValue() }
|
||||
|
||||
override DataFlowType getType() {
|
||||
exists(int sub, DataFlowType type, boolean isGLValue |
|
||||
type = getInstructionType(this.getInstruction(), isGLValue) and
|
||||
if isGLValue = true then sub = 1 else sub = 0
|
||||
|
|
||||
result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub)
|
||||
result = getTypeImpl(type.getUnderlyingType(), indirectionIndex - sub)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1136,7 +1126,7 @@ class FinalParameterNode extends Node, TFinalParameterNode {
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
override DataFlowType getType() { result = getTypeImpl(p.getUnspecifiedType(), indirectionIndex) }
|
||||
override DataFlowType getType() { result = getTypeImpl(p.getUnderlyingType(), indirectionIndex) }
|
||||
|
||||
final override Location getLocationImpl() {
|
||||
// Parameters can have multiple locations. When there's a unique location we use
|
||||
@@ -1761,15 +1751,18 @@ class DefinitionByReferenceNode extends IndirectArgumentOutNode {
|
||||
}
|
||||
|
||||
/**
|
||||
* A `Node` corresponding to a variable in the program, as opposed to the
|
||||
* value of that variable at some particular point. This can be used for
|
||||
* modeling flow in and out of global variables.
|
||||
* A `Node` corresponding to a global (or `static` local) variable in the
|
||||
* program, as opposed to the value of that variable at some particular point.
|
||||
* This is used to model flow through global variables (and `static` local
|
||||
* variables).
|
||||
*
|
||||
* There is no `VariableNode` for non-`static` local variables.
|
||||
*/
|
||||
class VariableNode extends Node, TVariableNode {
|
||||
class VariableNode extends Node, TGlobalLikeVariableNode {
|
||||
Variable v;
|
||||
int indirectionIndex;
|
||||
|
||||
VariableNode() { this = TVariableNode(v, indirectionIndex) }
|
||||
VariableNode() { this = TGlobalLikeVariableNode(v, indirectionIndex) }
|
||||
|
||||
/** Gets the variable corresponding to this node. */
|
||||
Variable getVariable() { result = v }
|
||||
@@ -1789,7 +1782,7 @@ class VariableNode extends Node, TVariableNode {
|
||||
}
|
||||
|
||||
override DataFlowType getType() {
|
||||
result = getTypeImpl(v.getUnspecifiedType(), indirectionIndex - 1)
|
||||
result = getTypeImpl(v.getUnderlyingType(), indirectionIndex - 1)
|
||||
}
|
||||
|
||||
final override Location getLocationImpl() {
|
||||
|
||||
@@ -507,13 +507,13 @@ module ProductFlow {
|
||||
private predicate pathSuccPlus(TNodePair n1, TNodePair n2) = fastTC(pathSucc/2)(n1, n2)
|
||||
|
||||
private predicate localPathStep1(Flow1::PathNode pred, Flow1::PathNode succ) {
|
||||
Flow1::PathGraph::edges(pred, succ) and
|
||||
Flow1::PathGraph::edges(pred, succ, _, _) and
|
||||
pragma[only_bind_out](pred.getNode().getEnclosingCallable()) =
|
||||
pragma[only_bind_out](succ.getNode().getEnclosingCallable())
|
||||
}
|
||||
|
||||
private predicate localPathStep2(Flow2::PathNode pred, Flow2::PathNode succ) {
|
||||
Flow2::PathGraph::edges(pred, succ) and
|
||||
Flow2::PathGraph::edges(pred, succ, _, _) and
|
||||
pragma[only_bind_out](pred.getNode().getEnclosingCallable()) =
|
||||
pragma[only_bind_out](succ.getNode().getEnclosingCallable())
|
||||
}
|
||||
@@ -530,7 +530,7 @@ module ProductFlow {
|
||||
TJump()
|
||||
|
||||
private predicate intoImpl1(Flow1::PathNode pred1, Flow1::PathNode succ1, DataFlowCall call) {
|
||||
Flow1::PathGraph::edges(pred1, succ1) and
|
||||
Flow1::PathGraph::edges(pred1, succ1, _, _) and
|
||||
pred1.getNode().(ArgumentNode).getCall() = call and
|
||||
succ1.getNode() instanceof ParameterNode
|
||||
}
|
||||
@@ -543,7 +543,7 @@ module ProductFlow {
|
||||
}
|
||||
|
||||
private predicate outImpl1(Flow1::PathNode pred1, Flow1::PathNode succ1, DataFlowCall call) {
|
||||
Flow1::PathGraph::edges(pred1, succ1) and
|
||||
Flow1::PathGraph::edges(pred1, succ1, _, _) and
|
||||
exists(ReturnKindExt returnKind |
|
||||
succ1.getNode() = returnKind.getAnOutNode(call) and
|
||||
pred1.getNode().(ReturnNodeExt).getKind() = returnKind
|
||||
@@ -558,7 +558,7 @@ module ProductFlow {
|
||||
}
|
||||
|
||||
private predicate intoImpl2(Flow2::PathNode pred2, Flow2::PathNode succ2, DataFlowCall call) {
|
||||
Flow2::PathGraph::edges(pred2, succ2) and
|
||||
Flow2::PathGraph::edges(pred2, succ2, _, _) and
|
||||
pred2.getNode().(ArgumentNode).getCall() = call and
|
||||
succ2.getNode() instanceof ParameterNode
|
||||
}
|
||||
@@ -571,7 +571,7 @@ module ProductFlow {
|
||||
}
|
||||
|
||||
private predicate outImpl2(Flow2::PathNode pred2, Flow2::PathNode succ2, DataFlowCall call) {
|
||||
Flow2::PathGraph::edges(pred2, succ2) and
|
||||
Flow2::PathGraph::edges(pred2, succ2, _, _) and
|
||||
exists(ReturnKindExt returnKind |
|
||||
succ2.getNode() = returnKind.getAnOutNode(call) and
|
||||
pred2.getNode().(ReturnNodeExt).getKind() = returnKind
|
||||
@@ -590,7 +590,7 @@ module ProductFlow {
|
||||
Declaration predDecl, Declaration succDecl, Flow1::PathNode pred1, Flow1::PathNode succ1,
|
||||
TKind kind
|
||||
) {
|
||||
Flow1::PathGraph::edges(pred1, succ1) and
|
||||
Flow1::PathGraph::edges(pred1, succ1, _, _) and
|
||||
predDecl != succDecl and
|
||||
pred1.getNode().getEnclosingCallable() = predDecl and
|
||||
succ1.getNode().getEnclosingCallable() = succDecl and
|
||||
@@ -610,7 +610,7 @@ module ProductFlow {
|
||||
Declaration predDecl, Declaration succDecl, Flow2::PathNode pred2, Flow2::PathNode succ2,
|
||||
TKind kind
|
||||
) {
|
||||
Flow2::PathGraph::edges(pred2, succ2) and
|
||||
Flow2::PathGraph::edges(pred2, succ2, _, _) and
|
||||
predDecl != succDecl and
|
||||
pred2.getNode().getEnclosingCallable() = predDecl and
|
||||
succ2.getNode().getEnclosingCallable() = succDecl and
|
||||
|
||||
@@ -4,7 +4,11 @@ private import DataFlowUtil
|
||||
private import DataFlowImplCommon as DataFlowImplCommon
|
||||
private import semmle.code.cpp.models.interfaces.Allocation as Alloc
|
||||
private import semmle.code.cpp.models.interfaces.DataFlow as DataFlow
|
||||
private import semmle.code.cpp.models.interfaces.Taint as Taint
|
||||
private import semmle.code.cpp.models.interfaces.PartialFlow as PartialFlow
|
||||
private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs as FIO
|
||||
private import semmle.code.cpp.ir.internal.IRCppLanguage
|
||||
private import semmle.code.cpp.ir.dataflow.internal.ModelUtil
|
||||
private import DataFlowPrivate
|
||||
private import ssa0.SsaInternals as SsaInternals0
|
||||
import SsaInternalsCommon
|
||||
@@ -138,12 +142,11 @@ private newtype TDefOrUseImpl =
|
||||
isIteratorUse(container, iteratorAddress, _, indirectionIndex)
|
||||
} or
|
||||
TFinalParameterUse(Parameter p, int indirectionIndex) {
|
||||
// Avoid creating parameter nodes if there is no definitions of the variable other than the initializaion.
|
||||
exists(SsaInternals0::Def def |
|
||||
def.getSourceVariable().getBaseVariable().(BaseIRVariable).getIRVariable().getAst() = p and
|
||||
not def.getValue().asInstruction() instanceof InitializeParameterInstruction and
|
||||
unspecifiedTypeIsModifiableAt(p.getUnspecifiedType(), indirectionIndex)
|
||||
)
|
||||
underlyingTypeIsModifiableAt(p.getUnderlyingType(), indirectionIndex) and
|
||||
// Only create an SSA read for the final use of a parameter if there's
|
||||
// actually a body of the enclosing function. If there's no function body
|
||||
// then we'll never need to flow out of the function anyway.
|
||||
p.getFunction().hasDefinition()
|
||||
}
|
||||
|
||||
private predicate isGlobalUse(
|
||||
@@ -172,11 +175,13 @@ private predicate isGlobalDefImpl(
|
||||
)
|
||||
}
|
||||
|
||||
private predicate unspecifiedTypeIsModifiableAt(Type unspecified, int indirectionIndex) {
|
||||
indirectionIndex = [1 .. getIndirectionForUnspecifiedType(unspecified).getNumberOfIndirections()] and
|
||||
private predicate underlyingTypeIsModifiableAt(Type underlying, int indirectionIndex) {
|
||||
indirectionIndex =
|
||||
[1 .. getIndirectionForUnspecifiedType(underlying.getUnspecifiedType())
|
||||
.getNumberOfIndirections()] and
|
||||
exists(CppType cppType |
|
||||
cppType.hasUnspecifiedType(unspecified, _) and
|
||||
isModifiableAt(cppType, indirectionIndex + 1)
|
||||
cppType.hasUnderlyingType(underlying, false) and
|
||||
isModifiableAt(cppType, indirectionIndex)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -545,6 +550,11 @@ class GlobalUse extends UseImpl, TGlobalUse {
|
||||
*/
|
||||
Type getUnspecifiedType() { result = global.getUnspecifiedType() }
|
||||
|
||||
/**
|
||||
* Gets the type of this use, after typedefs have been resolved.
|
||||
*/
|
||||
Type getUnderlyingType() { result = global.getUnderlyingType() }
|
||||
|
||||
override predicate isCertain() { any() }
|
||||
|
||||
override BaseSourceVariableInstruction getBase() { none() }
|
||||
@@ -588,11 +598,16 @@ class GlobalDefImpl extends DefOrUseImpl, TGlobalDefImpl {
|
||||
int getIndirection() { result = indirectionIndex }
|
||||
|
||||
/**
|
||||
* Gets the type of this use after specifiers have been deeply stripped
|
||||
* and typedefs have been resolved.
|
||||
* Gets the type of this definition after specifiers have been deeply
|
||||
* stripped and typedefs have been resolved.
|
||||
*/
|
||||
Type getUnspecifiedType() { result = global.getUnspecifiedType() }
|
||||
|
||||
/**
|
||||
* Gets the type of this definition, after typedefs have been resolved.
|
||||
*/
|
||||
Type getUnderlyingType() { result = global.getUnderlyingType() }
|
||||
|
||||
override string toString() { result = "Def of " + this.getSourceVariable() }
|
||||
|
||||
override Location getLocation() { result = f.getLocation() }
|
||||
@@ -784,10 +799,58 @@ private Node getAPriorDefinition(SsaDefOrUse defOrUse) {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate inOut(FIO::FunctionInput input, FIO::FunctionOutput output) {
|
||||
exists(int indirectionIndex |
|
||||
input.isQualifierObject(indirectionIndex) and
|
||||
output.isQualifierObject(indirectionIndex)
|
||||
or
|
||||
exists(int i |
|
||||
input.isParameterDeref(i, indirectionIndex) and
|
||||
output.isParameterDeref(i, indirectionIndex)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there should not be use-use flow out of `n`. That is, `n` is
|
||||
* an out-barrier to use-use flow. This includes:
|
||||
*
|
||||
* - an input to a call that would be assumed to have use-use flow to the same
|
||||
* argument as an output, but this flow should be blocked because the
|
||||
* function is modeled with another flow to that output (for example the
|
||||
* first argument of `strcpy`).
|
||||
* - a conversion that flows to such an input.
|
||||
*/
|
||||
private predicate modeledFlowBarrier(Node n) {
|
||||
exists(
|
||||
FIO::FunctionInput input, FIO::FunctionOutput output, CallInstruction call,
|
||||
PartialFlow::PartialFlowFunction partialFlowFunc
|
||||
|
|
||||
n = callInput(call, input) and
|
||||
inOut(input, output) and
|
||||
exists(callOutput(call, output)) and
|
||||
partialFlowFunc = call.getStaticCallTarget() and
|
||||
not partialFlowFunc.isPartialWrite(output)
|
||||
|
|
||||
call.getStaticCallTarget().(DataFlow::DataFlowFunction).hasDataFlow(_, output)
|
||||
or
|
||||
call.getStaticCallTarget().(Taint::TaintFunction).hasTaintFlow(_, output)
|
||||
)
|
||||
or
|
||||
exists(Operand operand, Instruction instr, Node n0, int indirectionIndex |
|
||||
modeledFlowBarrier(n0) and
|
||||
nodeHasInstruction(n0, instr, indirectionIndex) and
|
||||
conversionFlow(operand, instr, false, _) and
|
||||
nodeHasOperand(n, operand, indirectionIndex)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if there is def-use or use-use flow from `nodeFrom` to `nodeTo`. */
|
||||
predicate ssaFlow(Node nodeFrom, Node nodeTo) {
|
||||
exists(Node nFrom, boolean uncertain, SsaDefOrUse defOrUse |
|
||||
ssaFlowImpl(defOrUse, nFrom, nodeTo, uncertain) and nodeFrom != nodeTo
|
||||
ssaFlowImpl(defOrUse, nFrom, nodeTo, uncertain) and
|
||||
not modeledFlowBarrier(nFrom) and
|
||||
nodeFrom != nodeTo
|
||||
|
|
||||
if uncertain = true then nodeFrom = [nFrom, getAPriorDefinition(defOrUse)] else nodeFrom = nFrom
|
||||
)
|
||||
@@ -1092,6 +1155,11 @@ class GlobalDef extends TGlobalDef, SsaDefOrUse {
|
||||
*/
|
||||
DataFlowType getUnspecifiedType() { result = global.getUnspecifiedType() }
|
||||
|
||||
/**
|
||||
* Gets the type of this definition, after typedefs have been resolved.
|
||||
*/
|
||||
DataFlowType getUnderlyingType() { result = global.getUnderlyingType() }
|
||||
|
||||
/** Gets the `IRFunction` whose body is evaluated after this definition. */
|
||||
IRFunction getIRFunction() { result = global.getIRFunction() }
|
||||
|
||||
|
||||
@@ -452,7 +452,7 @@ private module IsModifiableAtImpl {
|
||||
private predicate impl(CppType cppType, int indirectionIndex) {
|
||||
exists(Type pointerType, Type base |
|
||||
isUnderlyingIndirectionType(pointerType) and
|
||||
cppType.hasUnderlyingType(pointerType, _) and
|
||||
cppType.hasUnderlyingType(pointerType, false) and
|
||||
base = getTypeImpl(pointerType, indirectionIndex)
|
||||
|
|
||||
// The value cannot be modified if it has a const specifier,
|
||||
|
||||
@@ -2125,13 +2125,6 @@ class ChiInstruction extends Instruction {
|
||||
*/
|
||||
final Instruction getPartial() { result = this.getPartialOperand().getDef() }
|
||||
|
||||
/**
|
||||
* Gets the bit range `[startBit, endBit)` updated by the partial operand of this `ChiInstruction`, relative to the start address of the total operand.
|
||||
*/
|
||||
final predicate getUpdatedInterval(int startBit, int endBit) {
|
||||
Construction::getIntervalUpdatedByChi(this, startBit, endBit)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the `ChiPartialOperand` totally, but not exactly, overlaps with the `ChiTotalOperand`.
|
||||
* This means that the `ChiPartialOperand` will not override the entire memory associated with the
|
||||
|
||||
@@ -233,20 +233,6 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the partial operand of this `ChiInstruction` updates the bit range
|
||||
* `[startBitOffset, endBitOffset)` of the total operand.
|
||||
*/
|
||||
cached
|
||||
predicate getIntervalUpdatedByChi(ChiInstruction chi, int startBitOffset, int endBitOffset) {
|
||||
exists(Alias::MemoryLocation location, OldInstruction oldInstruction |
|
||||
oldInstruction = getOldInstruction(chi.getPartial()) and
|
||||
location = Alias::getResultMemoryLocation(oldInstruction) and
|
||||
startBitOffset = Alias::getStartBitOffset(location) and
|
||||
endBitOffset = Alias::getEndBitOffset(location)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `operand` totally overlaps with its definition and consumes the bit range
|
||||
* `[startBitOffset, endBitOffset)`.
|
||||
|
||||
@@ -2125,13 +2125,6 @@ class ChiInstruction extends Instruction {
|
||||
*/
|
||||
final Instruction getPartial() { result = this.getPartialOperand().getDef() }
|
||||
|
||||
/**
|
||||
* Gets the bit range `[startBit, endBit)` updated by the partial operand of this `ChiInstruction`, relative to the start address of the total operand.
|
||||
*/
|
||||
final predicate getUpdatedInterval(int startBit, int endBit) {
|
||||
Construction::getIntervalUpdatedByChi(this, startBit, endBit)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the `ChiPartialOperand` totally, but not exactly, overlaps with the `ChiTotalOperand`.
|
||||
* This means that the `ChiPartialOperand` will not override the entire memory associated with the
|
||||
|
||||
@@ -11,6 +11,7 @@ private import InstructionTag
|
||||
private import TranslatedCondition
|
||||
private import TranslatedElement
|
||||
private import TranslatedExpr
|
||||
private import TranslatedCall
|
||||
private import TranslatedStmt
|
||||
private import TranslatedFunction
|
||||
private import TranslatedGlobalVar
|
||||
@@ -202,12 +203,6 @@ Instruction getMemoryOperandDefinition(
|
||||
none()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the partial operand of this `ChiInstruction` updates the bit range
|
||||
* `[startBitOffset, endBitOffset)` of the total operand.
|
||||
*/
|
||||
predicate getIntervalUpdatedByChi(ChiInstruction chi, int startBit, int endBit) { none() }
|
||||
|
||||
/**
|
||||
* Holds if the operand totally overlaps with its definition and consumes the
|
||||
* bit range `[startBitOffset, endBitOffset)`.
|
||||
|
||||
@@ -85,10 +85,14 @@ newtype TInstructionTag =
|
||||
// The next three cases handle generation of branching for __except handling.
|
||||
TryExceptCompareNegativeOneBranch() or
|
||||
TryExceptCompareZeroBranch() or
|
||||
TryExceptCompareOneBranch()
|
||||
TryExceptCompareOneBranch() or
|
||||
ImplicitDestructorTag(int index) {
|
||||
exists(Expr e | exists(e.getImplicitDestructorCall(index))) or
|
||||
exists(Stmt s | exists(s.getImplicitDestructorCall(index)))
|
||||
}
|
||||
|
||||
class InstructionTag extends TInstructionTag {
|
||||
final string toString() { result = "Tag" }
|
||||
final string toString() { result = getInstructionTagId(this) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -255,4 +259,8 @@ string getInstructionTagId(TInstructionTag tag) {
|
||||
tag = TryExceptCompareZeroBranch() and result = "TryExceptCompareZeroBranch"
|
||||
or
|
||||
tag = TryExceptCompareOneBranch() and result = "TryExceptCompareOneBranch"
|
||||
or
|
||||
exists(int index |
|
||||
tag = ImplicitDestructorTag(index) and result = "ImplicitDestructor(" + index + ")"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ private CallInstruction getTranslatedCallInstruction(Call call) {
|
||||
* of a higher-level constructor (e.g. the allocator call in a `NewExpr`).
|
||||
*/
|
||||
abstract class TranslatedCall extends TranslatedExpr {
|
||||
final override TranslatedElement getChild(int id) {
|
||||
final override TranslatedElement getChildInternal(int id) {
|
||||
// We choose the child's id in the order of evaluation.
|
||||
// The qualifier is evaluated before the call target, because the value of
|
||||
// the call target may depend on the value of the qualifier for virtual
|
||||
@@ -47,13 +47,19 @@ abstract class TranslatedCall extends TranslatedExpr {
|
||||
else result = this.getFirstCallTargetInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getSideEffects().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getSideEffects() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = CallTag() and
|
||||
opcode instanceof Opcode::Call and
|
||||
resultType = getTypeForPRValue(this.getCallResultType())
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getQualifier() and
|
||||
result = this.getFirstCallTargetInstruction(kind)
|
||||
or
|
||||
@@ -87,7 +93,7 @@ abstract class TranslatedCall extends TranslatedExpr {
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
tag = CallTag() and
|
||||
result = this.getSideEffects().getFirstInstruction(kind)
|
||||
}
|
||||
@@ -225,7 +231,7 @@ abstract class TranslatedSideEffects extends TranslatedElement {
|
||||
)
|
||||
}
|
||||
|
||||
final override Instruction getChildSuccessor(TranslatedElement te, EdgeKind kind) {
|
||||
final override Instruction getChildSuccessorInternal(TranslatedElement te, EdgeKind kind) {
|
||||
exists(int i |
|
||||
this.getChild(i) = te and
|
||||
if exists(this.getChild(i + 1))
|
||||
@@ -234,6 +240,10 @@ abstract class TranslatedSideEffects extends TranslatedElement {
|
||||
)
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() {
|
||||
result = this.getChild(max(int i | exists(this.getChild(i))))
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
|
||||
none()
|
||||
}
|
||||
@@ -246,7 +256,18 @@ abstract class TranslatedSideEffects extends TranslatedElement {
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getALastInstructionInternal() {
|
||||
if exists(this.getAChild())
|
||||
then result = this.getChild(max(int i | exists(this.getChild(i)))).getALastInstruction()
|
||||
else
|
||||
// If there are no side effects, the "last" instruction should be the parent call's last
|
||||
// instruction, so that implicit destructors can be inserted in the right place.
|
||||
result = this.getParent().getInstruction(CallTag())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
|
||||
/** Gets the primary instruction to be associated with each side effect instruction. */
|
||||
abstract Instruction getPrimaryInstruction();
|
||||
@@ -273,8 +294,8 @@ abstract class TranslatedDirectCall extends TranslatedCall {
|
||||
resultType = getFunctionGLValueType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
result = TranslatedCall.super.getInstructionSuccessor(tag, kind)
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
result = TranslatedCall.super.getInstructionSuccessorInternal(tag, kind)
|
||||
or
|
||||
tag = CallTargetTag() and
|
||||
result = this.getFirstArgumentOrCallInstruction(kind)
|
||||
@@ -367,6 +388,16 @@ class TranslatedStructorCall extends TranslatedFunctionCall {
|
||||
context = this.getParent() and
|
||||
result = context.getReceiver()
|
||||
)
|
||||
or
|
||||
exists(Stmt parent |
|
||||
expr = parent.getAnImplicitDestructorCall() and
|
||||
result = getTranslatedExpr(expr.getQualifier().getFullyConverted()).getResult()
|
||||
)
|
||||
or
|
||||
exists(Expr parent |
|
||||
expr = parent.getAnImplicitDestructorCall() and
|
||||
result = getTranslatedExpr(expr.getQualifier().getFullyConverted()).getResult()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate hasQualifier() { any() }
|
||||
@@ -416,19 +447,25 @@ private int initializeAllocationGroup() { result = 3 }
|
||||
abstract class TranslatedSideEffect extends TranslatedElement {
|
||||
final override TranslatedElement getChild(int n) { none() }
|
||||
|
||||
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getInstruction(OnlyInstructionTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
|
||||
tag = OnlyInstructionTag() and
|
||||
this.sideEffectInstruction(opcode, type)
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
result = this.getParent().getChildSuccessor(this, kind) and
|
||||
tag = OnlyInstructionTag()
|
||||
}
|
||||
|
||||
@@ -50,19 +50,29 @@ abstract class TranslatedFlexibleCondition extends TranslatedCondition, Conditio
|
||||
{
|
||||
TranslatedFlexibleCondition() { this = TTranslatedFlexibleCondition(expr) }
|
||||
|
||||
final override predicate handlesDestructorsExplicitly() { none() } // TODO: this needs to be revisted when we get unnamed destructors
|
||||
|
||||
final override TranslatedElement getChild(int id) { id = 0 and result = this.getOperand() }
|
||||
|
||||
final override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getOperand().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
final override Instruction getALastInstructionInternal() {
|
||||
result = this.getOperand().getALastInstruction()
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
|
||||
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
|
||||
abstract TranslatedCondition getOperand();
|
||||
}
|
||||
@@ -88,12 +98,16 @@ class TranslatedParenthesisCondition extends TranslatedFlexibleCondition {
|
||||
abstract class TranslatedNativeCondition extends TranslatedCondition, TTranslatedNativeCondition {
|
||||
TranslatedNativeCondition() { this = TTranslatedNativeCondition(expr) }
|
||||
|
||||
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
}
|
||||
|
||||
abstract class TranslatedBinaryLogicalOperation extends TranslatedNativeCondition, ConditionContext {
|
||||
override BinaryLogicalOperation expr;
|
||||
|
||||
final override predicate handlesDestructorsExplicitly() { none() } // TODO: this needs to be revisted when we get unnamed destructors
|
||||
|
||||
final override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getLeftOperand()
|
||||
or
|
||||
@@ -104,11 +118,19 @@ abstract class TranslatedBinaryLogicalOperation extends TranslatedNativeConditio
|
||||
result = this.getLeftOperand().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
final override Instruction getALastInstructionInternal() {
|
||||
result = this.getLeftOperand().getALastInstruction()
|
||||
or
|
||||
result = this.getRightOperand().getALastInstruction()
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
|
||||
final TranslatedCondition getLeftOperand() {
|
||||
result = getTranslatedCondition(expr.getLeftOperand().getFullyConverted())
|
||||
@@ -162,19 +184,25 @@ class TranslatedValueCondition extends TranslatedCondition, TTranslatedValueCond
|
||||
result = this.getValueExpr().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(ValueConditionConditionalBranchTag())
|
||||
}
|
||||
|
||||
final override predicate handlesDestructorsExplicitly() { none() } // TODO: this needs to be revisted when we get unnamed destructors
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = ValueConditionConditionalBranchTag() and
|
||||
opcode instanceof Opcode::ConditionalBranch and
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getValueExpr() and
|
||||
result = this.getInstruction(ValueConditionConditionalBranchTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
tag = ValueConditionConditionalBranchTag() and
|
||||
(
|
||||
kind instanceof TrueEdge and
|
||||
|
||||
@@ -60,6 +60,10 @@ abstract class TranslatedLocalVariableDeclaration extends TranslatedVariableInit
|
||||
*/
|
||||
abstract LocalVariable getVariable();
|
||||
|
||||
final override TranslatedElement getChild(int id) {
|
||||
result = TranslatedVariableInitialization.super.getChildInternal(id)
|
||||
}
|
||||
|
||||
final override Type getTargetType() { result = getVariableType(this.getVariable()) }
|
||||
|
||||
final override TranslatedInitialization getInitialization() {
|
||||
@@ -152,7 +156,13 @@ class TranslatedStaticLocalVariableDeclarationEntry extends TranslatedDeclaratio
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
final override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(DynamicInitializationConditionalBranchTag())
|
||||
or
|
||||
result = this.getInstruction(DynamicInitializationFlagStoreTag())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
tag = DynamicInitializationFlagAddressTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = this.getInstruction(DynamicInitializationFlagLoadTag())
|
||||
@@ -178,7 +188,7 @@ class TranslatedStaticLocalVariableDeclarationEntry extends TranslatedDeclaratio
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and
|
||||
result = this.getInstruction(DynamicInitializationFlagConstantTag()) and
|
||||
kind instanceof GotoEdge
|
||||
|
||||
@@ -20,10 +20,14 @@ private import SideEffects
|
||||
* they were explicit nodes in the expression tree, rather than as implicit
|
||||
* nodes as in the regular AST representation.
|
||||
*/
|
||||
private Element getRealParent(Expr expr) {
|
||||
Element getRealParent(Expr expr) {
|
||||
result = expr.getParentWithConversions()
|
||||
or
|
||||
result.(Destructor).getADestruction() = expr
|
||||
or
|
||||
result.(Expr).getAnImplicitDestructorCall() = expr
|
||||
or
|
||||
result.(Stmt).getAnImplicitDestructorCall() = expr
|
||||
}
|
||||
|
||||
IRUserVariable getIRUserVariable(Declaration decl, Variable var) {
|
||||
@@ -105,12 +109,6 @@ private predicate ignoreExprOnly(Expr expr) {
|
||||
newExpr.getAllocatorCall() = expr
|
||||
)
|
||||
or
|
||||
exists(DeleteOrDeleteArrayExpr deleteExpr |
|
||||
// Ignore the destructor call as we don't model it yet. Don't ignore
|
||||
// its arguments, though, as they are the arguments to the deallocator.
|
||||
deleteExpr.getDestructorCall() = expr
|
||||
)
|
||||
or
|
||||
// The extractor deliberately emits an `ErrorExpr` as the first argument to
|
||||
// the allocator call, if any, of a `NewOrNewArrayExpr`. That `ErrorExpr`
|
||||
// should not be translated.
|
||||
@@ -118,6 +116,11 @@ private predicate ignoreExprOnly(Expr expr) {
|
||||
or
|
||||
not translateFunction(getEnclosingFunction(expr)) and
|
||||
not Raw::varHasIRFunc(getEnclosingVariable(expr))
|
||||
or
|
||||
exists(DeleteOrDeleteArrayExpr deleteExpr |
|
||||
// Ignore the destructor call, because the duplicated qualifier breaks control flow.
|
||||
deleteExpr.getDestructorCall() = expr
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -209,6 +212,8 @@ private predicate usedAsCondition(Expr expr) {
|
||||
or
|
||||
exists(IfStmt ifStmt | ifStmt.getCondition().getFullyConverted() = expr)
|
||||
or
|
||||
exists(ConstexprIfStmt ifStmt | ifStmt.getCondition().getFullyConverted() = expr)
|
||||
or
|
||||
exists(ConditionalExpr condExpr |
|
||||
// The two-operand form of `ConditionalExpr` treats its condition as a value, since it needs to
|
||||
// be reused as a value if the condition is true.
|
||||
@@ -474,7 +479,6 @@ private module IRDeclarationEntries {
|
||||
* This class exists to work around the fact that `DeclStmt`s in some cases
|
||||
* do not have `DeclarationEntry`s. Currently, this is the case for:
|
||||
* - `DeclStmt`s in template instantiations.
|
||||
* - `DeclStmt`s that are generated by the desugaring of range-based for-loops.
|
||||
*
|
||||
* So instead, the IR works with `IRDeclarationEntry`s that synthesize missing
|
||||
* `DeclarationEntry`s when there is no result for `DeclStmt::getDeclarationEntry`.
|
||||
@@ -607,16 +611,27 @@ newtype TTranslatedElement =
|
||||
TTranslatedInitialization(Expr expr) {
|
||||
not ignoreExpr(expr) and
|
||||
(
|
||||
exists(Initializer init | init.getExpr().getFullyConverted() = expr) or
|
||||
exists(ClassAggregateLiteral initList | initList.getAFieldExpr(_).getFullyConverted() = expr) or
|
||||
exists(Initializer init | init.getExpr().getFullyConverted() = expr)
|
||||
or
|
||||
exists(ClassAggregateLiteral initList | initList.getAFieldExpr(_).getFullyConverted() = expr)
|
||||
or
|
||||
exists(ArrayOrVectorAggregateLiteral initList |
|
||||
initList.getAnElementExpr(_).getFullyConverted() = expr
|
||||
) or
|
||||
exists(ReturnStmt returnStmt | returnStmt.getExpr().getFullyConverted() = expr) or
|
||||
exists(ConstructorFieldInit fieldInit | fieldInit.getExpr().getFullyConverted() = expr) or
|
||||
exists(NewExpr newExpr | newExpr.getInitializer().getFullyConverted() = expr) or
|
||||
exists(ThrowExpr throw | throw.getExpr().getFullyConverted() = expr) or
|
||||
exists(TemporaryObjectExpr temp | temp.getExpr() = expr) or
|
||||
)
|
||||
or
|
||||
exists(ReturnStmt returnStmt |
|
||||
returnStmt.getExpr().getFullyConverted() = expr and
|
||||
hasReturnValue(returnStmt.getEnclosingFunction())
|
||||
)
|
||||
or
|
||||
exists(ConstructorFieldInit fieldInit | fieldInit.getExpr().getFullyConverted() = expr)
|
||||
or
|
||||
exists(NewExpr newExpr | newExpr.getInitializer().getFullyConverted() = expr)
|
||||
or
|
||||
exists(ThrowExpr throw | throw.getExpr().getFullyConverted() = expr)
|
||||
or
|
||||
exists(TemporaryObjectExpr temp | temp.getExpr() = expr)
|
||||
or
|
||||
exists(LambdaExpression lambda | lambda.getInitializer().getFullyConverted() = expr)
|
||||
)
|
||||
} or
|
||||
@@ -750,8 +765,6 @@ newtype TTranslatedElement =
|
||||
// on `*this` without an `Expr`.
|
||||
TTranslatedStructorQualifierSideEffect(Call call, SideEffectOpcode opcode) {
|
||||
not ignoreSideEffects(call) and
|
||||
// Don't bother with destructor calls for now, since we won't see very many of them in the IR
|
||||
// until we start injecting implicit destructor calls.
|
||||
call instanceof ConstructorCall and
|
||||
opcode = getASideEffectOpcode(call, -1)
|
||||
} or
|
||||
@@ -865,6 +878,23 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
1 + sum(TranslatedElement child | child = this.getChildByRank(_) | child.getDescendantCount())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this element has implicit destructor calls that should follow it.
|
||||
*/
|
||||
predicate hasAnImplicitDestructorCall() { none() }
|
||||
|
||||
/**
|
||||
* Gets the child index of the first destructor call that should be executed after this `TranslatedElement`
|
||||
*/
|
||||
int getFirstDestructorCallIndex() { none() }
|
||||
|
||||
/**
|
||||
* Holds if this `TranslatedElement` includes any destructor calls that must be performed after
|
||||
* it in its `getChildSuccessorInternal`, `getInstructionSuccessorInternal`, and
|
||||
* `getALastInstructionInternal` relations, rather than needing them inserted.
|
||||
*/
|
||||
predicate handlesDestructorsExplicitly() { none() }
|
||||
|
||||
private int getUniqueId() {
|
||||
if not exists(this.getParent())
|
||||
then result = 0
|
||||
@@ -900,15 +930,81 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
/**
|
||||
* Gets the successor instruction of the instruction that was generated by
|
||||
* this element for tag `tag`. The successor edge kind is specified by `kind`.
|
||||
* This predicate does not usually include destructors, which are inserted as
|
||||
* part of `getInstructionSuccessor` unless `handlesDestructorsExplicitly`
|
||||
* holds.
|
||||
*/
|
||||
abstract Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind);
|
||||
abstract Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind);
|
||||
|
||||
/**
|
||||
* Gets the successor instruction of the instruction that was generated by
|
||||
* this element for tag `tag`. The successor edge kind is specified by `kind`.
|
||||
*/
|
||||
final Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
if
|
||||
this.hasAnImplicitDestructorCall() and
|
||||
this.getInstruction(tag) = this.getALastInstructionInternal() and
|
||||
not this.handlesDestructorsExplicitly()
|
||||
then
|
||||
result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind) and
|
||||
kind instanceof GotoEdge
|
||||
else result = this.getInstructionSuccessorInternal(tag, kind)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an instruction within this `TranslatedElement` (including its transitive children) which
|
||||
* will be followed by an instruction outside the `TranslatedElement`.
|
||||
*/
|
||||
final Instruction getALastInstruction() {
|
||||
if this.hasAnImplicitDestructorCall() and not this.handlesDestructorsExplicitly()
|
||||
then result = this.getChild(max(int n | exists(this.getChild(n)))).getALastInstruction() // last destructor
|
||||
else result = this.getALastInstructionInternal()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an instruction within this `TranslatedElement` (including its transitive children) which
|
||||
* will be followed by an instruction outside the `TranslatedElement`.
|
||||
* This predicate does not usually include destructors, which are inserted as
|
||||
* part of `getALastInstruction` unless `handlesDestructorsExplicitly` holds.
|
||||
*/
|
||||
abstract Instruction getALastInstructionInternal();
|
||||
|
||||
TranslatedElement getLastChild() { none() }
|
||||
|
||||
/**
|
||||
* Gets the successor instruction to which control should flow after the
|
||||
* child element specified by `child` has finished execution. The successor
|
||||
* edge kind is specified by `kind`.
|
||||
* This predicate does not usually include destructors, which are inserted as
|
||||
* part of `getChildSuccessor` unless `handlesDestructorsExplicitly` holds.
|
||||
*/
|
||||
Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
|
||||
|
||||
/**
|
||||
* Gets the successor instruction to which control should flow after the
|
||||
* child element specified by `child` has finished execution. The successor
|
||||
* edge kind is specified by `kind`.
|
||||
*/
|
||||
abstract Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind);
|
||||
final Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
(
|
||||
if
|
||||
// this is the last child and we need to handle destructors for it
|
||||
this.hasAnImplicitDestructorCall() and
|
||||
not this.handlesDestructorsExplicitly() and
|
||||
child = this.getLastChild()
|
||||
then result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind)
|
||||
else result = this.getChildSuccessorInternal(child, kind)
|
||||
)
|
||||
or
|
||||
not this.handlesDestructorsExplicitly() and
|
||||
exists(int id |
|
||||
id >= this.getFirstDestructorCallIndex() and
|
||||
child = this.getChild(id) and
|
||||
if id = max(int n | exists(this.getChild(n)))
|
||||
then result = this.getParent().getChildSuccessor(this, kind)
|
||||
else result = this.getChild(id + 1).getFirstInstruction(kind)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instruction to which control should flow if an exception is thrown
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -114,7 +114,11 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(ExitFunctionTag())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
tag = EnterFunctionTag() and
|
||||
@@ -150,7 +154,7 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
|
||||
)
|
||||
}
|
||||
|
||||
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int paramIndex | child = this.getParameter(paramIndex) |
|
||||
if
|
||||
exists(func.getParameter(paramIndex + 1)) or
|
||||
@@ -379,7 +383,13 @@ abstract class TranslatedParameter extends TranslatedElement {
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getALastInstructionInternal() {
|
||||
if this.hasIndirection()
|
||||
then result = this.getInstruction(InitializerIndirectStoreTag())
|
||||
else result = this.getInstruction(InitializerStoreTag())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
tag = InitializerVariableAddressTag() and
|
||||
result = this.getInstruction(InitializerStoreTag())
|
||||
@@ -397,7 +407,9 @@ abstract class TranslatedParameter extends TranslatedElement {
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = InitializerVariableAddressTag() and
|
||||
@@ -611,15 +623,23 @@ class TranslatedConstructorInitList extends TranslatedElement, InitializationCon
|
||||
else result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getLastChild().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() {
|
||||
result = this.getChild(max(int id | exists(this.getChild(id))))
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Function getFunction() { result = func }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int id |
|
||||
child = this.getChild(id) and
|
||||
if exists(this.getChild(id + 1))
|
||||
@@ -678,15 +698,23 @@ class TranslatedDestructorDestructionList extends TranslatedElement,
|
||||
else result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getChild(max(int id | exists(this.getChild(id)))).getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() {
|
||||
result = this.getChild(max(int id | exists(this.getChild(id))))
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Function getFunction() { result = func }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int id |
|
||||
child = this.getChild(id) and
|
||||
if exists(this.getChild(id + 1))
|
||||
@@ -728,7 +756,20 @@ class TranslatedReadEffects extends TranslatedElement, TTranslatedReadEffects {
|
||||
else result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getALastInstructionInternal() {
|
||||
if exists(this.getAChild())
|
||||
then
|
||||
result =
|
||||
max(TranslatedElement child, int id | child = this.getChild(id) | child order by id)
|
||||
.getFirstInstruction(any(GotoEdge goto))
|
||||
else result = this.getParent().getChildSuccessor(this, any(GotoEdge goto))
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() {
|
||||
result = this.getChild(max(int id | exists(this.getChild(id))))
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int id | child = this.getChild(id) |
|
||||
if exists(TranslatedReadEffect child2, int id2 | id2 > id and child2 = this.getChild(id2))
|
||||
then
|
||||
@@ -746,7 +787,7 @@ class TranslatedReadEffects extends TranslatedElement, TTranslatedReadEffects {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
}
|
||||
|
||||
private TranslatedThisReadEffect getTranslatedThisReadEffect(Function func) {
|
||||
@@ -760,9 +801,9 @@ private TranslatedParameterReadEffect getTranslatedParameterReadEffect(Parameter
|
||||
abstract class TranslatedReadEffect extends TranslatedElement {
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
@@ -772,6 +813,10 @@ abstract class TranslatedReadEffect extends TranslatedElement {
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
opcode instanceof Opcode::ReturnIndirection and
|
||||
tag = OnlyInstructionTag() and
|
||||
|
||||
@@ -27,6 +27,10 @@ class TranslatedStaticStorageDurationVarInit extends TranslatedRootElement,
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(ExitFunctionTag())
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int n) {
|
||||
n = 1 and
|
||||
result = getTranslatedInitialization(var.getInitializer().getExpr().getFullyConverted())
|
||||
@@ -58,7 +62,7 @@ class TranslatedStaticStorageDurationVarInit extends TranslatedRootElement,
|
||||
type = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
tag = EnterFunctionTag() and
|
||||
@@ -81,7 +85,7 @@ class TranslatedStaticStorageDurationVarInit extends TranslatedRootElement,
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getChild(1) and
|
||||
result = this.getInstruction(ReturnTag()) and
|
||||
kind instanceof GotoEdge
|
||||
|
||||
@@ -35,13 +35,19 @@ abstract class InitializationContext extends TranslatedElement {
|
||||
* declarations, `return` statements, and `throw` expressions.
|
||||
*/
|
||||
abstract class TranslatedVariableInitialization extends TranslatedElement, InitializationContext {
|
||||
final override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() }
|
||||
TranslatedElement getChildInternal(int id) { id = 0 and result = this.getInitialization() }
|
||||
|
||||
final override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getInstruction(InitializerVariableAddressTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInitialization().getALastInstruction()
|
||||
or
|
||||
not exists(this.getInitialization()) and result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = InitializerVariableAddressTag() and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
@@ -53,7 +59,7 @@ abstract class TranslatedVariableInitialization extends TranslatedElement, Initi
|
||||
resultType = getTypeForPRValue(this.getTargetType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
(
|
||||
tag = InitializerVariableAddressTag() and
|
||||
if this.hasUninitializedInstruction()
|
||||
@@ -71,7 +77,7 @@ abstract class TranslatedVariableInitialization extends TranslatedElement, Initi
|
||||
)
|
||||
}
|
||||
|
||||
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and
|
||||
result = this.getInitializationSuccessor(kind)
|
||||
}
|
||||
@@ -177,7 +183,11 @@ abstract class TranslatedListInitialization extends TranslatedInitialization, In
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getChild(max(int i | exists(this.getChild(i)))).getALastInstruction()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int index |
|
||||
child = this.getChild(index) and
|
||||
if exists(this.getChild(index + 1))
|
||||
@@ -190,7 +200,9 @@ abstract class TranslatedListInitialization extends TranslatedInitialization, In
|
||||
none()
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getTargetAddress() { result = this.getContext().getTargetAddress() }
|
||||
|
||||
@@ -260,18 +272,22 @@ class TranslatedSimpleDirectInitialization extends TranslatedDirectInitializatio
|
||||
not expr instanceof StringLiteral
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(InitializerStoreTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = InitializerStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getTypeForPRValue(this.getContext().getTargetType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
tag = InitializerStoreTag() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitializer() and
|
||||
result = this.getInstruction(InitializerStoreTag()) and
|
||||
kind instanceof GotoEdge
|
||||
@@ -296,6 +312,12 @@ class TranslatedSimpleDirectInitialization extends TranslatedDirectInitializatio
|
||||
class TranslatedStringLiteralInitialization extends TranslatedDirectInitialization {
|
||||
override StringLiteral expr;
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
if this.zeroInitRange(_, _)
|
||||
then result = this.getInstruction(ZeroPadStringStoreTag())
|
||||
else result = this.getInstruction(InitializerStoreTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
// Load the string literal to make it a prvalue of type `char[len]`
|
||||
tag = InitializerLoadStringTag() and
|
||||
@@ -337,7 +359,7 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
tag = InitializerLoadStringTag() and
|
||||
result = this.getInstruction(InitializerStoreTag())
|
||||
@@ -367,7 +389,7 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitializer() and
|
||||
result = this.getInstruction(InitializerLoadStringTag()) and
|
||||
kind instanceof GotoEdge
|
||||
@@ -457,16 +479,22 @@ class TranslatedConstructorInitialization extends TranslatedDirectInitialization
|
||||
{
|
||||
override ConstructorCall expr;
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInitializer().getALastInstruction()
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitializer() and result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getInitializer() }
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
none()
|
||||
}
|
||||
@@ -558,23 +586,29 @@ class TranslatedExplicitFieldInitialization extends TranslatedFieldInitializatio
|
||||
this = TTranslatedExplicitFieldInitialization(ast, field, expr, position)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInitialization().getALastInstruction()
|
||||
}
|
||||
|
||||
override Instruction getTargetAddress() {
|
||||
result = this.getInstruction(this.getFieldAddressTag())
|
||||
}
|
||||
|
||||
override Type getTargetType() { result = field.getUnspecifiedType() }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
tag = this.getFieldAddressTag() and
|
||||
result = this.getInitialization().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() }
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getInitialization() }
|
||||
|
||||
private TranslatedInitialization getInitialization() {
|
||||
result = getTranslatedInitialization(expr)
|
||||
}
|
||||
@@ -595,6 +629,10 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization,
|
||||
{
|
||||
TranslatedFieldValueInitialization() { this = TTranslatedFieldValueInitialization(ast, field) }
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(this.getFieldDefaultValueStoreTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
TranslatedFieldInitialization.super.hasInstruction(opcode, tag, resultType)
|
||||
or
|
||||
@@ -607,7 +645,7 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization,
|
||||
resultType = getTypeForPRValue(field.getUnspecifiedType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
tag = this.getFieldAddressTag() and
|
||||
@@ -639,7 +677,7 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization,
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
|
||||
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
@@ -689,7 +727,7 @@ abstract class TranslatedElementInitialization extends TranslatedElement {
|
||||
resultType = getTypeForGLValue(this.getElementType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
tag = this.getElementIndexTag() and
|
||||
result = this.getInstruction(this.getElementAddressTag()) and
|
||||
kind instanceof GotoEdge
|
||||
@@ -743,20 +781,24 @@ class TranslatedExplicitElementInitialization extends TranslatedElementInitializ
|
||||
this = TTranslatedExplicitElementInitialization(initList, elementIndex, position)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInitialization().getALastInstruction()
|
||||
}
|
||||
|
||||
override Instruction getTargetAddress() {
|
||||
result = this.getInstruction(this.getElementAddressTag())
|
||||
}
|
||||
|
||||
override Type getTargetType() { result = this.getElementType() }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
result = TranslatedElementInitialization.super.getInstructionSuccessor(tag, kind)
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
result = TranslatedElementInitialization.super.getInstructionSuccessorInternal(tag, kind)
|
||||
or
|
||||
tag = this.getElementAddressTag() and
|
||||
result = this.getInitialization().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
@@ -788,6 +830,10 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
this = TTranslatedElementValueInitialization(initList, elementIndex, elementCount)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(this.getElementDefaultValueStoreTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
TranslatedElementInitialization.super.hasInstruction(opcode, tag, resultType)
|
||||
or
|
||||
@@ -800,8 +846,8 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
resultType = this.getDefaultValueType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
result = TranslatedElementInitialization.super.getInstructionSuccessor(tag, kind)
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
result = TranslatedElementInitialization.super.getInstructionSuccessorInternal(tag, kind)
|
||||
or
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
@@ -836,7 +882,7 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
|
||||
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
@@ -876,11 +922,13 @@ abstract class TranslatedStructorCallFromStructor extends TranslatedElement, Str
|
||||
|
||||
final override Function getFunction() { result = getEnclosingFunction(call) }
|
||||
|
||||
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getStructorCall() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getStructorCall() }
|
||||
|
||||
final TranslatedExpr getStructorCall() { result = getTranslatedExpr(call) }
|
||||
}
|
||||
|
||||
@@ -894,13 +942,17 @@ abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStru
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getStructorCall().getALastInstruction()
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode instanceof Opcode::ConvertToNonVirtualBase and
|
||||
resultType = getTypeForGLValue(call.getTarget().getDeclaringType())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = this.getStructorCall().getFirstInstruction(kind)
|
||||
}
|
||||
@@ -947,11 +999,17 @@ class TranslatedConstructorDelegationInit extends TranslatedConstructorCallFromC
|
||||
result = this.getStructorCall().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getStructorCall().getALastInstruction()
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
|
||||
final override Instruction getReceiver() {
|
||||
result = getTranslatedFunction(this.getFunction()).getInitializeThisInstruction()
|
||||
@@ -1009,6 +1067,8 @@ class TranslatedConstructorBareInit extends TranslatedElement, TTranslatedConstr
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() { none() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
@@ -1017,9 +1077,9 @@ class TranslatedConstructorBareInit extends TranslatedElement, TTranslatedConstr
|
||||
|
||||
override Declaration getFunction() { result = this.getParent().getFunction() }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
|
||||
}
|
||||
|
||||
TranslatedConstructorBareInit getTranslatedConstructorBareInit(ConstructorInit init) {
|
||||
|
||||
@@ -138,7 +138,7 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
|
||||
result = "1"
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
// Generate -1 -> Compare condition
|
||||
tag = TryExceptGenerateNegativeOne() and
|
||||
kind instanceof GotoEdge and
|
||||
@@ -202,7 +202,7 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
child = this.getTranslatedCondition() and
|
||||
result = this.getInstruction(TryExceptGenerateNegativeOne())
|
||||
@@ -211,6 +211,14 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getTranslatedHandler() }
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getTranslatedHandler().getALastInstruction()
|
||||
or
|
||||
result = this.getInstruction(UnwindTag())
|
||||
}
|
||||
|
||||
private TranslatedExpr getTranslatedCondition() {
|
||||
result = getTranslatedExpr(tryExcept.getCondition())
|
||||
}
|
||||
@@ -235,6 +243,27 @@ abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt {
|
||||
|
||||
TranslatedStmt() { this = TTranslatedStmt(stmt) }
|
||||
|
||||
abstract TranslatedElement getChildInternal(int id);
|
||||
|
||||
final override TranslatedElement getChild(int id) {
|
||||
result = this.getChildInternal(id)
|
||||
or
|
||||
exists(int destructorIndex |
|
||||
result.(TranslatedExpr).getExpr() = stmt.getImplicitDestructorCall(destructorIndex) and
|
||||
id = this.getFirstDestructorCallIndex() + destructorIndex
|
||||
)
|
||||
}
|
||||
|
||||
final override int getFirstDestructorCallIndex() {
|
||||
result = max(int childId | exists(this.getChildInternal(childId))) + 1
|
||||
or
|
||||
not exists(this.getChildInternal(_)) and result = 0
|
||||
}
|
||||
|
||||
final override predicate hasAnImplicitDestructorCall() {
|
||||
exists(stmt.getAnImplicitDestructorCall())
|
||||
}
|
||||
|
||||
final override string toString() { result = stmt.toString() }
|
||||
|
||||
final override Locatable getAst() { result = stmt }
|
||||
@@ -252,25 +281,29 @@ class TranslatedEmptyStmt extends TranslatedStmt {
|
||||
stmt instanceof SwitchCase
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
override TranslatedElement getChildInternal(int id) { none() }
|
||||
|
||||
override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getInstruction(OnlyInstructionTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode instanceof Opcode::NoOp and
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -281,7 +314,7 @@ class TranslatedEmptyStmt extends TranslatedStmt {
|
||||
class TranslatedDeclStmt extends TranslatedStmt {
|
||||
override DeclStmt stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) { result = this.getDeclarationEntry(id) }
|
||||
override TranslatedElement getChildInternal(int id) { result = this.getDeclarationEntry(id) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
@@ -294,6 +327,12 @@ class TranslatedDeclStmt extends TranslatedStmt {
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getChild(this.getChildCount() - 1).getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getChild(this.getChildCount() - 1) }
|
||||
|
||||
private int getChildCount() { result = count(this.getDeclarationEntry(_)) }
|
||||
|
||||
IRDeclarationEntry getIRDeclarationEntry(int index) {
|
||||
@@ -318,9 +357,9 @@ class TranslatedDeclStmt extends TranslatedStmt {
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int index |
|
||||
child = this.getDeclarationEntry(index) and
|
||||
if index = (this.getChildCount() - 1)
|
||||
@@ -335,7 +374,7 @@ class TranslatedExprStmt extends TranslatedStmt {
|
||||
|
||||
TranslatedExpr getExpr() { result = getTranslatedExpr(stmt.getExpr().getFullyConverted()) }
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = this.getExpr() }
|
||||
override TranslatedElement getChildInternal(int id) { id = 0 and result = this.getExpr() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
@@ -345,9 +384,15 @@ class TranslatedExprStmt extends TranslatedStmt {
|
||||
result = this.getExpr().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getExpr().getALastInstruction()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override TranslatedElement getLastChild() { result = this.getExpr() }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getExpr() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
@@ -359,6 +404,21 @@ abstract class TranslatedReturnStmt extends TranslatedStmt {
|
||||
final TranslatedFunction getEnclosingFunction() {
|
||||
result = getTranslatedFunction(stmt.getEnclosingFunction())
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int id |
|
||||
child = this.getChild(id) and
|
||||
id >= this.getFirstDestructorCallIndex() and
|
||||
(
|
||||
result = this.getChild(id + 1).getFirstInstruction(kind)
|
||||
or
|
||||
not exists(this.getChild(id + 1)) and
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
final override predicate handlesDestructorsExplicitly() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -368,7 +428,19 @@ class TranslatedReturnValueStmt extends TranslatedReturnStmt, TranslatedVariable
|
||||
TranslatedReturnValueStmt() { stmt.hasExpr() and hasReturnValue(stmt.getEnclosingFunction()) }
|
||||
|
||||
final override Instruction getInitializationSuccessor(EdgeKind kind) {
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
if this.hasAnImplicitDestructorCall()
|
||||
then result = this.getChild(1).getFirstInstruction(kind)
|
||||
else result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
result = TranslatedVariableInitialization.super.getChildSuccessorInternal(child, kind)
|
||||
or
|
||||
result = TranslatedReturnStmt.super.getChildSuccessorInternal(child, kind)
|
||||
}
|
||||
|
||||
final override TranslatedElement getChildInternal(int id) {
|
||||
result = TranslatedVariableInitialization.super.getChildInternal(id)
|
||||
}
|
||||
|
||||
final override Type getTargetType() { result = this.getEnclosingFunction().getReturnType() }
|
||||
@@ -390,7 +462,7 @@ class TranslatedReturnVoidExpressionStmt extends TranslatedReturnStmt {
|
||||
stmt.hasExpr() and not hasReturnValue(stmt.getEnclosingFunction())
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
id = 0 and
|
||||
result = this.getExpr()
|
||||
}
|
||||
@@ -399,21 +471,31 @@ class TranslatedReturnVoidExpressionStmt extends TranslatedReturnStmt {
|
||||
result = this.getExpr().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
if this.hasAnImplicitDestructorCall()
|
||||
then result = this.getChild(max(int id | exists(this.getChild(id)))).getALastInstruction()
|
||||
else result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode instanceof Opcode::NoOp and
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
if this.hasAnImplicitDestructorCall()
|
||||
then result = this.getChild(1).getFirstInstruction(kind)
|
||||
else result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getExpr() and
|
||||
result = this.getInstruction(OnlyInstructionTag()) and
|
||||
kind instanceof GotoEdge
|
||||
or
|
||||
result = TranslatedReturnStmt.super.getChildSuccessorInternal(child, kind)
|
||||
}
|
||||
|
||||
private TranslatedExpr getExpr() { result = getTranslatedExpr(stmt.getExpr()) }
|
||||
@@ -428,25 +510,43 @@ class TranslatedReturnVoidStmt extends TranslatedReturnStmt {
|
||||
not stmt.hasExpr() and not hasReturnValue(stmt.getEnclosingFunction())
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
override TranslatedElement getChildInternal(int id) { none() }
|
||||
|
||||
override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getInstruction(OnlyInstructionTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
if this.hasAnImplicitDestructorCall()
|
||||
then result = this.getChild(max(int id | exists(this.getChild(id)))).getALastInstruction()
|
||||
else result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode instanceof Opcode::NoOp and
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
if this.hasAnImplicitDestructorCall()
|
||||
then result = this.getChild(0).getFirstInstruction(kind)
|
||||
else result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int id |
|
||||
this.getChild(id) = child and
|
||||
(
|
||||
result = this.getChild(id + 1).getFirstInstruction(kind)
|
||||
or
|
||||
not exists(this.getChild(id + 1)) and
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -464,6 +564,16 @@ class TranslatedNoValueReturnStmt extends TranslatedReturnStmt, TranslatedVariab
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
}
|
||||
|
||||
final override TranslatedElement getChildInternal(int id) {
|
||||
result = TranslatedVariableInitialization.super.getChildInternal(id)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
result = TranslatedVariableInitialization.super.getChildSuccessorInternal(child, kind)
|
||||
or
|
||||
result = TranslatedReturnStmt.super.getChildSuccessorInternal(child, kind)
|
||||
}
|
||||
|
||||
final override Type getTargetType() { result = this.getEnclosingFunction().getReturnType() }
|
||||
|
||||
final override TranslatedInitialization getInitialization() { none() }
|
||||
@@ -518,7 +628,7 @@ private class TryOrMicrosoftTryStmt extends Stmt {
|
||||
class TranslatedTryStmt extends TranslatedStmt {
|
||||
override TryOrMicrosoftTryStmt stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
id = 0 and result = this.getBody()
|
||||
or
|
||||
result = this.getHandler(id - 1)
|
||||
@@ -531,13 +641,23 @@ class TranslatedTryStmt extends TranslatedStmt {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getBody().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getLastChild().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() {
|
||||
if exists(this.getFinally())
|
||||
then result = this.getFinally()
|
||||
else result = [this.getBody(), this.getHandler(_)]
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
// All non-finally children go to the successor of the `try` if
|
||||
// there is no finally block, but if there is a finally block
|
||||
// then we go to that one.
|
||||
@@ -581,7 +701,7 @@ class TranslatedTryStmt extends TranslatedStmt {
|
||||
class TranslatedBlock extends TranslatedStmt {
|
||||
override BlockStmt stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) { result = this.getStmt(id) }
|
||||
override TranslatedElement getChildInternal(int id) { result = this.getStmt(id) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
this.isEmpty() and
|
||||
@@ -596,18 +716,26 @@ class TranslatedBlock extends TranslatedStmt {
|
||||
else result = this.getStmt(0).getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
if this.isEmpty()
|
||||
then result = this.getInstruction(OnlyInstructionTag())
|
||||
else result = this.getStmt(this.getStmtCount() - 1).getFirstInstruction(any(GotoEdge goto))
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getStmt(this.getStmtCount() - 1) }
|
||||
|
||||
private predicate isEmpty() { not exists(stmt.getStmt(0)) }
|
||||
|
||||
private TranslatedStmt getStmt(int index) { result = getTranslatedStmt(stmt.getStmt(index)) }
|
||||
|
||||
private int getStmtCount() { result = stmt.getNumStmt() }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int index |
|
||||
child = this.getStmt(index) and
|
||||
if index = (this.getStmtCount() - 1)
|
||||
@@ -623,14 +751,20 @@ class TranslatedBlock extends TranslatedStmt {
|
||||
abstract class TranslatedHandler extends TranslatedStmt {
|
||||
override Handler stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 1 and result = this.getBlock() }
|
||||
override TranslatedElement getChildInternal(int id) { id = 1 and result = this.getBlock() }
|
||||
|
||||
override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getInstruction(CatchTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getBlock().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getBlock() }
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getBlock() and result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
@@ -656,20 +790,20 @@ class TranslatedCatchByTypeHandler extends TranslatedHandler {
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
result = super.getChild(id)
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
result = super.getChildInternal(id)
|
||||
or
|
||||
id = 0 and result = this.getParameter()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
result = super.getChildSuccessor(child, kind)
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
result = super.getChildSuccessorInternal(child, kind)
|
||||
or
|
||||
child = this.getParameter() and
|
||||
result = this.getBlock().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
tag = CatchTag() and
|
||||
(
|
||||
kind instanceof GotoEdge and
|
||||
@@ -702,7 +836,7 @@ class TranslatedCatchAnyHandler extends TranslatedHandler {
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
tag = CatchTag() and
|
||||
result = this.getBlock().getFirstInstruction(kind)
|
||||
}
|
||||
@@ -717,7 +851,13 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
|
||||
else result = this.getFirstConditionInstruction(kind)
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getElse().getALastInstruction() or result = this.getThen().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getElse() or result = this.getThen() }
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
id = 0 and result = this.getInitialization()
|
||||
or
|
||||
id = 1 and result = this.getCondition()
|
||||
@@ -747,7 +887,7 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
|
||||
|
||||
private predicate hasElse() { exists(stmt.getElse()) }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildTrueSuccessor(TranslatedCondition child, EdgeKind kind) {
|
||||
child = this.getCondition() and
|
||||
@@ -761,7 +901,7 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
|
||||
else result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and
|
||||
result = this.getFirstConditionInstruction(kind)
|
||||
or
|
||||
@@ -774,9 +914,87 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
|
||||
}
|
||||
}
|
||||
|
||||
class TranslatedConstExprIfStmt extends TranslatedStmt, ConditionContext {
|
||||
override ConstexprIfStmt stmt;
|
||||
|
||||
override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
if this.hasInitialization()
|
||||
then result = this.getInitialization().getFirstInstruction(kind)
|
||||
else result = this.getFirstConditionInstruction(kind)
|
||||
}
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
id = 0 and result = this.getInitialization()
|
||||
or
|
||||
id = 1 and result = this.getCondition()
|
||||
or
|
||||
id = 2 and result = this.getThen()
|
||||
or
|
||||
id = 3 and result = this.getElse()
|
||||
}
|
||||
|
||||
private predicate hasInitialization() { exists(stmt.getInitialization()) }
|
||||
|
||||
private TranslatedStmt getInitialization() {
|
||||
result = getTranslatedStmt(stmt.getInitialization())
|
||||
}
|
||||
|
||||
private TranslatedCondition getCondition() {
|
||||
result = getTranslatedCondition(stmt.getCondition().getFullyConverted())
|
||||
}
|
||||
|
||||
private Instruction getFirstConditionInstruction(EdgeKind kind) {
|
||||
result = this.getCondition().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
private TranslatedStmt getThen() { result = getTranslatedStmt(stmt.getThen()) }
|
||||
|
||||
private TranslatedStmt getElse() { result = getTranslatedStmt(stmt.getElse()) }
|
||||
|
||||
private predicate hasElse() { exists(stmt.getElse()) }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildTrueSuccessor(TranslatedCondition child, EdgeKind kind) {
|
||||
child = this.getCondition() and
|
||||
result = this.getThen().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
|
||||
child = this.getCondition() and
|
||||
if this.hasElse()
|
||||
then result = this.getElse().getFirstInstruction(kind)
|
||||
else result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and
|
||||
result = this.getFirstConditionInstruction(kind)
|
||||
or
|
||||
(child = this.getThen() or child = this.getElse()) and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getThen().getALastInstruction()
|
||||
or
|
||||
result = this.getElse().getALastInstruction()
|
||||
}
|
||||
}
|
||||
|
||||
abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
|
||||
override Loop stmt;
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getCondition().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getCondition() }
|
||||
|
||||
final TranslatedCondition getCondition() {
|
||||
result = getTranslatedCondition(stmt.getCondition().getFullyConverted())
|
||||
}
|
||||
@@ -791,7 +1009,7 @@ abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
|
||||
|
||||
final predicate hasCondition() { exists(stmt.getCondition()) }
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
id = 0 and result = this.getCondition()
|
||||
or
|
||||
id = 1 and result = this.getBody()
|
||||
@@ -801,13 +1019,15 @@ abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
|
||||
none()
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
|
||||
final override Instruction getChildTrueSuccessor(TranslatedCondition child, EdgeKind kind) {
|
||||
child = this.getCondition() and result = this.getBody().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
final override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
|
||||
override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
|
||||
child = this.getCondition() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
@@ -816,13 +1036,36 @@ abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
|
||||
class TranslatedWhileStmt extends TranslatedLoop {
|
||||
TranslatedWhileStmt() { stmt instanceof WhileStmt }
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
id = 0 and result = this.getCondition()
|
||||
or
|
||||
id = 1 and result = this.getBody()
|
||||
or
|
||||
exists(int n |
|
||||
result.getAst() = stmt.getImplicitDestructorCall(n) and
|
||||
id = 2 + n
|
||||
)
|
||||
}
|
||||
|
||||
override predicate handlesDestructorsExplicitly() { any() }
|
||||
|
||||
final override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
|
||||
child = this.getCondition() and
|
||||
if this.hasAnImplicitDestructorCall()
|
||||
then result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind)
|
||||
else result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getFirstConditionInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getBody() and
|
||||
result = this.getFirstConditionInstruction(kind)
|
||||
or
|
||||
child = this.getChild(this.getFirstDestructorCallIndex()) and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -833,7 +1076,7 @@ class TranslatedDoStmt extends TranslatedLoop {
|
||||
result = this.getBody().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getBody() and
|
||||
result = this.getFirstConditionInstruction(kind)
|
||||
}
|
||||
@@ -842,7 +1085,16 @@ class TranslatedDoStmt extends TranslatedLoop {
|
||||
class TranslatedForStmt extends TranslatedLoop {
|
||||
override ForStmt stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
override predicate handlesDestructorsExplicitly() { any() }
|
||||
|
||||
final override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
|
||||
child = this.getCondition() and
|
||||
if this.hasAnImplicitDestructorCall()
|
||||
then result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind)
|
||||
else result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
id = 0 and result = this.getInitialization()
|
||||
or
|
||||
id = 1 and result = this.getCondition()
|
||||
@@ -850,6 +1102,11 @@ class TranslatedForStmt extends TranslatedLoop {
|
||||
id = 2 and result = this.getUpdate()
|
||||
or
|
||||
id = 3 and result = this.getBody()
|
||||
or
|
||||
exists(int n |
|
||||
result.getAst() = stmt.getImplicitDestructorCall(n) and
|
||||
id = 4 + n
|
||||
)
|
||||
}
|
||||
|
||||
private TranslatedStmt getInitialization() {
|
||||
@@ -868,7 +1125,7 @@ class TranslatedForStmt extends TranslatedLoop {
|
||||
else result = this.getFirstConditionInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and
|
||||
result = this.getFirstConditionInstruction(kind)
|
||||
or
|
||||
@@ -880,6 +1137,19 @@ class TranslatedForStmt extends TranslatedLoop {
|
||||
)
|
||||
or
|
||||
child = this.getUpdate() and result = this.getFirstConditionInstruction(kind)
|
||||
or
|
||||
exists(int destructorId |
|
||||
destructorId >= this.getFirstDestructorCallIndex() and
|
||||
child = this.getChild(destructorId) and
|
||||
result = this.getChild(destructorId + 1).getFirstInstruction(kind)
|
||||
)
|
||||
or
|
||||
exists(int lastDestructorIndex |
|
||||
lastDestructorIndex =
|
||||
max(int n | exists(this.getChild(n)) and n >= this.getFirstDestructorCallIndex()) and
|
||||
child = this.getChild(lastDestructorIndex) and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -893,26 +1163,45 @@ class TranslatedForStmt extends TranslatedLoop {
|
||||
class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
|
||||
override RangeBasedForStmt stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getRangeVariableDeclStmt()
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
id = 0 and result = this.getInitialization()
|
||||
or
|
||||
id = 1 and result = this.getRangeVariableDeclStmt()
|
||||
or
|
||||
// Note: `__begin` and `__end` are declared by the same `DeclStmt`
|
||||
id = 1 and result = this.getBeginEndVariableDeclStmt()
|
||||
id = 2 and result = this.getBeginEndVariableDeclStmt()
|
||||
or
|
||||
id = 2 and result = this.getCondition()
|
||||
id = 3 and result = this.getCondition()
|
||||
or
|
||||
id = 3 and result = this.getUpdate()
|
||||
id = 4 and result = this.getUpdate()
|
||||
or
|
||||
id = 4 and result = this.getVariableDeclStmt()
|
||||
id = 5 and result = this.getVariableDeclStmt()
|
||||
or
|
||||
id = 5 and result = this.getBody()
|
||||
id = 6 and result = this.getBody()
|
||||
}
|
||||
|
||||
private predicate hasInitialization() { exists(stmt.getInitialization()) }
|
||||
|
||||
private TranslatedStmt getInitialization() {
|
||||
result = getTranslatedStmt(stmt.getInitialization())
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getRangeVariableDeclStmt().getFirstInstruction(kind)
|
||||
if this.hasInitialization()
|
||||
then result = this.getInitialization().getFirstInstruction(kind)
|
||||
else result = this.getFirstRangeVariableDeclStmtInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getCondition().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getCondition() }
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and
|
||||
result = this.getFirstRangeVariableDeclStmtInstruction(kind)
|
||||
or
|
||||
child = this.getRangeVariableDeclStmt() and
|
||||
result = this.getBeginEndVariableDeclStmt().getFirstInstruction(kind)
|
||||
or
|
||||
@@ -933,7 +1222,7 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildTrueSuccessor(TranslatedCondition child, EdgeKind kind) {
|
||||
child = this.getCondition() and
|
||||
@@ -952,6 +1241,10 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
|
||||
)
|
||||
}
|
||||
|
||||
private Instruction getFirstRangeVariableDeclStmtInstruction(EdgeKind kind) {
|
||||
result = this.getRangeVariableDeclStmt().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
private TranslatedDeclStmt getBeginEndVariableDeclStmt() {
|
||||
exists(IRVariableDeclarationEntry entry |
|
||||
entry.getStmt() = stmt.getBeginEndDeclaration() and
|
||||
@@ -987,7 +1280,11 @@ class TranslatedJumpStmt extends TranslatedStmt {
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override TranslatedElement getChildInternal(int id) { none() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
@@ -995,12 +1292,12 @@ class TranslatedJumpStmt extends TranslatedStmt {
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = getTranslatedStmt(stmt.getTarget()).getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
|
||||
}
|
||||
|
||||
private EdgeKind getCaseEdge(SwitchCase switchCase) {
|
||||
@@ -1031,7 +1328,13 @@ class TranslatedSwitchStmt extends TranslatedStmt {
|
||||
else result = this.getFirstExprInstruction(kind)
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getBody().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getBody() }
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
id = 0 and result = this.getInitialization()
|
||||
or
|
||||
id = 1 and result = this.getExpr()
|
||||
@@ -1057,7 +1360,7 @@ class TranslatedSwitchStmt extends TranslatedStmt {
|
||||
result = this.getExpr().getResult()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
tag = SwitchBranchTag() and
|
||||
exists(SwitchCase switchCase |
|
||||
switchCase = stmt.getASwitchCase() and
|
||||
@@ -1071,7 +1374,7 @@ class TranslatedSwitchStmt extends TranslatedStmt {
|
||||
result = this.getParent().getChildSuccessor(this, any(GotoEdge edge))
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and
|
||||
result = this.getFirstExprInstruction(kind)
|
||||
or
|
||||
@@ -1086,7 +1389,7 @@ class TranslatedSwitchStmt extends TranslatedStmt {
|
||||
class TranslatedAsmStmt extends TranslatedStmt {
|
||||
override AsmStmt stmt;
|
||||
|
||||
override TranslatedExpr getChild(int id) {
|
||||
override TranslatedExpr getChildInternal(int id) {
|
||||
result = getTranslatedExpr(stmt.getChild(id).(Expr).getFullyConverted())
|
||||
}
|
||||
|
||||
@@ -1098,6 +1401,8 @@ class TranslatedAsmStmt extends TranslatedStmt {
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() { result = this.getInstruction(AsmTag()) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = AsmTag() and
|
||||
opcode instanceof Opcode::InlineAsm and
|
||||
@@ -1108,7 +1413,7 @@ class TranslatedAsmStmt extends TranslatedStmt {
|
||||
exists(int index |
|
||||
tag = AsmTag() and
|
||||
operandTag = asmOperand(index) and
|
||||
result = this.getChild(index).getResult()
|
||||
result = this.getChildInternal(index).getResult()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1120,12 +1425,12 @@ class TranslatedAsmStmt extends TranslatedStmt {
|
||||
result = getUnknownType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
tag = AsmTag() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int index |
|
||||
child = this.getChild(index) and
|
||||
if exists(this.getChild(index + 1))
|
||||
@@ -1140,7 +1445,7 @@ class TranslatedAsmStmt extends TranslatedStmt {
|
||||
class TranslatedVlaDimensionStmt extends TranslatedStmt {
|
||||
override VlaDimensionStmt stmt;
|
||||
|
||||
override TranslatedExpr getChild(int id) {
|
||||
override TranslatedExpr getChildInternal(int id) {
|
||||
id = 0 and
|
||||
result = getTranslatedExpr(stmt.getDimensionExpr().getFullyConverted())
|
||||
}
|
||||
@@ -1149,13 +1454,19 @@ class TranslatedVlaDimensionStmt extends TranslatedStmt {
|
||||
result = this.getChild(0).getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getChild(0).getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getChild(0) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getChild(0) and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
@@ -1164,13 +1475,17 @@ class TranslatedVlaDimensionStmt extends TranslatedStmt {
|
||||
class TranslatedVlaDeclarationStmt extends TranslatedStmt {
|
||||
override VlaDeclStmt stmt;
|
||||
|
||||
override TranslatedExpr getChild(int id) { none() }
|
||||
override TranslatedExpr getChildInternal(int id) { none() }
|
||||
|
||||
override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getInstruction(OnlyInstructionTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
// TODO: This needs a new kind of instruction that represents initialization of a VLA.
|
||||
// For now we just emit a `NoOp` instruction so that the CFG isn't incomplete.
|
||||
@@ -1179,10 +1494,10 @@ class TranslatedVlaDeclarationStmt extends TranslatedStmt {
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
|
||||
}
|
||||
|
||||
@@ -2125,13 +2125,6 @@ class ChiInstruction extends Instruction {
|
||||
*/
|
||||
final Instruction getPartial() { result = this.getPartialOperand().getDef() }
|
||||
|
||||
/**
|
||||
* Gets the bit range `[startBit, endBit)` updated by the partial operand of this `ChiInstruction`, relative to the start address of the total operand.
|
||||
*/
|
||||
final predicate getUpdatedInterval(int startBit, int endBit) {
|
||||
Construction::getIntervalUpdatedByChi(this, startBit, endBit)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the `ChiPartialOperand` totally, but not exactly, overlaps with the `ChiTotalOperand`.
|
||||
* This means that the `ChiPartialOperand` will not override the entire memory associated with the
|
||||
|
||||
@@ -233,20 +233,6 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the partial operand of this `ChiInstruction` updates the bit range
|
||||
* `[startBitOffset, endBitOffset)` of the total operand.
|
||||
*/
|
||||
cached
|
||||
predicate getIntervalUpdatedByChi(ChiInstruction chi, int startBitOffset, int endBitOffset) {
|
||||
exists(Alias::MemoryLocation location, OldInstruction oldInstruction |
|
||||
oldInstruction = getOldInstruction(chi.getPartial()) and
|
||||
location = Alias::getResultMemoryLocation(oldInstruction) and
|
||||
startBitOffset = Alias::getStartBitOffset(location) and
|
||||
endBitOffset = Alias::getEndBitOffset(location)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `operand` totally overlaps with its definition and consumes the bit range
|
||||
* `[startBitOffset, endBitOffset)`.
|
||||
|
||||
@@ -11,7 +11,7 @@ private int getTypeSizeWorkaround(Type type) {
|
||||
exists(Type unspecifiedType |
|
||||
unspecifiedType = type.getUnspecifiedType() and
|
||||
(
|
||||
unspecifiedType instanceof FunctionReferenceType and
|
||||
(unspecifiedType instanceof FunctionReferenceType or unspecifiedType instanceof RoutineType) and
|
||||
result = getPointerSize()
|
||||
or
|
||||
exists(PointerToMemberType ptmType |
|
||||
@@ -176,7 +176,7 @@ private IRType getIRTypeForPRValue(Type type) {
|
||||
isPointerIshType(unspecifiedType) and
|
||||
result.(IRAddressType).getByteSize() = getTypeSize(unspecifiedType)
|
||||
or
|
||||
unspecifiedType instanceof FunctionPointerIshType and
|
||||
(unspecifiedType instanceof FunctionPointerIshType or unspecifiedType instanceof RoutineType) and
|
||||
result.(IRFunctionAddressType).getByteSize() = getTypeSize(type)
|
||||
or
|
||||
unspecifiedType instanceof VoidType and result instanceof IRVoidType
|
||||
|
||||
@@ -3,6 +3,7 @@ private import implementations.Deallocation
|
||||
private import implementations.Fread
|
||||
private import implementations.Getenv
|
||||
private import implementations.Gets
|
||||
private import implementations.GetText
|
||||
private import implementations.IdentityFunction
|
||||
private import implementations.Inet
|
||||
private import implementations.Iterator
|
||||
|
||||
@@ -15,6 +15,8 @@ private class GetDelimFunction extends TaintFunction, AliasFunction, SideEffectF
|
||||
i.isParameter(3) and o.isParameterDeref(0)
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput o) { o.isParameterDeref(3) }
|
||||
|
||||
override predicate parameterNeverEscapes(int index) { index = [0, 1, 3] }
|
||||
|
||||
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import semmle.code.cpp.models.interfaces.DataFlow
|
||||
|
||||
/**
|
||||
* Returns the transated text index for a given gettext function `f`
|
||||
*/
|
||||
private int getTextArg(Function f) {
|
||||
// basic variations of gettext
|
||||
f.hasGlobalOrStdName("gettext") and result = 0
|
||||
or
|
||||
f.hasGlobalOrStdName("dgettext") and result = 1
|
||||
or
|
||||
f.hasGlobalOrStdName("dcgettext") and result = 1
|
||||
or
|
||||
// plural variations of gettext that take one format string for singular and another for plural form
|
||||
f.hasGlobalOrStdName("ngettext") and
|
||||
(result = 0 or result = 1)
|
||||
or
|
||||
f.hasGlobalOrStdName("dngettext") and
|
||||
(result = 1 or result = 2)
|
||||
or
|
||||
f.hasGlobalOrStdName("dcngettext") and
|
||||
(result = 1 or result = 2)
|
||||
}
|
||||
|
||||
class GetTextFunction extends DataFlowFunction {
|
||||
int argInd;
|
||||
|
||||
GetTextFunction() { argInd = getTextArg(this) }
|
||||
|
||||
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
||||
input.isParameterDeref(argInd) and output.isReturnValueDeref()
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,8 @@ private class FgetsFunction extends DataFlowFunction, TaintFunction, ArrayFuncti
|
||||
output.isReturnValue()
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isParameterDeref(2) }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
input.isParameter(2) and
|
||||
output.isParameterDeref(0)
|
||||
|
||||
@@ -20,6 +20,8 @@ private class InetAton extends TaintFunction, ArrayFunction {
|
||||
output.isParameterDeref(1)
|
||||
}
|
||||
|
||||
override predicate isPartialWrite(FunctionOutput output) { output.isParameterDeref(1) }
|
||||
|
||||
override predicate hasArrayInput(int bufParam) { bufParam = 0 }
|
||||
|
||||
override predicate hasArrayOutput(int bufParam) { bufParam = 1 }
|
||||
|
||||
@@ -22,11 +22,28 @@ private class MemsetFunctionModel extends ArrayFunction, DataFlowFunction, Alias
|
||||
])
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index of the parameter that specifies the fill character to insert, if any.
|
||||
*/
|
||||
private int getFillCharParameterIndex() {
|
||||
(
|
||||
this.hasGlobalOrStdOrBslName("memset")
|
||||
or
|
||||
this.hasGlobalOrStdName("wmemset")
|
||||
or
|
||||
this.hasGlobalName(["__builtin_memset", "__builtin_memset_chk"])
|
||||
) and
|
||||
result = 1
|
||||
}
|
||||
|
||||
override predicate hasArrayOutput(int bufParam) { bufParam = 0 }
|
||||
|
||||
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
||||
input.isParameter(0) and
|
||||
output.isReturnValue()
|
||||
or
|
||||
input.isParameter(this.getFillCharParameterIndex()) and
|
||||
(output.isParameterDeref(0) or output.isReturnValueDeref())
|
||||
}
|
||||
|
||||
override predicate hasArrayWithVariableSize(int bufParam, int countParam) {
|
||||
|
||||
@@ -168,3 +168,57 @@ private class SmartPtrSetterFunction extends MemberFunction, AliasFunction, Side
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A destructor assocaited with a smart pointer. */
|
||||
private class SmartPtrDestructor extends Destructor, SideEffectFunction, AliasFunction {
|
||||
SmartPtr declaringType;
|
||||
|
||||
SmartPtrDestructor() {
|
||||
declaringType = this.getDeclaringType() and not this.isFromUninstantiatedTemplate(_)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the destructor associated with the base type of this smart pointer.
|
||||
*/
|
||||
private Destructor getBaseTypeDestructor() {
|
||||
result.getDeclaringType() = declaringType.getBaseType()
|
||||
}
|
||||
|
||||
override predicate hasOnlySpecificReadSideEffects() {
|
||||
this.getBaseTypeDestructor().(SideEffectFunction).hasOnlySpecificReadSideEffects()
|
||||
or
|
||||
// If there's no declared destructor for the base type then it won't have
|
||||
// any strange read side effects.
|
||||
not exists(this.getBaseTypeDestructor())
|
||||
}
|
||||
|
||||
override predicate hasOnlySpecificWriteSideEffects() {
|
||||
this.getBaseTypeDestructor().(SideEffectFunction).hasOnlySpecificWriteSideEffects()
|
||||
or
|
||||
// If there's no declared destructor for the base type then it won't have
|
||||
// any strange write side effects.
|
||||
not exists(this.getBaseTypeDestructor())
|
||||
}
|
||||
|
||||
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||
i = -1 and buffer = false
|
||||
}
|
||||
|
||||
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||
i = -1 and buffer = false and mustWrite = true
|
||||
}
|
||||
|
||||
override predicate parameterNeverEscapes(int index) {
|
||||
this.getBaseTypeDestructor().(AliasFunction).parameterNeverEscapes(index)
|
||||
or
|
||||
// If there's no declared destructor for the base type then it won't cause
|
||||
// anything to escape.
|
||||
not exists(this.getBaseTypeDestructor()) and
|
||||
index = -1
|
||||
}
|
||||
|
||||
override predicate parameterEscapesOnlyViaReturn(int index) {
|
||||
// A destructor call does not have a return value
|
||||
none()
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user