Compare commits

..

1 Commits

Author SHA1 Message Date
github-actions[bot]
086cf1017f Release preparation for version 2.16.0 2024-01-12 15:29:27 +00:00
2409 changed files with 68399 additions and 145658 deletions

View File

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

View File

@@ -1 +1 @@
6.5.0
6.3.1

View File

@@ -1 +0,0 @@
DisableFormat: true

4
.gitattributes vendored
View File

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

View File

@@ -1,8 +1,5 @@
name: Check change note
permissions:
pull-requests: read
on:
pull_request_target:
types: [labeled, unlabeled, opened, synchronize, reopened, ready_for_review]

View File

@@ -9,9 +9,6 @@ on:
- main
- "rc/*"
permissions:
contents: read
jobs:
check:
runs-on: ubuntu-latest

View File

@@ -10,9 +10,6 @@ on:
- main
- "rc/*"
permissions:
contents: read
jobs:
qldoc:
runs-on: ubuntu-latest

View File

@@ -11,9 +11,6 @@ on:
- "rc/*"
workflow_dispatch:
permissions:
contents: read
jobs:
check:
name: Check query IDs

View File

@@ -5,9 +5,6 @@ on:
schedule:
- cron: "30 1 * * *"
permissions:
issues: write
jobs:
stale:
if: github.repository == 'github/codeql'

View File

@@ -30,7 +30,7 @@ jobs:
- name: Setup dotnet
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.101
dotnet-version: 8.0.100
- name: Checkout repository
uses: actions/checkout@v4

View File

@@ -8,12 +8,8 @@ on:
- "codeql-cli-*"
pull_request:
permissions:
contents: read
jobs:
compile-queries:
if: github.repository_owner == 'github'
runs-on: ubuntu-latest-xl
steps:

View File

@@ -25,9 +25,6 @@ defaults:
run:
working-directory: csharp
permissions:
contents: read
jobs:
qlupgrade:
runs-on: ubuntu-latest
@@ -49,7 +46,6 @@ 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
@@ -78,13 +74,13 @@ jobs:
- name: Setup dotnet
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.101
dotnet-version: 8.0.100
- name: Extractor unit tests
run: |
dotnet test -p:RuntimeFrameworkVersion=8.0.1 extractor/Semmle.Util.Tests
dotnet test -p:RuntimeFrameworkVersion=8.0.1 extractor/Semmle.Extraction.Tests
dotnet test -p:RuntimeFrameworkVersion=8.0.1 autobuilder/Semmle.Autobuild.CSharp.Tests
dotnet test -p:RuntimeFrameworkVersion=8.0.1 "${{ github.workspace }}/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests"
dotnet test -p:RuntimeFrameworkVersion=8.0.0 extractor/Semmle.Util.Tests
dotnet test -p:RuntimeFrameworkVersion=8.0.0 extractor/Semmle.Extraction.Tests
dotnet test -p:RuntimeFrameworkVersion=8.0.0 autobuilder/Semmle.Autobuild.CSharp.Tests
dotnet test -p:RuntimeFrameworkVersion=8.0.0 "${{ github.workspace }}/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests"
shell: bash
stubgentest:
runs-on: ubuntu-latest

View File

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

View File

@@ -19,10 +19,6 @@ on:
- main
- "rc/*"
permissions:
contents: read
pull-requests: read
jobs:
generate:
name: Generate framework coverage artifacts

View File

@@ -6,10 +6,6 @@ on:
types:
- completed
permissions:
contents: read
pull-requests: write
jobs:
check:
name: Check framework coverage differences and comment

View File

@@ -3,9 +3,6 @@ name: Build framework coverage timeseries reports
on:
workflow_dispatch:
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest

View File

@@ -5,10 +5,6 @@ on:
schedule:
- cron: "0 0 * * *"
permissions:
contents: write
pull-requests: write
jobs:
update:
name: Update framework coverage report

View File

@@ -7,9 +7,6 @@ on:
description: "github/codeql repo SHA used for looking up the CSV models"
required: false
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest

View File

@@ -7,14 +7,13 @@ 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:

View File

@@ -8,11 +8,7 @@ on:
- .github/actions/**
- codeql-workspace.yml
env:
GO_VERSION: '~1.22.0'
permissions:
contents: read
GO_VERSION: '~1.21.0'
jobs:
test-mac:
name: Test MacOS
@@ -22,7 +18,6 @@ jobs:
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
cache: false
id: go
- name: Check out code
@@ -51,7 +46,6 @@ 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:
@@ -59,7 +53,6 @@ jobs:
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
cache: false
id: go
- name: Check out code

View File

@@ -15,16 +15,10 @@ on:
- .github/workflows/go-tests.yml
- .github/actions/**
- codeql-workspace.yml
env:
GO_VERSION: '~1.22.0'
permissions:
contents: read
GO_VERSION: '~1.21.0'
jobs:
test-linux:
if: github.repository_owner == 'github'
name: Test Linux (Ubuntu)
runs-on: ubuntu-latest-xl
steps:
@@ -32,7 +26,6 @@ jobs:
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
cache: false
id: go
- name: Check out code

View File

@@ -2,12 +2,11 @@ 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

View File

@@ -12,7 +12,6 @@ on:
- main
paths:
- "java/ql/src/utils/modelgenerator/**/*.*"
- "misc/scripts/models-as-data/*.*"
- ".github/workflows/mad_modelDiff.yml"
permissions:
@@ -62,9 +61,8 @@ jobs:
DATABASE=$2
cd codeql-$QL_VARIANT
SHORTNAME=`basename $DATABASE`
python java/ql/src/utils/modelgenerator/GenerateFlowModel.py --with-summaries --with-sinks $DATABASE $SHORTNAME/$QL_VARIANT
mkdir -p $MODELS/$SHORTNAME
mv java/ql/lib/ext/generated/$SHORTNAME/$QL_VARIANT $MODELS/$SHORTNAME
python java/ql/src/utils/modelgenerator/GenerateFlowModel.py --with-summaries --with-sinks $DATABASE ${SHORTNAME}.temp.model.yml
mv java/ql/lib/ext/generated/${SHORTNAME}.temp.model.yml $MODELS/${SHORTNAME}Generated_${QL_VARIANT}.model.yml
cd ..
}
@@ -87,16 +85,16 @@ jobs:
set -x
MODELS=`pwd`/tmp-models
ls -1 tmp-models/
for m in $MODELS/*/main/*.model.yml ; do
for m in $MODELS/*_main.model.yml ; do
t="${m/main/"pr"}"
basename=`basename $m`
name="diff_${basename/.model.yml/""}"
name="diff_${basename/_main.model.yml/""}"
(diff -w -u $m $t | diff2html -i stdin -F $MODELS/$name.html) || true
done
- uses: actions/upload-artifact@v3
with:
name: models
path: tmp-models/**/**/*.model.yml
path: tmp-models/*.model.yml
retention-days: 20
- uses: actions/upload-artifact@v3
with:

View File

@@ -11,9 +11,6 @@ on:
- ".github/workflows/mad_regenerate-models.yml"
- ".github/actions/fetch-codeql/action.yml"
permissions:
contents: read
jobs:
regenerate-models:
runs-on: ubuntu-latest

View File

@@ -77,7 +77,7 @@ jobs:
done < "${RUNNER_TEMP}/paths.txt" >> comment_body.txt
exit "${EXIT_CODE}"
- if: ${{ !cancelled() }}
- if: always()
uses: actions/upload-artifact@v3
with:
name: comment

View File

@@ -9,13 +9,8 @@ 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 ###
@@ -24,7 +19,7 @@ jobs:
fetch-depth: 0
- name: Find codeql
id: find-codeql
uses: github/codeql-action/init@main
uses: github/codeql-action/init@v2
with:
languages: javascript # does not matter
- uses: ./.github/actions/os-version
@@ -70,7 +65,7 @@ jobs:
exclude:*/ql/lib/upgrades/
exclude:java/ql/integration-tests
- name: Upload sarif to code-scanning
uses: github/codeql-action/upload-sarif@main
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: ql-for-ql.sarif
category: ql-for-ql

View File

@@ -11,10 +11,6 @@ on:
- ql/ql/src/ql.dbscheme
workflow_dispatch:
permissions:
contents: read
security-events: read
jobs:
measure:
env:
@@ -29,7 +25,7 @@ jobs:
- name: Find codeql
id: find-codeql
uses: github/codeql-action/init@main
uses: github/codeql-action/init@v2
with:
languages: javascript # does not matter
- uses: ./.github/actions/os-version

View File

@@ -17,9 +17,6 @@ on:
env:
CARGO_TERM_COLOR: always
permissions:
contents: read
jobs:
qltest:
runs-on: ubuntu-latest
@@ -27,7 +24,7 @@ jobs:
- uses: actions/checkout@v4
- name: Find codeql
id: find-codeql
uses: github/codeql-action/init@main
uses: github/codeql-action/init@v2
with:
languages: javascript # does not matter
- uses: ./.github/actions/os-version
@@ -72,7 +69,7 @@ jobs:
echo "/usr/local/opt/gnu-tar/libexec/gnubin" >> $GITHUB_PATH
- name: Find codeql
id: find-codeql
uses: github/codeql-action/init@main
uses: github/codeql-action/init@v2
with:
languages: javascript # does not matter
- uses: ./.github/actions/os-version

View File

@@ -13,9 +13,6 @@ on:
- '.github/actions/fetch-codeql/action.yml'
- 'misc/scripts/generate-code-scanning-query-list.py'
permissions:
contents: read
jobs:
build:

View File

@@ -32,9 +32,6 @@ defaults:
run:
working-directory: ruby
permissions:
contents: read
jobs:
build:
strategy:
@@ -51,11 +48,9 @@ jobs:
run: |
brew install gnu-tar
echo "/usr/local/opt/gnu-tar/libexec/gnubin" >> $GITHUB_PATH
- name: Prepare Windows
if: runner.os == 'Windows'
shell: powershell
run: |
git config --global core.longpaths true
- name: Install cargo-cross
if: runner.os == 'Linux'
run: cargo install cross --version 0.2.5
- uses: ./.github/actions/os-version
id: os_version
- name: Cache entire extractor
@@ -84,8 +79,16 @@ jobs:
- name: Run tests
if: steps.cache-extractor.outputs.cache-hit != 'true'
run: cd extractor && cargo test --verbose
- name: Release build
if: steps.cache-extractor.outputs.cache-hit != 'true'
# 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'
run: cd extractor && cargo build --release
- name: Generate dbscheme
if: ${{ matrix.os == 'ubuntu-latest' && steps.cache-extractor.outputs.cache-hit != 'true'}}
@@ -108,7 +111,6 @@ 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
@@ -117,7 +119,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: |
@@ -229,3 +231,54 @@ 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

View File

@@ -17,9 +17,6 @@ on:
- .github/workflows/ruby-dataset-measure.yml
workflow_dispatch:
permissions:
contents: read
jobs:
measure:
env:

View File

@@ -29,9 +29,6 @@ defaults:
run:
working-directory: ruby
permissions:
contents: read
jobs:
qlupgrade:
runs-on: ubuntu-latest
@@ -53,7 +50,6 @@ 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

View File

@@ -33,62 +33,46 @@ 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.repository_owner == 'github' && github.event_name == 'pull_request' }}
if : ${{ 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.repository_owner == 'github' && github.event_name == 'pull_request' }}
if : ${{ github.event_name == 'pull_request' }}
needs: build-and-test-macos
runs-on: macos-12-xl
timeout-minutes: 60
steps:
- uses: actions/checkout@v4
- uses: ./swift/actions/run-integration-tests
clang-format:
if : ${{ github.event_name == 'pull_request' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pre-commit/action@646c83fcd040023954eafda54b4db0192ce70507
name: Check that python code is properly formatted
with:
extra_args: clang-format --all-files
codegen:
if : ${{ github.event_name == 'pull_request' }}
runs-on: ubuntu-latest
@@ -98,12 +82,12 @@ jobs:
- uses: actions/setup-python@v4
with:
python-version-file: 'swift/.python-version'
- uses: pre-commit/action@646c83fcd040023954eafda54b4db0192ce70507
- uses: pre-commit/action@v3.0.0
name: Check that python code is properly formatted
with:
extra_args: autopep8 --all-files
- uses: ./.github/actions/fetch-codeql
- uses: pre-commit/action@646c83fcd040023954eafda54b4db0192ce70507
- uses: pre-commit/action@v3.0.0
name: Check that QL generated code was checked in
with:
extra_args: swift-codegen --all-files

View File

@@ -10,9 +10,6 @@ on:
- main
- 'rc/*'
permissions:
contents: read
jobs:
sync:
runs-on: ubuntu-latest

View File

@@ -23,9 +23,6 @@ defaults:
run:
working-directory: shared/tree-sitter-extractor
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest

View File

@@ -15,9 +15,6 @@ on:
- ".github/workflows/validate-change-notes.yml"
- ".github/actions/fetch-codeql/action.yml"
permissions:
contents: read
jobs:
check-change-note:
runs-on: ubuntu-latest

View File

@@ -10,9 +10,10 @@ repos:
exclude: /test/.*$(?<!\.ql)(?<!\.qll)(?<!\.qlref)|.*\.patch
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v17.0.6
rev: v13.0.1
hooks:
- id: clang-format
files: ^swift/.*\.(h|c|cpp)$
- repo: https://github.com/pre-commit/mirrors-autopep8
rev: v1.6.0

View File

@@ -25,7 +25,6 @@
# 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

View File

@@ -1,69 +0,0 @@
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")
bazel_dep(name = "rules_rust", version = "0.39.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",
)
crate = use_extension(
"@rules_rust//crate_universe:extension.bzl",
"crate",
)
crate.from_cargo(
name = "r", # short name due to long path issues on windows
cargo_lockfile = "//ruby/extractor:Cargo.lock",
manifests = [
"//ruby/extractor:Cargo.toml",
],
)
use_repo(crate, "r")

View File

@@ -1,2 +1,12 @@
# please use MODULE.bazel to add dependencies
# this empty file is required by internal repositories, don't remove it
# 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()

View File

@@ -473,6 +473,10 @@
"ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModelsExtensions.qll",
"python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsExtensions.qll"
],
"Typo database": [
"javascript/ql/src/Expressions/TypoDatabase.qll",
"ql/ql/src/codeql_ql/style/TypoDatabase.qll"
],
"Swift declarations test file": [
"swift/ql/test/extractor-tests/declarations/declarations.swift",
"swift/ql/test/library-tests/ast/declarations.swift"

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,11 +0,0 @@
class Declaration extends @declaration {
string toString() { none() }
}
class MangledName extends @mangledname {
string toString() { none() }
}
from Declaration d, MangledName n
where mangled_name(d, n, _)
select d, n

View File

@@ -1,3 +0,0 @@
description: Add completness information to mangled name table
compatibility: full
mangled_name.rel: run mangled_name.qlo

View File

@@ -1,6 +1,5 @@
description: Support C++17 if and switch initializers
compatibility: partial
constexpr_if_initialization.rel: delete
if_initialization.rel: delete
switch_initialization.rel: delete
exprparents.rel: run exprparents.qlo

View File

@@ -1,22 +1,6 @@
## 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
* Deleted many deprecated predicates and classes with uppercase `XML`, `SSA`, `SAL`, `SQL`, etc. in their names. Use the PascalCased versions instead.
* Deleted the deprecated `StrcatFunction` class, use `semmle.code.cpp.models.implementations.Strcat.qll` instead.
No user-facing changes.
## 0.12.3

View File

@@ -1,6 +1,3 @@
## 0.12.4
### Minor Analysis Improvements
* Deleted many deprecated predicates and classes with uppercase `XML`, `SSA`, `SAL`, `SQL`, etc. in their names. Use the PascalCased versions instead.
* Deleted the deprecated `StrcatFunction` class, use `semmle.code.cpp.models.implementations.Strcat.qll` instead.
No user-facing changes.

View File

@@ -1,6 +0,0 @@
## 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.

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.12.6
lastReleaseVersion: 0.12.4

View File

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

View File

@@ -380,6 +380,9 @@ class Class extends UserType {
*/
predicate isPod() { is_pod_class(underlyingElement(this)) }
/** DEPRECATED: Alias for isPod */
deprecated predicate isPOD() { this.isPod() }
/**
* Holds if this class, struct or union is a standard-layout class
* [N4140 9(7)]. Also holds for structs in C programs.

View File

@@ -7,7 +7,6 @@ import semmle.code.cpp.Location
private import semmle.code.cpp.Enclosing
private import semmle.code.cpp.internal.ResolveClass
private import semmle.code.cpp.internal.ResolveGlobalVariable
private import semmle.code.cpp.internal.ResolveFunction
/**
* Get the `Element` that represents this `@element`.
@@ -31,14 +30,11 @@ pragma[inline]
@element unresolveElement(Element e) {
not result instanceof @usertype and
not result instanceof @variable and
not result instanceof @function and
result = e
or
e = resolveClass(result)
or
e = resolveGlobalVariable(result)
or
e = resolveFunction(result)
}
/**

View File

@@ -9,7 +9,6 @@ import semmle.code.cpp.exprs.Call
import semmle.code.cpp.metrics.MetricFunction
import semmle.code.cpp.Linkage
private import semmle.code.cpp.internal.ResolveClass
private import semmle.code.cpp.internal.ResolveFunction
/**
* A C/C++ function [N4140 8.3.5]. Both member functions and non-member
@@ -26,8 +25,6 @@ private import semmle.code.cpp.internal.ResolveFunction
* in more detail in `Declaration.qll`.
*/
class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
Function() { isFunction(underlyingElement(this)) }
override string getName() { functions(underlyingElement(this), result, _) }
/**

View File

@@ -104,6 +104,9 @@ predicate isPodClass03(Class c) {
)
}
/** DEPRECATED: Alias for isPodClass03 */
deprecated predicate isPODClass03 = isPodClass03/1;
/**
* Holds if `t` is a POD type, according to the rules specified in
* C++03 3.9(10):
@@ -123,3 +126,6 @@ predicate isPodType03(Type t) {
isPodType03(ut.(SpecifiedType).getUnspecifiedType())
)
}
/** DEPRECATED: Alias for isPodType03 */
deprecated predicate isPODType03 = isPodType03/1;

View File

@@ -306,14 +306,7 @@ class ExprNode extends AstNode {
ExprNode() { expr = ast }
override AstNode getChildInternal(int childIndex) {
result.getAst() = expr.getChild(childIndex)
or
exists(int destructorIndex |
result.getAst() = expr.getImplicitDestructorCall(destructorIndex) and
childIndex = destructorIndex + max(int index | exists(expr.getChild(index)) or index = 0) + 1
)
}
override AstNode getChildInternal(int childIndex) { result.getAst() = expr.getChild(childIndex) }
override string getProperty(string key) {
result = super.getProperty(key)
@@ -446,11 +439,6 @@ class StmtNode extends AstNode {
result.getAst() = child.(Stmt)
)
)
or
exists(int destructorIndex |
result.getAst() = stmt.getImplicitDestructorCall(destructorIndex) and
childIndex = destructorIndex + max(int index | exists(stmt.getChild(index)) or index = 0) + 1
)
}
override string getChildAccessorPredicateInternal(int childIndex) {
@@ -674,10 +662,6 @@ private string getChildAccessorWithoutConversions(Locatable parent, Element chil
or
not namedStmtChildPredicates(s, child, _) and
exists(int n | s.getChild(n) = child and result = "getChild(" + n + ")")
or
exists(int n |
s.getImplicitDestructorCall(n) = child and result = "getImplicitDestructorCall(" + n + ")"
)
)
or
exists(Expr expr | expr = parent |
@@ -685,11 +669,6 @@ private string getChildAccessorWithoutConversions(Locatable parent, Element chil
or
not namedExprChildPredicates(expr, child, _) and
exists(int n | expr.getChild(n) = child and result = "getChild(" + n + ")")
or
exists(int n |
expr.getImplicitDestructorCall(n) = child and
result = "getImplicitDestructorCall(" + n + ")"
)
)
)
}
@@ -735,9 +714,7 @@ private predicate namedStmtChildPredicates(Locatable s, Element e, string pred)
or
s.(ForStmt).getStmt() = e and pred = "getStmt()"
or
s.(RangeBasedForStmt).getInitialization() = e and pred = "getInitialization()"
or
s.(RangeBasedForStmt).getChild(1) = e and pred = "getChild(1)"
s.(RangeBasedForStmt).getChild(0) = e and pred = "getChild(0)"
or
s.(RangeBasedForStmt).getBeginEndDeclaration() = e and pred = "getBeginEndDeclaration()"
or
@@ -745,7 +722,7 @@ private predicate namedStmtChildPredicates(Locatable s, Element e, string pred)
or
s.(RangeBasedForStmt).getUpdate() = e and pred = "getUpdate()"
or
s.(RangeBasedForStmt).getChild(5) = e and pred = "getChild(5)"
s.(RangeBasedForStmt).getChild(4) = e and pred = "getChild(4)"
or
s.(RangeBasedForStmt).getStmt() = e and pred = "getStmt()"
or
@@ -837,11 +814,7 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
or
expr.(OverloadedArrayExpr).getArrayOffset() = ele and pred = "getArrayOffset()"
or
// 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()"
expr.(OverloadedPointerDereferenceExpr).getExpr() = ele and pred = "getExpr()"
or
expr.(CommaExpr).getLeftOperand() = ele and pred = "getLeftOperand()"
or

View File

@@ -234,16 +234,7 @@ class VariableDeclarationEntry extends DeclarationEntry, @var_decl {
* int f(int y) { return y; }
* ```
*/
override string getName() {
exists(string name |
var_decls(underlyingElement(this), _, _, name, _) and
(
name != "" and result = name
or
name = "" and result = this.getVariable().(LocalVariable).getName()
)
)
}
override string getName() { var_decls(underlyingElement(this), _, _, result, _) and result != "" }
/**
* Gets the type of the variable which is being declared or defined.

View File

@@ -32,6 +32,9 @@ class XmlLocatable extends @xmllocatable, TXmlLocatable {
string toString() { none() } // overridden in subclasses
}
/** DEPRECATED: Alias for XmlLocatable */
deprecated class XMLLocatable = XmlLocatable;
/**
* An `XmlParent` is either an `XmlElement` or an `XmlFile`,
* both of which can contain other elements.
@@ -92,6 +95,9 @@ class XmlParent extends @xmlparent {
string toString() { result = this.getName() }
}
/** DEPRECATED: Alias for XmlParent */
deprecated class XMLParent = XmlParent;
/** An XML file. */
class XmlFile extends XmlParent, File {
XmlFile() { xmlEncoding(this, _) }
@@ -113,8 +119,14 @@ class XmlFile extends XmlParent, File {
/** Gets a DTD associated with this XML file. */
XmlDtd getADtd() { xmlDTDs(result, _, _, _, this) }
/** DEPRECATED: Alias for getADtd */
deprecated XmlDtd getADTD() { result = this.getADtd() }
}
/** DEPRECATED: Alias for XmlFile */
deprecated class XMLFile = XmlFile;
/**
* An XML document type definition (DTD).
*
@@ -151,6 +163,9 @@ class XmlDtd extends XmlLocatable, @xmldtd {
}
}
/** DEPRECATED: Alias for XmlDtd */
deprecated class XMLDTD = XmlDtd;
/**
* An XML element in an XML file.
*
@@ -206,6 +221,9 @@ class XmlElement extends @xmlelement, XmlParent, XmlLocatable {
override string toString() { result = this.getName() }
}
/** DEPRECATED: Alias for XmlElement */
deprecated class XMLElement = XmlElement;
/**
* An attribute that occurs inside an XML element.
*
@@ -236,6 +254,9 @@ class XmlAttribute extends @xmlattribute, XmlLocatable {
override string toString() { result = this.getName() + "=" + this.getValue() }
}
/** DEPRECATED: Alias for XmlAttribute */
deprecated class XMLAttribute = XmlAttribute;
/**
* A namespace used in an XML file.
*
@@ -252,6 +273,9 @@ class XmlNamespace extends XmlLocatable, @xmlnamespace {
/** Gets the URI of this namespace. */
string getUri() { xmlNs(this, _, result, _) }
/** DEPRECATED: Alias for getUri */
deprecated string getURI() { result = this.getUri() }
/** Holds if this namespace has no prefix. */
predicate isDefault() { this.getPrefix() = "" }
@@ -262,6 +286,9 @@ class XmlNamespace extends XmlLocatable, @xmlnamespace {
}
}
/** DEPRECATED: Alias for XmlNamespace */
deprecated class XMLNamespace = XmlNamespace;
/**
* A comment in an XML file.
*
@@ -282,6 +309,9 @@ class XmlComment extends @xmlcomment, XmlLocatable {
override string toString() { result = this.getText() }
}
/** DEPRECATED: Alias for XmlComment */
deprecated class XMLComment = XmlComment;
/**
* A sequence of characters that occurs between opening and
* closing tags of an XML element, excluding other elements.
@@ -305,3 +335,6 @@ class XmlCharacters extends @xmlcharacters, XmlLocatable {
/** Gets a printable representation of this XML character sequence. */
override string toString() { result = this.getCharacters() }
}
/** DEPRECATED: Alias for XmlCharacters */
deprecated class XMLCharacters = XmlCharacters;

View File

@@ -5,6 +5,9 @@ class NullMacro extends Macro {
NullMacro() { this.getHead() = "NULL" }
}
/** DEPRECATED: Alias for NullMacro */
deprecated class NULLMacro = NullMacro;
/** A use of the NULL macro. */
class NULL extends Literal {
NULL() { exists(NullMacro nm | this = nm.getAnInvocation().getAnExpandedElement()) }

View File

@@ -0,0 +1,22 @@
import cpp
/**
* DEPRECATED: use `semmle.code.cpp.models.implementations.Strcat.qll` instead.
*
* A function that concatenates the string from its second argument
* to the string from its first argument, for example `strcat`.
*/
deprecated class StrcatFunction extends Function {
StrcatFunction() {
this.getName() =
[
"strcat", // strcat(dst, src)
"strncat", // strncat(dst, src, max_amount)
"wcscat", // wcscat(dst, src)
"_mbscat", // _mbscat(dst, src)
"wcsncat", // wcsncat(dst, src, max_amount)
"_mbsncat", // _mbsncat(dst, src, max_amount)
"_mbsncat_l" // _mbsncat_l(dst, src, max_amount, locale)
]
}
}

View File

@@ -1,101 +0,0 @@
/**
* A library for detecting general string concatenations.
*/
import cpp
import semmle.code.cpp.models.implementations.Strcat
import semmle.code.cpp.models.interfaces.FormattingFunction
private import semmle.code.cpp.dataflow.new.DataFlow
/**
* A call that performs a string concatenation. A string can be either a C
* string (i.e., a value of type `char*`), or a C++ string (i.e., a value of
* type `std::string`).
*/
class StringConcatenation extends Call {
StringConcatenation() {
// sprintf-like functions, i.e., concat through formatting
this instanceof FormattingFunctionCall
or
this.getTarget() instanceof StrcatFunction
or
this.getTarget() instanceof StrlcatFunction
or
// operator+ and ostream (<<) concat
exists(Call call, Operator op |
call.getTarget() = op and
op.hasQualifiedName(["std", "bsl"], ["operator+", "operator<<"]) and
op.getType()
.stripType()
.(UserType)
.hasQualifiedName(["std", "bsl"], ["basic_string", "basic_ostream"]) and
this = call
)
}
/**
* Gets an operand of this concatenation (one of the string operands being
* concatenated).
* Will not return out param for sprintf-like functions, but will consider the format string
* to be part of the operands.
*/
Expr getAnOperand() {
// The result is an argument of 'this' (a call)
result = this.getAnArgument() and
// addresses odd behavior with overloaded operators
// i.e., "call to operator+" appearing as an operand
// occurs in cases like `string s = s1 + s2 + s3`, which is represented as
// `string s = (s1.operator+(s2)).operator+(s3);`
// By limiting to non-calls we get the leaf operands (the variables or raw strings)
// also, by not enumerating allowed types (variables and strings) we avoid issues
// with missed corner cases or extensions/changes to CodeQL in the future which might
// invalidate that approach.
not result instanceof Call and
// Limit the result type to string
(
result.getUnderlyingType().stripType().getName() = "char"
or
result
.getType()
.getUnspecifiedType()
.(UserType)
.hasQualifiedName(["std", "bsl"], "basic_string")
) and
// when 'this' is a `FormattingFunctionCall` the result must be the format string argument
// or one of the formatting arguments
(
this instanceof FormattingFunctionCall
implies
(
result = this.(FormattingFunctionCall).getFormat()
or
exists(int n |
result = this.getArgument(n) and
n >= this.(FormattingFunctionCall).getTarget().getFirstFormatArgumentIndex()
)
)
)
}
/**
* Gets the data flow node representing the concatenation result.
*/
DataFlow::Node getResultNode() {
if this.getTarget() instanceof StrcatFunction
then
result.asDefiningArgument() =
this.getArgument(this.getTarget().(StrcatFunction).getParamDest())
or
// Hardcoding it is also the return
result.asExpr() = this.(Call)
else
if this.getTarget() instanceof StrlcatFunction
then (
result.asDefiningArgument() =
this.getArgument(this.getTarget().(StrlcatFunction).getParamDest())
) else
if this instanceof FormattingFunctionCall
then result.asDefiningArgument() = this.(FormattingFunctionCall).getOutputArgument(_)
else result.asExpr() = this.(Call)
}
}

View File

@@ -203,42 +203,30 @@ private class GuardConditionFromIR extends GuardCondition {
* `&&` and `||`. See the detailed explanation on predicate `controls`.
*/
private predicate controlsBlock(BasicBlock controlled, boolean testIsTrue) {
exists(IRBlock irb |
exists(IRBlock irb, Instruction instr |
ir.controls(irb, testIsTrue) and
nonExcludedIRAndBasicBlock(irb, controlled) and
not isUnreachedBlock(irb)
instr = irb.getAnInstruction() and
instr.getAst().(ControlFlowNode).getBasicBlock() = controlled and
not isUnreachedBlock(irb) and
not this.excludeAsControlledInstruction(instr)
)
}
}
private predicate excludeAsControlledInstruction(Instruction instr) {
// Exclude the temporaries generated by a ternary expression.
exists(TranslatedConditionalExpr tce |
instr = tce.getInstruction(ConditionValueFalseStoreTag())
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())
)
or
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)
)
// Exclude unreached instructions, as their AST is the whole function and not a block.
instr instanceof UnreachedInstruction
}
}
/**

View File

@@ -637,10 +637,8 @@ 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 = 1 and ni = s and spec.isAround()
i = 0 and ni = s and spec.isAround()
)
or
exists(DeclStmt s |
@@ -651,22 +649,22 @@ private predicate straightLineSparse(Node scope, int i, Node ni, Spec spec) {
// DeclStmt in that case.
exists(s.getADeclaration())
|
i = 2 and ni = s and spec.isAround()
i = 1 and ni = s and spec.isAround()
)
or
i = 3 and ni = for.getCondition() and spec.isBefore()
i = 2 and ni = for.getCondition() and spec.isBefore()
or
i = 4 and /* BARRIER */ ni = for and spec.isBarrier()
i = 3 and /* BARRIER */ ni = for and spec.isBarrier()
or
exists(DeclStmt declStmt | declStmt.getADeclaration() = for.getVariable() |
i = 5 and ni = declStmt and spec.isAfter()
i = 4 and ni = declStmt and spec.isAfter()
)
or
i = 6 and ni = for.getStmt() and spec.isAround()
i = 5 and ni = for.getStmt() and spec.isAround()
or
i = 7 and ni = for.getUpdate() and spec.isAround()
i = 6 and ni = for.getUpdate() and spec.isAround()
or
i = 8 and ni = for.getCondition() and spec.isBefore()
i = 7 and ni = for.getCondition() and spec.isBefore()
)
or
scope =

View File

@@ -54,6 +54,18 @@ private predicate functionSignature(Function f, string qualifiedName, int nparam
not f.isStatic()
}
/**
* Holds if the set of viable implementations that can be called by `call`
* might be improved by knowing the call context.
*/
predicate mayBenefitFromCallContext(DataFlowCall call, Function f) { none() }
/**
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference.
*/
Function viableImplInCallContext(DataFlowCall call, DataFlowCall ctx) { none() }
/** A parameter position represented by an integer. */
class ParameterPosition extends int {
ParameterPosition() { any(ParameterNode p).isParameterOf(_, this) }

View File

@@ -244,15 +244,9 @@ class ConditionDeclExpr extends Expr, @condition_decl {
/**
* Gets the compiler-generated variable access that conceptually occurs after
* the initialization of the declared variable, if any.
* the initialization of the declared variable.
*/
VariableAccess getVariableAccess() { result = this.getExpr() }
/**
* Gets the expression that is evaluated after the initialization of the declared
* variable.
*/
Expr getExpr() { result = this.getChild(0) }
VariableAccess getVariableAccess() { result = this.getChild(0) }
/**
* Gets the expression that initializes the declared variable. This predicate

View File

@@ -58,19 +58,6 @@ class Expr extends StmtParent, @expr {
/** Gets the parent of this expression, if any. */
Element getParent() { exprparents(underlyingElement(this), _, unresolveElement(result)) }
/**
* Gets the `n`th compiler-generated destructor call that is performed after this expression, in
* order of destruction.
*/
DestructorCall getImplicitDestructorCall(int n) {
synthetic_destructor_call(this, max(int i | synthetic_destructor_call(this, i, _)) - n, result)
}
/**
* Gets a compiler-generated destructor call that is performed after this expression.
*/
DestructorCall getAnImplicitDestructorCall() { synthetic_destructor_call(this, _, result) }
/** Gets the location of this expression. */
override Location getLocation() {
result = this.getExprLocationOverride()

View File

@@ -1,160 +0,0 @@
/**
* This library offers a view of preprocessor branches (`#if`, `#ifdef`,
* `#ifndef`, `#elif` and `#else`) as blocks of code between the opening and
* closing directives, with navigable parent-child relationships to other
* blocks. The main class is `PreprocessorBlock`.
*/
import cpp
/**
* Gets the line of the `ix`th `PreprocessorBranchDirective` in file `f`.
*/
private int getPreprocLineFromIndex(File f, int ix) {
result =
rank[ix](PreprocessorBranchDirective g | g.getFile() = f | g.getLocation().getStartLine())
}
/**
* Gets the `ix`th `PreprocessorBranchDirective` in file `f`.
*/
private PreprocessorBranchDirective getPreprocFromIndex(File f, int ix) {
result.getFile() = f and
result.getLocation().getStartLine() = getPreprocLineFromIndex(f, ix)
}
/**
* Get the index of a `PreprocessorBranchDirective` in its `file`.
*/
private int getPreprocIndex(PreprocessorBranchDirective directive) {
directive = getPreprocFromIndex(directive.getFile(), result)
}
/**
* A chunk of code from one preprocessor branch (`#if`, `#ifdef`,
* `#ifndef`, `#elif` or `#else`) to the directive that closes it
* (`#elif`, `#else` or `#endif`). The `getParent()` method
* allows these blocks to be navigated as a tree, with the root
* being the entire file.
*/
class PreprocessorBlock extends @element {
PreprocessorBlock() {
mkElement(this) instanceof File or
mkElement(this) instanceof PreprocessorBranch or
mkElement(this) instanceof PreprocessorElse
}
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
filepath = this.getFile().toString() and
startline = this.getStartLine() and
startcolumn = 0 and
endline = this.getEndLine() and
endcolumn = 0
}
/**
* Gets a textual representation of this element.
*/
string toString() { result = mkElement(this).toString() }
/**
* Gets the file this `PreprocessorBlock` is located in.
*/
File getFile() { result = mkElement(this).getFile() }
/**
* Gets the start line number of this `PreprocessorBlock`.
*/
int getStartLine() { result = mkElement(this).getLocation().getStartLine() }
/**
* Gets the end line number of this `PreprocessorBlock`.
*/
int getEndLine() {
result = mkElement(this).(File).getMetrics().getNumberOfLines() or
result =
mkElement(this).(PreprocessorBranchDirective).getNext().getLocation().getStartLine() - 1
}
private PreprocessorBlock getParentInternal() {
// find the `#ifdef` corresponding to this block and the
// PreprocessorBranchDirective `prev` that came directly
// before it in the source.
exists(int ix, PreprocessorBranchDirective prev |
ix = getPreprocIndex(mkElement(this).(PreprocessorBranchDirective).getIf()) and
prev = getPreprocFromIndex(this.getFile(), ix - 1)
|
if prev instanceof PreprocessorEndif
then
// if we follow an #endif, we have the same parent
// as its corresponding `#if` has.
result = unresolveElement(prev.getIf()).(PreprocessorBlock).getParentInternal()
else
// otherwise we directly follow an #if / #ifdef / #ifndef /
// #elif / #else that must be a level above and our parent
// block.
mkElement(result) = prev
)
}
/**
* Gets the `PreprocessorBlock` that's directly surrounding this one.
* Has no result if this is a file.
*/
PreprocessorBlock getParent() {
not mkElement(this) instanceof File and
(
if exists(this.getParentInternal())
then
// found parent directive
result = this.getParentInternal()
else
// top level directive
mkElement(result) = this.getFile()
)
}
/**
* Gets a `PreprocessorBlock` that's directly inside this one.
*/
PreprocessorBlock getAChild() { result.getParent() = this }
private Include getAnEnclosedInclude() {
result.getFile() = this.getFile() and
result.getLocation().getStartLine() > this.getStartLine() and
result.getLocation().getStartLine() <= this.getEndLine()
}
/**
* Gets an include directive that is directly in this
* `PreprocessorBlock`.
*/
Include getAnInclude() {
result = this.getAnEnclosedInclude() and
not result = this.getAChild().getAnEnclosedInclude()
}
private Macro getAnEnclosedMacro() {
result.getFile() = this.getFile() and
result.getLocation().getStartLine() > this.getStartLine() and
result.getLocation().getStartLine() <= this.getEndLine()
}
/**
* Gets a macro definition that is directly in this
* `PreprocessorBlock`.
*/
Macro getAMacro() {
result = this.getAnEnclosedMacro() and
not result = this.getAChild().getAnEnclosedMacro()
}
}

View File

@@ -3,7 +3,7 @@ import semmle.code.cpp.Type
/** For upgraded databases without mangled name info. */
pragma[noinline]
private string getTopLevelClassName(@usertype c) {
not mangled_name(_, _, _) and
not mangled_name(_, _) and
isClass(c) and
usertypes(c, result, _) and
not namespacembrs(_, c) and // not in a namespace
@@ -17,7 +17,7 @@ private string getTopLevelClassName(@usertype c) {
*/
pragma[noinline]
private predicate existsCompleteWithName(string name, @usertype d) {
not mangled_name(_, _, _) and
not mangled_name(_, _) and
is_complete(d) and
name = getTopLevelClassName(d) and
onlyOneCompleteClassExistsWithName(name)
@@ -26,7 +26,7 @@ private predicate existsCompleteWithName(string name, @usertype d) {
/** For upgraded databases without mangled name info. */
pragma[noinline]
private predicate onlyOneCompleteClassExistsWithName(string name) {
not mangled_name(_, _, _) and
not mangled_name(_, _) and
strictcount(@usertype c | is_complete(c) and getTopLevelClassName(c) = name) = 1
}
@@ -36,7 +36,7 @@ private predicate onlyOneCompleteClassExistsWithName(string name) {
*/
pragma[noinline]
private predicate existsIncompleteWithName(string name, @usertype c) {
not mangled_name(_, _, _) and
not mangled_name(_, _) and
not is_complete(c) and
name = getTopLevelClassName(c)
}
@@ -47,7 +47,7 @@ private predicate existsIncompleteWithName(string name, @usertype c) {
* with the same name.
*/
private predicate oldHasCompleteTwin(@usertype c, @usertype d) {
not mangled_name(_, _, _) and
not mangled_name(_, _) and
exists(string name |
existsIncompleteWithName(name, c) and
existsCompleteWithName(name, d)
@@ -57,7 +57,7 @@ private predicate oldHasCompleteTwin(@usertype c, @usertype d) {
pragma[noinline]
private @mangledname getClassMangledName(@usertype c) {
isClass(c) and
mangled_name(c, result, _)
mangled_name(c, result)
}
/** Holds if `d` is a unique complete class named `name`. */

View File

@@ -1,57 +0,0 @@
private predicate hasDefinition(@function f) {
exists(@fun_decl fd | fun_decls(fd, f, _, _, _) | fun_def(fd))
}
private predicate onlyOneCompleteFunctionExistsWithMangledName(@mangledname name) {
strictcount(@function f | hasDefinition(f) and mangled_name(f, name, true)) = 1
}
/** Holds if `f` is a unique function with a definition named `name`. */
private predicate isFunctionWithMangledNameAndWithDefinition(@mangledname name, @function f) {
hasDefinition(f) and
mangled_name(f, name, true) and
onlyOneCompleteFunctionExistsWithMangledName(name)
}
/** Holds if `f` is a function without a definition named `name`. */
private predicate isFunctionWithMangledNameAndWithoutDefinition(@mangledname name, @function f) {
not hasDefinition(f) and
mangled_name(f, name, true)
}
/**
* Holds if `incomplete` is a function without a definition, and there exists
* a unique function `complete` with the same name that does have a definition.
*/
private predicate hasTwinWithDefinition(@function incomplete, @function complete) {
not function_instantiation(incomplete, complete) and
(
not compgenerated(incomplete) or
not compgenerated(complete)
) and
exists(@mangledname name |
isFunctionWithMangledNameAndWithoutDefinition(name, incomplete) and
isFunctionWithMangledNameAndWithDefinition(name, complete)
)
}
import Cached
cached
private module Cached {
/**
* If `f` is a function without a definition, and there exists a unique
* function with the same name that does have a definition, then the
* result is that unique function. Otherwise, the result is `f`.
*/
cached
@function resolveFunction(@function f) {
hasTwinWithDefinition(f, result)
or
not hasTwinWithDefinition(f, _) and
result = f
}
cached
predicate isFunction(@function f) { f = resolveFunction(_) }
}

View File

@@ -3,20 +3,20 @@ private predicate hasDefinition(@globalvariable g) {
}
private predicate onlyOneCompleteGlobalVariableExistsWithMangledName(@mangledname name) {
strictcount(@globalvariable g | hasDefinition(g) and mangled_name(g, name, _)) = 1
strictcount(@globalvariable g | hasDefinition(g) and mangled_name(g, name)) = 1
}
/** Holds if `g` is a unique global variable with a definition named `name`. */
private predicate isGlobalWithMangledNameAndWithDefinition(@mangledname name, @globalvariable g) {
hasDefinition(g) and
mangled_name(g, name, _) and
mangled_name(g, name) and
onlyOneCompleteGlobalVariableExistsWithMangledName(name)
}
/** Holds if `g` is a global variable without a definition named `name`. */
private predicate isGlobalWithMangledNameAndWithoutDefinition(@mangledname name, @globalvariable g) {
not hasDefinition(g) and
mangled_name(g, name, _)
mangled_name(g, name)
}
/**

View File

@@ -249,7 +249,9 @@ private predicate functionSignature(Function f, string qualifiedName, int nparam
* Holds if the set of viable implementations that can be called by `call`
* might be improved by knowing the call context.
*/
predicate mayBenefitFromCallContext(DataFlowCall call) { mayBenefitFromCallContext(call, _, _) }
predicate mayBenefitFromCallContext(DataFlowCall call, DataFlowCallable f) {
mayBenefitFromCallContext(call, f, _)
}
/**
* Holds if `call` is a call through a function pointer, and the pointer

View File

@@ -22,8 +22,4 @@ module CppDataFlow implements InputSig {
predicate getAdditionalFlowIntoCallNodeTerm = Private::getAdditionalFlowIntoCallNodeTerm/2;
predicate validParameterAliasStep = Private::validParameterAliasStep/2;
predicate mayBenefitFromCallContext = Private::mayBenefitFromCallContext/1;
predicate viableImplInCallContext = Private::viableImplInCallContext/2;
}

View File

@@ -7,9 +7,6 @@ private import SsaInternals as Ssa
private import DataFlowImplCommon as DataFlowImplCommon
private import codeql.util.Unit
private import Node0ToString
private import ModelUtil
private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs as IO
private import semmle.code.cpp.models.interfaces.DataFlow as DF
cached
private module Cached {
@@ -1181,19 +1178,6 @@ private int countNumberOfBranchesUsingParameter(SwitchInstruction switch, Parame
)
}
pragma[nomagic]
private predicate isInputOutput(
DF::DataFlowFunction target, Node node1, Node node2, IO::FunctionInput input,
IO::FunctionOutput output
) {
exists(CallInstruction call |
node1 = callInput(call, input) and
node2 = callOutput(call, output) and
call.getStaticCallTarget() = target and
target.hasDataFlow(input, output)
)
}
/**
* Holds if the data-flow step from `node1` to `node2` can be used to
* determine where side-effects may return from a callable.
@@ -1205,11 +1189,6 @@ private predicate isInputOutput(
* int x = *p;
* ```
* does not preserve the identity of `*p`.
*
* Similarly, a function that copies the contents of a string into a new location
* does not also preserve the identity. For example, `strdup(p)` does not
* preserve the identity of `*p` (since it allocates new storage and copies
* the string into the new storage).
*/
bindingset[node1, node2]
pragma[inline_late]
@@ -1246,16 +1225,7 @@ predicate validParameterAliasStep(Node node1, Node node2) {
not exists(Operand operand |
node1.asOperand() = operand and
node2.asInstruction().(StoreInstruction).getSourceValueOperand() = operand
) and
(
// Either this is not a modeled flow.
not isInputOutput(_, node1, node2, _, _)
or
exists(DF::DataFlowFunction target, IO::FunctionInput input, IO::FunctionOutput output |
// Or it is a modeled flow and there's `*input` to `*output` flow
isInputOutput(target, node1, node2, input.getIndirectionInput(), output.getIndirectionOutput()) and
// and in that case there should also be `input` to `output` flow
target.hasDataFlow(input, output)
)
)
// TODO: Also block flow through models that don't preserve identity such
// as `strdup`.
}

View File

@@ -55,12 +55,29 @@ private newtype TIRDataFlowNode =
TFinalParameterNode(Parameter p, int indirectionIndex) {
exists(Ssa::FinalParameterUse use |
use.getParameter() = p and
use.getIndirectionIndex() = indirectionIndex
use.getIndirectionIndex() = indirectionIndex and
parameterIsRedefined(p)
)
} 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`.
*/
@@ -692,7 +709,7 @@ class FinalGlobalValue extends Node, TFinalGlobalValue {
override DataFlowType getType() {
exists(int indirectionIndex |
indirectionIndex = globalUse.getIndirectionIndex() and
result = getTypeImpl(globalUse.getUnderlyingType(), indirectionIndex - 1)
result = getTypeImpl(globalUse.getUnspecifiedType(), indirectionIndex - 1)
)
}
@@ -723,7 +740,7 @@ class InitialGlobalValue extends Node, TInitialGlobalValue {
override DataFlowType getType() {
exists(DataFlowType type |
type = globalDef.getUnderlyingType() and
type = globalDef.getUnspecifiedType() and
if this.isGLValue()
then result = type
else result = getTypeImpl(type, globalDef.getIndirectionIndex() - 1)
@@ -926,13 +943,10 @@ 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`.
// 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.
// 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`.
stripped.getUnspecifiedType() != t.getUnspecifiedType() and
result = getTypeImpl0(stripped, indirectionIndex - 1)
)
@@ -982,14 +996,12 @@ 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.getUnderlyingType(), indirectionIndex - sub)
result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub)
)
}
@@ -1026,14 +1038,12 @@ 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.getUnderlyingType(), indirectionIndex - sub)
result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub)
)
}
@@ -1126,7 +1136,7 @@ class FinalParameterNode extends Node, TFinalParameterNode {
override Declaration getEnclosingCallable() { result = this.getFunction() }
override DataFlowType getType() { result = getTypeImpl(p.getUnderlyingType(), indirectionIndex) }
override DataFlowType getType() { result = getTypeImpl(p.getUnspecifiedType(), indirectionIndex) }
final override Location getLocationImpl() {
// Parameters can have multiple locations. When there's a unique location we use
@@ -1384,24 +1394,11 @@ abstract private class ExprNodeBase extends Node {
final Expr getExpr(int n) { result = this.getConvertedExpr(n).getUnconverted() }
}
/**
* Holds if there exists a dataflow node whose `asExpr(n)` should evaluate
* to `e`.
*/
private predicate exprNodeShouldBe(Expr e, int n) {
exprNodeShouldBeInstruction(_, e, n) or
exprNodeShouldBeOperand(_, e, n) or
exprNodeShouldBeIndirectOutNode(_, e, n)
}
private class InstructionExprNode extends ExprNodeBase, InstructionNode {
InstructionExprNode() {
exists(Expr e, int n |
exprNodeShouldBeInstruction(this, e, n) and
not exists(Expr conv |
exprNodeShouldBe(conv, n + 1) and
conv.getUnconverted() = e.getUnconverted()
)
not exprNodeShouldBeInstruction(_, e, n + 1)
)
}
@@ -1412,10 +1409,7 @@ private class OperandExprNode extends ExprNodeBase, OperandNode {
OperandExprNode() {
exists(Expr e, int n |
exprNodeShouldBeOperand(this, e, n) and
not exists(Expr conv |
exprNodeShouldBe(conv, n + 1) and
conv.getUnconverted() = e.getUnconverted()
)
not exprNodeShouldBeOperand(_, e, n + 1)
)
}
@@ -1480,17 +1474,12 @@ private module IndirectNodeToIndirectExpr<IndirectNodeToIndirectExprSig Sig> {
indirectNodeHasIndirectExpr(node, e, n, indirectionIndex) and
not exists(Expr conv, int adjustedIndirectionIndex |
adjustForReference(e, indirectionIndex, conv, adjustedIndirectionIndex) and
indirectExprNodeShouldBe(conv, n + 1, adjustedIndirectionIndex)
indirectNodeHasIndirectExpr(_, conv, n + 1, adjustedIndirectionIndex)
)
)
}
}
private predicate indirectExprNodeShouldBe(Expr e, int n, int indirectionIndex) {
indirectExprNodeShouldBeIndirectOperand(_, e, n, indirectionIndex) or
indirectExprNodeShouldBeIndirectInstruction(_, e, n, indirectionIndex)
}
private module IndirectOperandIndirectExprNodeImpl implements IndirectNodeToIndirectExprSig {
class IndirectNode = IndirectOperand;
@@ -1779,7 +1768,7 @@ class VariableNode extends Node, TVariableNode {
}
override DataFlowType getType() {
result = getTypeImpl(v.getUnderlyingType(), indirectionIndex - 1)
result = getTypeImpl(v.getUnspecifiedType(), indirectionIndex - 1)
}
final override Location getLocationImpl() {

View File

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

View File

@@ -4,11 +4,7 @@ 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
@@ -142,26 +138,22 @@ private newtype TDefOrUseImpl =
isIteratorUse(container, iteratorAddress, _, indirectionIndex)
} or
TFinalParameterUse(Parameter p, int 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()
// 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)
)
}
private predicate isGlobalUse(
GlobalLikeVariable v, IRFunction f, int indirection, int indirectionIndex
) {
// Generate a "global use" at the end of the function body if there's a
// direct definition somewhere in the body of the function
indirection =
min(int cand, VariableAddressInstruction vai |
vai.getEnclosingIRFunction() = f and
vai.getAstVariable() = v and
isDef(_, _, _, vai, cand, indirectionIndex)
|
cand
)
exists(VariableAddressInstruction vai |
vai.getEnclosingIRFunction() = f and
vai.getAstVariable() = v and
isDef(_, _, _, vai, indirection, indirectionIndex)
)
}
private predicate isGlobalDefImpl(
@@ -175,13 +167,11 @@ private predicate isGlobalDefImpl(
)
}
private predicate underlyingTypeIsModifiableAt(Type underlying, int indirectionIndex) {
indirectionIndex =
[1 .. getIndirectionForUnspecifiedType(underlying.getUnspecifiedType())
.getNumberOfIndirections()] and
private predicate unspecifiedTypeIsModifiableAt(Type unspecified, int indirectionIndex) {
indirectionIndex = [1 .. getIndirectionForUnspecifiedType(unspecified).getNumberOfIndirections()] and
exists(CppType cppType |
cppType.hasUnderlyingType(underlying, false) and
isModifiableAt(cppType, indirectionIndex)
cppType.hasUnspecifiedType(unspecified, _) and
isModifiableAt(cppType, indirectionIndex + 1)
)
}
@@ -457,57 +447,6 @@ class FinalParameterUse extends UseImpl, TFinalParameterUse {
}
}
/**
* A use that models a synthetic "last use" of a global variable just before a
* function returns.
*
* We model global variable flow by:
* - Inserting a last use of any global variable that's modified by a function
* - Flowing from the last use to the `VariableNode` that represents the global
* variable.
* - Flowing from the `VariableNode` to an "initial def" of the global variable
* in any function that may read the global variable.
* - Flowing from the initial definition to any subsequent uses of the global
* variable in the function body.
*
* For example, consider the following pair of functions:
* ```cpp
* int global;
* int source();
* void sink(int);
*
* void set_global() {
* global = source();
* }
*
* void read_global() {
* sink(global);
* }
* ```
* we insert global uses and defs so that (from the point-of-view of dataflow)
* the above scenario looks like:
* ```cpp
* int global; // (1)
* int source();
* void sink(int);
*
* void set_global() {
* global = source();
* __global_use(global); // (2)
* }
*
* void read_global() {
* global = __global_def; // (3)
* sink(global); // (4)
* }
* ```
* and flow from `source()` to the argument of `sink` is then modeled as
* follows:
* 1. Flow from `source()` to `(2)` (via SSA).
* 2. Flow from `(2)` to `(1)` (via a `jumpStep`).
* 3. Flow from `(1)` to `(3)` (via a `jumpStep`).
* 4. Flow from `(3)` to `(4)` (via SSA).
*/
class GlobalUse extends UseImpl, TGlobalUse {
GlobalLikeVariable global;
IRFunction f;
@@ -550,22 +489,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() }
}
/**
* A definition that models a synthetic "initial definition" of a global
* variable just after the function entry point.
*
* See the QLDoc for `GlobalUse` for how this is used.
*/
class GlobalDefImpl extends DefOrUseImpl, TGlobalDefImpl {
GlobalLikeVariable global;
IRFunction f;
@@ -598,16 +526,11 @@ class GlobalDefImpl extends DefOrUseImpl, TGlobalDefImpl {
int getIndirection() { result = indirectionIndex }
/**
* Gets the type of this definition after specifiers have been deeply
* stripped and typedefs have been resolved.
* Gets the type of this use 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() }
@@ -624,10 +547,7 @@ class GlobalDefImpl extends DefOrUseImpl, TGlobalDefImpl {
*/
predicate adjacentDefRead(DefOrUse defOrUse1, UseOrPhi use) {
exists(IRBlock bb1, int i1, SourceVariable v |
defOrUse1
.asDefOrUse()
.hasIndexInBlock(pragma[only_bind_out](bb1), pragma[only_bind_out](i1),
pragma[only_bind_out](v))
defOrUse1.asDefOrUse().hasIndexInBlock(bb1, i1, v)
|
exists(IRBlock bb2, int i2, DefinitionExt def |
adjacentDefReadExt(pragma[only_bind_into](def), pragma[only_bind_into](bb1),
@@ -649,11 +569,7 @@ predicate adjacentDefRead(DefOrUse defOrUse1, UseOrPhi use) {
* flows to `useOrPhi`.
*/
private predicate globalDefToUse(GlobalDef globalDef, UseOrPhi useOrPhi) {
exists(IRBlock bb1, int i1, SourceVariable v |
globalDef
.hasIndexInBlock(pragma[only_bind_out](bb1), pragma[only_bind_out](i1),
pragma[only_bind_out](v))
|
exists(IRBlock bb1, int i1, SourceVariable v | globalDef.hasIndexInBlock(bb1, i1, v) |
exists(IRBlock bb2, int i2 |
adjacentDefReadExt(_, pragma[only_bind_into](bb1), pragma[only_bind_into](i1),
pragma[only_bind_into](bb2), pragma[only_bind_into](i2)) and
@@ -799,58 +715,10 @@ 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
not modeledFlowBarrier(nFrom) and
nodeFrom != nodeTo
ssaFlowImpl(defOrUse, nFrom, nodeTo, uncertain) and nodeFrom != nodeTo
|
if uncertain = true then nodeFrom = [nFrom, getAPriorDefinition(defOrUse)] else nodeFrom = nFrom
)
@@ -1155,11 +1023,6 @@ 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() }

View File

@@ -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, false) and
cppType.hasUnderlyingType(pointerType, _) and
base = getTypeImpl(pointerType, indirectionIndex)
|
// The value cannot be modified if it has a const specifier,

View File

@@ -2125,6 +2125,13 @@ 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

View File

@@ -233,6 +233,20 @@ 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)`.
@@ -1054,3 +1068,6 @@ module Ssa {
predicate hasUnreachedInstruction = Cached::hasUnreachedInstructionCached/1;
}
/** DEPRECATED: Alias for Ssa */
deprecated module SSA = Ssa;

View File

@@ -3,6 +3,13 @@ import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.reachability.Rea
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.reachability.Dominance as Dominance
import semmle.code.cpp.ir.implementation.aliased_ssa.IR as NewIR
import semmle.code.cpp.ir.implementation.internal.TInstruction::AliasedSsaInstructions as SsaInstructions
/** DEPRECATED: Alias for SsaInstructions */
deprecated module SSAInstructions = SsaInstructions;
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
import AliasedSSA as Alias
import semmle.code.cpp.ir.implementation.internal.TOperand::AliasedSsaOperands as SsaOperands
/** DEPRECATED: Alias for SsaOperands */
deprecated module SSAOperands = SsaOperands;

View File

@@ -2,3 +2,6 @@ import semmle.code.cpp.ir.internal.IRCppLanguage as Language
import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as IRConstruction
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConstruction as UnaliasedSsa
import semmle.code.cpp.ir.implementation.aliased_ssa.internal.SSAConstruction as AliasedSsa
/** DEPRECATED: Alias for AliasedSsa */
deprecated module AliasedSSA = AliasedSsa;

View File

@@ -2125,6 +2125,13 @@ 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

View File

@@ -202,6 +202,12 @@ 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)`.
@@ -279,7 +285,7 @@ private predicate backEdgeCandidate(
// is a back edge. This includes edges from `continue` and the fall-through
// edge(s) after the last instruction(s) in the body.
exists(TranslatedWhileStmt s |
targetInstruction = s.getFirstConditionInstruction(_) and
targetInstruction = s.getFirstConditionInstruction() and
targetInstruction = sourceElement.getInstructionSuccessor(sourceTag, kind) and
requiredAncestor = s.getBody()
)
@@ -290,7 +296,7 @@ private predicate backEdgeCandidate(
// { ... } while (0)` statement. Note that all `continue` statements in a
// do-while loop produce forward edges.
exists(TranslatedDoStmt s |
targetInstruction = s.getBody().getFirstInstruction(_) and
targetInstruction = s.getBody().getFirstInstruction() and
targetInstruction = sourceElement.getInstructionSuccessor(sourceTag, kind) and
requiredAncestor = s.getCondition()
)
@@ -302,7 +308,7 @@ private predicate backEdgeCandidate(
// last instruction(s) in the body. A for loop may not have a condition, in
// which case `getFirstConditionInstruction` returns the body instead.
exists(TranslatedForStmt s |
targetInstruction = s.getFirstConditionInstruction(_) and
targetInstruction = s.getFirstConditionInstruction() and
targetInstruction = sourceElement.getInstructionSuccessor(sourceTag, kind) and
(
requiredAncestor = s.getUpdate()
@@ -316,7 +322,7 @@ private predicate backEdgeCandidate(
// Any edge from within the update of the loop to the condition of
// the loop is a back edge.
exists(TranslatedRangeBasedForStmt s |
targetInstruction = s.getCondition().getFirstInstruction(_) and
targetInstruction = s.getCondition().getFirstInstruction() and
targetInstruction = sourceElement.getInstructionSuccessor(sourceTag, kind) and
requiredAncestor = s.getUpdate()
)

View File

@@ -3,7 +3,6 @@ private import semmle.code.cpp.ir.implementation.Opcode
private import semmle.code.cpp.ir.implementation.internal.OperandTag
private import semmle.code.cpp.ir.internal.CppType
private import semmle.code.cpp.models.interfaces.SideEffect
private import semmle.code.cpp.models.interfaces.Throwing
private import InstructionTag
private import SideEffects
private import TranslatedElement
@@ -41,10 +40,10 @@ abstract class TranslatedCall extends TranslatedExpr {
id = this.getNumberOfArguments() and result = this.getSideEffects()
}
final override Instruction getFirstInstruction(EdgeKind kind) {
final override Instruction getFirstInstruction() {
if exists(this.getQualifier())
then result = this.getQualifier().getFirstInstruction(kind)
else result = this.getFirstCallTargetInstruction(kind)
then result = this.getQualifier().getFirstInstruction()
else result = this.getFirstCallTargetInstruction()
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
@@ -53,43 +52,34 @@ abstract class TranslatedCall extends TranslatedExpr {
resultType = getTypeForPRValue(this.getCallResultType())
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getQualifier() and
result = this.getFirstCallTargetInstruction(kind)
result = this.getFirstCallTargetInstruction()
or
child = this.getCallTarget() and
result = this.getFirstArgumentOrCallInstruction(kind)
result = this.getFirstArgumentOrCallInstruction()
or
exists(int argIndex |
child = this.getArgument(argIndex) and
if exists(this.getArgument(argIndex + 1))
then result = this.getArgument(argIndex + 1).getFirstInstruction(kind)
else (
result = this.getInstruction(CallTag()) and kind instanceof GotoEdge
)
then result = this.getArgument(argIndex + 1).getFirstInstruction()
else result = this.getInstruction(CallTag())
)
or
child = this.getSideEffects() and
if this.isNoReturn()
then
kind instanceof GotoEdge and
result =
any(UnreachedInstruction instr |
this.getEnclosingFunction().getFunction() = instr.getEnclosingFunction()
)
else (
not this.mustThrowException() and
result = this.getParent().getChildSuccessor(this, kind)
or
this.mayThrowException() and
kind instanceof ExceptionEdge and
result = this.getParent().getExceptionSuccessorInstruction(any(GotoEdge edge))
)
else result = this.getParent().getChildSuccessor(this)
}
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
kind instanceof GotoEdge and
tag = CallTag() and
result = this.getSideEffects().getFirstInstruction(kind)
result = this.getSideEffects().getFirstInstruction()
}
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
@@ -110,16 +100,6 @@ abstract class TranslatedCall extends TranslatedExpr {
final override Instruction getResult() { result = this.getInstruction(CallTag()) }
/**
* Holds if the evaluation of this call may throw an exception.
*/
abstract predicate mayThrowException();
/**
* Holds if the evaluation of this call always throws an exception.
*/
abstract predicate mustThrowException();
/**
* Gets the result type of the call.
*/
@@ -141,8 +121,8 @@ abstract class TranslatedCall extends TranslatedExpr {
* it can be overridden by a subclass for cases where there is a call target
* that is not computed from an expression (e.g. a direct call).
*/
Instruction getFirstCallTargetInstruction(EdgeKind kind) {
result = this.getCallTarget().getFirstInstruction(kind)
Instruction getFirstCallTargetInstruction() {
result = this.getCallTarget().getFirstInstruction()
}
/**
@@ -179,12 +159,10 @@ abstract class TranslatedCall extends TranslatedExpr {
* If there are any arguments, gets the first instruction of the first
* argument. Otherwise, returns the call instruction.
*/
final Instruction getFirstArgumentOrCallInstruction(EdgeKind kind) {
final Instruction getFirstArgumentOrCallInstruction() {
if this.hasArguments()
then result = this.getArgument(0).getFirstInstruction(kind)
else (
kind instanceof GotoEdge and result = this.getInstruction(CallTag())
)
then result = this.getArgument(0).getFirstInstruction()
else result = this.getInstruction(CallTag())
}
/**
@@ -225,12 +203,12 @@ abstract class TranslatedSideEffects extends TranslatedElement {
)
}
final override Instruction getChildSuccessor(TranslatedElement te, EdgeKind kind) {
final override Instruction getChildSuccessor(TranslatedElement te) {
exists(int i |
this.getChild(i) = te and
if exists(this.getChild(i + 1))
then result = this.getChild(i + 1).getFirstInstruction(kind)
else result = this.getParent().getChildSuccessor(this, kind)
then result = this.getChild(i + 1).getFirstInstruction()
else result = this.getParent().getChildSuccessor(this)
)
}
@@ -238,12 +216,11 @@ abstract class TranslatedSideEffects extends TranslatedElement {
none()
}
final override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getChild(0).getFirstInstruction(kind)
final override Instruction getFirstInstruction() {
result = this.getChild(0).getFirstInstruction()
or
// Some functions, like `std::move()`, have no side effects whatsoever.
not exists(this.getChild(0)) and
result = this.getParent().getChildSuccessor(this, kind)
not exists(this.getChild(0)) and result = this.getParent().getChildSuccessor(this)
}
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
@@ -258,9 +235,8 @@ abstract class TranslatedSideEffects extends TranslatedElement {
* (`TranslatedAllocatorCall`).
*/
abstract class TranslatedDirectCall extends TranslatedCall {
final override Instruction getFirstCallTargetInstruction(EdgeKind kind) {
result = this.getInstruction(CallTargetTag()) and
kind instanceof GotoEdge
final override Instruction getFirstCallTargetInstruction() {
result = this.getInstruction(CallTargetTag())
}
final override Instruction getCallTargetResult() { result = this.getInstruction(CallTargetTag()) }
@@ -277,7 +253,8 @@ abstract class TranslatedDirectCall extends TranslatedCall {
result = TranslatedCall.super.getInstructionSuccessor(tag, kind)
or
tag = CallTargetTag() and
result = this.getFirstArgumentOrCallInstruction(kind)
kind instanceof GotoEdge and
result = this.getFirstArgumentOrCallInstruction()
}
}
@@ -313,15 +290,6 @@ class TranslatedExprCall extends TranslatedCallExpr {
override TranslatedExpr getCallTarget() {
result = getTranslatedExpr(expr.getExpr().getFullyConverted())
}
final override predicate mayThrowException() {
// We assume that a call to a function pointer will not throw an exception.
// This is not sound in general, but this will greatly reduce the number of
// exceptional edges.
none()
}
final override predicate mustThrowException() { none() }
}
/**
@@ -343,14 +311,6 @@ class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall {
exists(this.getQualifier()) and
not exists(MemberFunction func | expr.getTarget() = func and func.isStatic())
}
final override predicate mayThrowException() {
expr.getTarget().(ThrowingFunction).mayThrowException(_)
}
final override predicate mustThrowException() {
expr.getTarget().(ThrowingFunction).mayThrowException(true)
}
}
/**
@@ -416,11 +376,10 @@ 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 getChildSuccessor(TranslatedElement child) { none() }
final override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getInstruction(OnlyInstructionTag()) and
kind instanceof GotoEdge
final override Instruction getFirstInstruction() {
result = this.getInstruction(OnlyInstructionTag())
}
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
@@ -429,8 +388,9 @@ abstract class TranslatedSideEffect extends TranslatedElement {
}
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
result = this.getParent().getChildSuccessor(this, kind) and
tag = OnlyInstructionTag()
result = this.getParent().getChildSuccessor(this) and
tag = OnlyInstructionTag() and
kind instanceof GotoEdge
}
final override Declaration getFunction() { result = this.getParent().getFunction() }

View File

@@ -7,17 +7,9 @@ private import TranslatedElement
private import TranslatedExpr
abstract class ConditionContext extends TranslatedElement {
/**
* Gets the instruction to be executed when `child` evaluates to `true`. The
* successor edge kind is specified by `kind`.
*/
abstract Instruction getChildTrueSuccessor(TranslatedCondition child, EdgeKind kind);
abstract Instruction getChildTrueSuccessor(TranslatedCondition child);
/**
* Gets the instruction to be executed when `child` evaluates to `false`. The
* successor edge kind is specified by `kind`.
*/
abstract Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind);
abstract Instruction getChildFalseSuccessor(TranslatedCondition child);
}
TranslatedCondition getTranslatedCondition(Expr expr) { result.getExpr() = expr }
@@ -52,8 +44,8 @@ abstract class TranslatedFlexibleCondition extends TranslatedCondition, Conditio
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 getFirstInstruction() {
result = this.getOperand().getFirstInstruction()
}
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
@@ -62,7 +54,7 @@ abstract class TranslatedFlexibleCondition extends TranslatedCondition, Conditio
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
final override Instruction getChildSuccessor(TranslatedElement child) { none() }
abstract TranslatedCondition getOperand();
}
@@ -70,14 +62,14 @@ abstract class TranslatedFlexibleCondition extends TranslatedCondition, Conditio
class TranslatedParenthesisCondition extends TranslatedFlexibleCondition {
override ParenthesisExpr expr;
final override Instruction getChildTrueSuccessor(TranslatedCondition child, EdgeKind kind) {
final override Instruction getChildTrueSuccessor(TranslatedCondition child) {
child = this.getOperand() and
result = this.getConditionContext().getChildTrueSuccessor(this, kind)
result = this.getConditionContext().getChildTrueSuccessor(this)
}
final override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
final override Instruction getChildFalseSuccessor(TranslatedCondition child) {
child = this.getOperand() and
result = this.getConditionContext().getChildFalseSuccessor(this, kind)
result = this.getConditionContext().getChildFalseSuccessor(this)
}
final override TranslatedCondition getOperand() {
@@ -88,7 +80,7 @@ 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 getChildSuccessor(TranslatedElement child) { none() }
}
abstract class TranslatedBinaryLogicalOperation extends TranslatedNativeCondition, ConditionContext {
@@ -100,8 +92,8 @@ abstract class TranslatedBinaryLogicalOperation extends TranslatedNativeConditio
id = 1 and result = this.getRightOperand()
}
final override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getLeftOperand().getFirstInstruction(kind)
final override Instruction getFirstInstruction() {
result = this.getLeftOperand().getFirstInstruction()
}
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
@@ -122,34 +114,34 @@ abstract class TranslatedBinaryLogicalOperation extends TranslatedNativeConditio
class TranslatedLogicalAndExpr extends TranslatedBinaryLogicalOperation {
TranslatedLogicalAndExpr() { expr instanceof LogicalAndExpr }
override Instruction getChildTrueSuccessor(TranslatedCondition child, EdgeKind kind) {
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
child = this.getLeftOperand() and
result = this.getRightOperand().getFirstInstruction(kind)
result = this.getRightOperand().getFirstInstruction()
or
child = this.getRightOperand() and
result = this.getConditionContext().getChildTrueSuccessor(this, kind)
result = this.getConditionContext().getChildTrueSuccessor(this)
}
override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
(child = this.getLeftOperand() or child = this.getRightOperand()) and
result = this.getConditionContext().getChildFalseSuccessor(this, kind)
result = this.getConditionContext().getChildFalseSuccessor(this)
}
}
class TranslatedLogicalOrExpr extends TranslatedBinaryLogicalOperation {
override LogicalOrExpr expr;
override Instruction getChildTrueSuccessor(TranslatedCondition child, EdgeKind kind) {
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
(child = this.getLeftOperand() or child = this.getRightOperand()) and
result = this.getConditionContext().getChildTrueSuccessor(this, kind)
result = this.getConditionContext().getChildTrueSuccessor(this)
}
override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
child = this.getLeftOperand() and
result = this.getRightOperand().getFirstInstruction(kind)
result = this.getRightOperand().getFirstInstruction()
or
child = this.getRightOperand() and
result = this.getConditionContext().getChildFalseSuccessor(this, kind)
result = this.getConditionContext().getChildFalseSuccessor(this)
}
}
@@ -158,9 +150,7 @@ class TranslatedValueCondition extends TranslatedCondition, TTranslatedValueCond
override TranslatedElement getChild(int id) { id = 0 and result = this.getValueExpr() }
override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getValueExpr().getFirstInstruction(kind)
}
override Instruction getFirstInstruction() { result = this.getValueExpr().getFirstInstruction() }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
tag = ValueConditionConditionalBranchTag() and
@@ -168,20 +158,19 @@ class TranslatedValueCondition extends TranslatedCondition, TTranslatedValueCond
resultType = getVoidType()
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getValueExpr() and
result = this.getInstruction(ValueConditionConditionalBranchTag()) and
kind instanceof GotoEdge
result = this.getInstruction(ValueConditionConditionalBranchTag())
}
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = ValueConditionConditionalBranchTag() and
(
kind instanceof TrueEdge and
result = this.getConditionContext().getChildTrueSuccessor(this, any(GotoEdge edge))
result = this.getConditionContext().getChildTrueSuccessor(this)
or
kind instanceof FalseEdge and
result = this.getConditionContext().getChildFalseSuccessor(this, any(GotoEdge edge))
result = this.getConditionContext().getChildFalseSuccessor(this)
)
}

View File

@@ -67,8 +67,8 @@ abstract class TranslatedLocalVariableDeclaration extends TranslatedVariableInit
getTranslatedInitialization(this.getVariable().getInitializer().getExpr().getFullyConverted())
}
final override Instruction getInitializationSuccessor(EdgeKind kind) {
result = this.getParent().getChildSuccessor(this, kind)
final override Instruction getInitializationSuccessor() {
result = this.getParent().getChildSuccessor(this)
}
final override IRVariable getIRVariable() {
@@ -147,9 +147,8 @@ class TranslatedStaticLocalVariableDeclarationEntry extends TranslatedDeclaratio
type = getBoolType()
}
final override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getInstruction(DynamicInitializationFlagAddressTag()) and
kind instanceof GotoEdge
final override Instruction getFirstInstruction() {
result = this.getInstruction(DynamicInitializationFlagAddressTag())
}
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
@@ -164,10 +163,10 @@ class TranslatedStaticLocalVariableDeclarationEntry extends TranslatedDeclaratio
tag = DynamicInitializationConditionalBranchTag() and
(
kind instanceof TrueEdge and
result = this.getParent().getChildSuccessor(this, any(GotoEdge edge))
result = this.getParent().getChildSuccessor(this)
or
kind instanceof FalseEdge and
result = this.getInitialization().getFirstInstruction(any(GotoEdge edge))
result = this.getInitialization().getFirstInstruction()
)
or
tag = DynamicInitializationFlagConstantTag() and
@@ -175,13 +174,13 @@ class TranslatedStaticLocalVariableDeclarationEntry extends TranslatedDeclaratio
result = this.getInstruction(DynamicInitializationFlagStoreTag())
or
tag = DynamicInitializationFlagStoreTag() and
result = this.getParent().getChildSuccessor(this, kind)
kind instanceof GotoEdge and
result = this.getParent().getChildSuccessor(this)
}
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
final override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getInitialization() and
result = this.getInstruction(DynamicInitializationFlagConstantTag()) and
kind instanceof GotoEdge
result = this.getInstruction(DynamicInitializationFlagConstantTag())
}
final override IRDynamicInitializationFlag getInstructionVariable(InstructionTag tag) {

View File

@@ -209,8 +209,6 @@ 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.
@@ -476,6 +474,7 @@ 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`.
@@ -828,10 +827,9 @@ abstract class TranslatedElement extends TTranslatedElement {
Location getLocation() { result = this.getAst().getLocation() }
/**
* Get the first instruction to be executed in the evaluation of this
* element when the edge kind is `kind`.
* Get the first instruction to be executed in the evaluation of this element.
*/
abstract Instruction getFirstInstruction(EdgeKind kind);
abstract Instruction getFirstInstruction();
/**
* Get the immediate child elements of this element.
@@ -906,19 +904,18 @@ abstract class TranslatedElement extends TTranslatedElement {
/**
* 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`.
* child element specified by `child` has finished execution.
*/
abstract Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind);
abstract Instruction getChildSuccessor(TranslatedElement child);
/**
* Gets the instruction to which control should flow if an exception is thrown
* within this element. This will generally return first `catch` block of the
* nearest enclosing `try`, or the `Unwind` instruction for the function if
* there is no enclosing `try`. The successor edge kind is specified by `kind`.
* there is no enclosing `try`.
*/
Instruction getExceptionSuccessorInstruction(EdgeKind kind) {
result = this.getParent().getExceptionSuccessorInstruction(kind)
Instruction getExceptionSuccessorInstruction() {
result = this.getParent().getExceptionSuccessorInstruction()
}
/**

View File

@@ -109,9 +109,8 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
result = getTranslatedEllipsisParameter(func)
}
final override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getInstruction(EnterFunctionTag()) and
kind instanceof GotoEdge
final override Instruction getFirstInstruction() {
result = this.getInstruction(EnterFunctionTag())
}
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
@@ -122,20 +121,17 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
or
tag = AliasedDefinitionTag() and
result = this.getInstruction(InitializeNonLocalTag())
)
or
(
tag = InitializeNonLocalTag() and
if exists(this.getThisType())
then result = this.getParameter(-1).getFirstInstruction(kind)
else
if exists(this.getParameter(0))
then result = this.getParameter(0).getFirstInstruction(kind)
else result = this.getBody().getFirstInstruction(kind)
)
or
kind instanceof GotoEdge and
(
or
(
tag = InitializeNonLocalTag() and
if exists(this.getThisType())
then result = this.getParameter(-1).getFirstInstruction()
else
if exists(this.getParameter(0))
then result = this.getParameter(0).getFirstInstruction()
else result = this.getBody().getFirstInstruction()
)
or
tag = ReturnValueAddressTag() and
result = this.getInstruction(ReturnTag())
or
@@ -150,25 +146,25 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
)
}
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
exists(int paramIndex | child = this.getParameter(paramIndex) |
final override Instruction getChildSuccessor(TranslatedElement child) {
exists(int paramIndex |
child = this.getParameter(paramIndex) and
if
exists(func.getParameter(paramIndex + 1)) or
getEllipsisParameterIndexForFunction(func) = paramIndex + 1
then result = this.getParameter(paramIndex + 1).getFirstInstruction(kind)
else result = this.getConstructorInitList().getFirstInstruction(kind)
then result = this.getParameter(paramIndex + 1).getFirstInstruction()
else result = this.getConstructorInitList().getFirstInstruction()
)
or
child = this.getConstructorInitList() and
result = this.getBody().getFirstInstruction(kind)
result = this.getBody().getFirstInstruction()
or
child = this.getBody() and
result = this.getReturnSuccessorInstruction(kind)
result = this.getReturnSuccessorInstruction()
or
child = this.getDestructorDestructionList() and
result = this.getReadEffects().getFirstInstruction(kind)
result = this.getReadEffects().getFirstInstruction()
or
kind instanceof GotoEdge and
child = this.getReadEffects() and
if this.hasReturnValue()
then result = this.getInstruction(ReturnValueAddressTag())
@@ -222,9 +218,8 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
)
}
final override Instruction getExceptionSuccessorInstruction(EdgeKind kind) {
result = this.getInstruction(UnwindTag()) and
kind instanceof GotoEdge
final override Instruction getExceptionSuccessorInstruction() {
result = this.getInstruction(UnwindTag())
}
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
@@ -273,8 +268,8 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
* Gets the instruction to which control should flow after a `return`
* statement.
*/
final Instruction getReturnSuccessorInstruction(EdgeKind kind) {
result = this.getDestructorDestructionList().getFirstInstruction(kind)
final Instruction getReturnSuccessorInstruction() {
result = this.getDestructorDestructionList().getFirstInstruction()
}
/**
@@ -374,30 +369,30 @@ TranslatedEllipsisParameter getTranslatedEllipsisParameter(Function func) {
abstract class TranslatedParameter extends TranslatedElement {
final override TranslatedElement getChild(int id) { none() }
final override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getInstruction(InitializerVariableAddressTag()) and
kind instanceof GotoEdge
final override Instruction getFirstInstruction() {
result = this.getInstruction(InitializerVariableAddressTag())
}
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
kind instanceof GotoEdge and
tag = InitializerVariableAddressTag() and
result = this.getInstruction(InitializerStoreTag())
or
tag = InitializerStoreTag() and
if this.hasIndirection()
then kind instanceof GotoEdge and result = this.getInstruction(InitializerIndirectAddressTag())
else result = this.getParent().getChildSuccessor(this, kind)
or
kind instanceof GotoEdge and
tag = InitializerIndirectAddressTag() and
result = this.getInstruction(InitializerIndirectStoreTag())
or
tag = InitializerIndirectStoreTag() and
result = this.getParent().getChildSuccessor(this, kind)
(
tag = InitializerVariableAddressTag() and
result = this.getInstruction(InitializerStoreTag())
or
tag = InitializerStoreTag() and
if this.hasIndirection()
then result = this.getInstruction(InitializerIndirectAddressTag())
else result = this.getParent().getChildSuccessor(this)
or
tag = InitializerIndirectAddressTag() and
result = this.getInstruction(InitializerIndirectStoreTag())
or
tag = InitializerIndirectStoreTag() and
result = this.getParent().getChildSuccessor(this)
)
}
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
final override Instruction getChildSuccessor(TranslatedElement child) { none() }
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
tag = InitializerVariableAddressTag() and
@@ -605,10 +600,10 @@ class TranslatedConstructorInitList extends TranslatedElement, InitializationCon
)
}
override Instruction getFirstInstruction(EdgeKind kind) {
override Instruction getFirstInstruction() {
if exists(this.getChild(0))
then result = this.getChild(0).getFirstInstruction(kind)
else result = this.getParent().getChildSuccessor(this, kind)
then result = this.getChild(0).getFirstInstruction()
else result = this.getParent().getChildSuccessor(this)
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
@@ -619,12 +614,12 @@ class TranslatedConstructorInitList extends TranslatedElement, InitializationCon
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
override Instruction getChildSuccessor(TranslatedElement child) {
exists(int id |
child = this.getChild(id) and
if exists(this.getChild(id + 1))
then result = this.getChild(id + 1).getFirstInstruction(kind)
else result = this.getParent().getChildSuccessor(this, kind)
then result = this.getChild(id + 1).getFirstInstruction()
else result = this.getParent().getChildSuccessor(this)
)
}
@@ -672,10 +667,10 @@ class TranslatedDestructorDestructionList extends TranslatedElement,
)
}
override Instruction getFirstInstruction(EdgeKind kind) {
override Instruction getFirstInstruction() {
if exists(this.getChild(0))
then result = this.getChild(0).getFirstInstruction(kind)
else result = this.getParent().getChildSuccessor(this, kind)
then result = this.getChild(0).getFirstInstruction()
else result = this.getParent().getChildSuccessor(this)
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
@@ -686,12 +681,12 @@ class TranslatedDestructorDestructionList extends TranslatedElement,
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
override Instruction getChildSuccessor(TranslatedElement child) {
exists(int id |
child = this.getChild(id) and
if exists(this.getChild(id + 1))
then result = this.getChild(id + 1).getFirstInstruction(kind)
else result = this.getParent().getChildSuccessor(this, kind)
then result = this.getChild(id + 1).getFirstInstruction()
else result = this.getParent().getChildSuccessor(this)
)
}
}
@@ -719,16 +714,16 @@ class TranslatedReadEffects extends TranslatedElement, TTranslatedReadEffects {
result = getTranslatedParameterReadEffect(func.getParameter(id))
}
override Instruction getFirstInstruction(EdgeKind kind) {
override Instruction getFirstInstruction() {
if exists(this.getAChild())
then
result =
min(TranslatedElement child, int id | child = this.getChild(id) | child order by id)
.getFirstInstruction(kind)
else result = this.getParent().getChildSuccessor(this, kind)
.getFirstInstruction()
else result = this.getParent().getChildSuccessor(this)
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
override Instruction getChildSuccessor(TranslatedElement child) {
exists(int id | child = this.getChild(id) |
if exists(TranslatedReadEffect child2, int id2 | id2 > id and child2 = this.getChild(id2))
then
@@ -737,8 +732,8 @@ class TranslatedReadEffects extends TranslatedElement, TTranslatedReadEffects {
child2 = this.getChild(id2) and id2 > id
|
child2 order by id2
).getFirstInstruction(kind)
else result = this.getParent().getChildSuccessor(this, kind)
).getFirstInstruction()
else result = this.getParent().getChildSuccessor(this)
)
}
@@ -760,17 +755,15 @@ 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 getChildSuccessor(TranslatedElement child) { none() }
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = OnlyInstructionTag() and
result = this.getParent().getChildSuccessor(this, kind)
kind = EdgeKind::gotoEdge() and
result = this.getParent().getChildSuccessor(this)
}
override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getInstruction(OnlyInstructionTag()) and
kind instanceof GotoEdge
}
override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
opcode instanceof Opcode::ReturnIndirection and

View File

@@ -22,10 +22,7 @@ class TranslatedStaticStorageDurationVarInit extends TranslatedRootElement,
final override Declaration getFunction() { result = var }
override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getInstruction(EnterFunctionTag()) and
kind instanceof GotoEdge
}
override Instruction getFirstInstruction() { result = this.getInstruction(EnterFunctionTag()) }
override TranslatedElement getChild(int n) {
n = 1 and
@@ -66,13 +63,10 @@ class TranslatedStaticStorageDurationVarInit extends TranslatedRootElement,
or
tag = AliasedDefinitionTag() and
result = this.getInstruction(InitializerVariableAddressTag())
)
or
tag = InitializerVariableAddressTag() and
result = this.getChild(1).getFirstInstruction(kind)
or
kind instanceof GotoEdge and
(
or
tag = InitializerVariableAddressTag() and
result = this.getChild(1).getFirstInstruction()
or
tag = ReturnTag() and
result = this.getInstruction(AliasedUseTag())
or
@@ -81,10 +75,9 @@ class TranslatedStaticStorageDurationVarInit extends TranslatedRootElement,
)
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getChild(1) and
result = this.getInstruction(ReturnTag()) and
kind instanceof GotoEdge
result = this.getInstruction(ReturnTag())
}
final override CppType getInstructionMemoryOperandType(

View File

@@ -37,9 +37,8 @@ abstract class InitializationContext extends TranslatedElement {
abstract class TranslatedVariableInitialization extends TranslatedElement, InitializationContext {
final override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() }
final override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getInstruction(InitializerVariableAddressTag()) and
kind instanceof GotoEdge
final override Instruction getFirstInstruction() {
result = this.getInstruction(InitializerVariableAddressTag())
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
@@ -56,24 +55,24 @@ abstract class TranslatedVariableInitialization extends TranslatedElement, Initi
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
(
tag = InitializerVariableAddressTag() and
kind instanceof GotoEdge and
if this.hasUninitializedInstruction()
then kind instanceof GotoEdge and result = this.getInstruction(InitializerStoreTag())
else result = this.getInitialization().getFirstInstruction(kind)
then result = this.getInstruction(InitializerStoreTag())
else result = this.getInitialization().getFirstInstruction()
)
or
this.hasUninitializedInstruction() and
kind instanceof GotoEdge and
tag = InitializerStoreTag() and
(
result = this.getInitialization().getFirstInstruction(kind)
result = this.getInitialization().getFirstInstruction()
or
not exists(this.getInitialization()) and
result = this.getInitializationSuccessor(kind)
not exists(this.getInitialization()) and result = this.getInitializationSuccessor()
)
}
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
child = this.getInitialization() and
result = this.getInitializationSuccessor(kind)
final override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getInitialization() and result = this.getInitializationSuccessor()
}
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
@@ -108,9 +107,8 @@ abstract class TranslatedVariableInitialization extends TranslatedElement, Initi
/**
* Gets the `Instruction` to be executed immediately after the initialization.
* The successor edge kind is specified by `kind`.
*/
abstract Instruction getInitializationSuccessor(EdgeKind kind);
abstract Instruction getInitializationSuccessor();
/**
* Holds if this initialization requires an `Uninitialized` instruction to be emitted before
@@ -170,19 +168,18 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn
* Represents the IR translation of an initialization from an initializer list.
*/
abstract class TranslatedListInitialization extends TranslatedInitialization, InitializationContext {
override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getChild(0).getFirstInstruction(kind)
override Instruction getFirstInstruction() {
result = this.getChild(0).getFirstInstruction()
or
not exists(this.getChild(0)) and
result = this.getParent().getChildSuccessor(this, kind)
not exists(this.getChild(0)) and result = this.getParent().getChildSuccessor(this)
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
override Instruction getChildSuccessor(TranslatedElement child) {
exists(int index |
child = this.getChild(index) and
if exists(this.getChild(index + 1))
then result = this.getChild(index + 1).getFirstInstruction(kind)
else result = this.getParent().getChildSuccessor(this, kind)
then result = this.getChild(index + 1).getFirstInstruction()
else result = this.getParent().getChildSuccessor(this)
)
}
@@ -242,8 +239,8 @@ abstract class TranslatedDirectInitialization extends TranslatedInitialization {
override TranslatedElement getChild(int id) { id = 0 and result = this.getInitializer() }
override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getInitializer().getFirstInstruction(kind)
override Instruction getFirstInstruction() {
result = this.getInitializer().getFirstInstruction()
}
final TranslatedExpr getInitializer() { result = getTranslatedExpr(expr) }
@@ -268,13 +265,12 @@ class TranslatedSimpleDirectInitialization extends TranslatedDirectInitializatio
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = InitializerStoreTag() and
result = this.getParent().getChildSuccessor(this, kind)
result = this.getParent().getChildSuccessor(this) and
kind instanceof GotoEdge
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
child = this.getInitializer() and
result = this.getInstruction(InitializerStoreTag()) and
kind instanceof GotoEdge
override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getInitializer() and result = this.getInstruction(InitializerStoreTag())
}
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
@@ -339,13 +335,12 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
kind instanceof GotoEdge and
tag = InitializerLoadStringTag() and
result = this.getInstruction(InitializerStoreTag())
or
if this.zeroInitRange(_, _)
then (
kind instanceof GotoEdge and
(
(
tag = InitializerLoadStringTag() and
result = this.getInstruction(InitializerStoreTag())
or
if this.zeroInitRange(_, _)
then (
tag = InitializerStoreTag() and
result = this.getInstruction(ZeroPadStringConstantTag())
or
@@ -357,20 +352,18 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
or
tag = ZeroPadStringElementAddressTag() and
result = this.getInstruction(ZeroPadStringStoreTag())
or
tag = ZeroPadStringStoreTag() and
result = this.getParent().getChildSuccessor(this)
) else (
tag = InitializerStoreTag() and
result = this.getParent().getChildSuccessor(this)
)
or
tag = ZeroPadStringStoreTag() and
result = this.getParent().getChildSuccessor(this, kind)
) else (
tag = InitializerStoreTag() and
result = this.getParent().getChildSuccessor(this, kind)
)
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
child = this.getInitializer() and
result = this.getInstruction(InitializerLoadStringTag()) and
kind instanceof GotoEdge
override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getInitializer() and result = this.getInstruction(InitializerLoadStringTag())
}
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
@@ -463,8 +456,8 @@ class TranslatedConstructorInitialization extends TranslatedDirectInitialization
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
child = this.getInitializer() and result = this.getParent().getChildSuccessor(this, kind)
override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getInitializer() and result = this.getParent().getChildSuccessor(this)
}
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
@@ -509,9 +502,8 @@ abstract class TranslatedFieldInitialization extends TranslatedElement {
result = getEnclosingVariable(ast).(StaticInitializedStaticLocalVariable)
}
final override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getInstruction(this.getFieldAddressTag()) and
kind instanceof GotoEdge
final override Instruction getFirstInstruction() {
result = this.getInstruction(this.getFieldAddressTag())
}
/**
@@ -566,11 +558,12 @@ class TranslatedExplicitFieldInitialization extends TranslatedFieldInitializatio
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = this.getFieldAddressTag() and
result = this.getInitialization().getFirstInstruction(kind)
result = this.getInitialization().getFirstInstruction() and
kind instanceof GotoEdge
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
child = this.getInitialization() and result = this.getParent().getChildSuccessor(this, kind)
override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getInitialization() and result = this.getParent().getChildSuccessor(this)
}
override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() }
@@ -615,10 +608,10 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization,
or
tag = this.getFieldDefaultValueTag() and
result = this.getInstruction(this.getFieldDefaultValueStoreTag())
or
tag = this.getFieldDefaultValueStoreTag() and
result = this.getParent().getChildSuccessor(this)
)
or
tag = this.getFieldDefaultValueStoreTag() and
result = this.getParent().getChildSuccessor(this, kind)
}
override string getInstructionConstantValue(InstructionTag tag) {
@@ -639,7 +632,7 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization,
)
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
override Instruction getChildSuccessor(TranslatedElement child) { none() }
override TranslatedElement getChild(int id) { none() }
@@ -674,9 +667,8 @@ abstract class TranslatedElementInitialization extends TranslatedElement {
result = getEnclosingVariable(initList).(StaticInitializedStaticLocalVariable)
}
final override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getInstruction(this.getElementIndexTag()) and
kind instanceof GotoEdge
final override Instruction getFirstInstruction() {
result = this.getInstruction(this.getElementIndexTag())
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
@@ -753,11 +745,12 @@ class TranslatedExplicitElementInitialization extends TranslatedElementInitializ
result = TranslatedElementInitialization.super.getInstructionSuccessor(tag, kind)
or
tag = this.getElementAddressTag() and
result = this.getInitialization().getFirstInstruction(kind)
result = this.getInitialization().getFirstInstruction() and
kind instanceof GotoEdge
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
child = this.getInitialization() and result = this.getParent().getChildSuccessor(this, kind)
override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getInitialization() and result = this.getParent().getChildSuccessor(this)
}
override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() }
@@ -810,10 +803,10 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
or
tag = this.getElementDefaultValueTag() and
result = this.getInstruction(this.getElementDefaultValueStoreTag())
or
tag = this.getElementDefaultValueStoreTag() and
result = this.getParent().getChildSuccessor(this)
)
or
tag = this.getElementDefaultValueStoreTag() and
result = this.getParent().getChildSuccessor(this, kind)
}
override string getInstructionConstantValue(InstructionTag tag) {
@@ -836,7 +829,7 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
)
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
override Instruction getChildSuccessor(TranslatedElement child) { none() }
override TranslatedElement getChild(int id) { none() }
@@ -876,9 +869,9 @@ abstract class TranslatedStructorCallFromStructor extends TranslatedElement, Str
final override Function getFunction() { result = getEnclosingFunction(call) }
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
final override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getStructorCall() and
result = this.getParent().getChildSuccessor(this, kind)
result = this.getParent().getChildSuccessor(this)
}
final TranslatedExpr getStructorCall() { result = getTranslatedExpr(call) }
@@ -889,9 +882,8 @@ abstract class TranslatedStructorCallFromStructor extends TranslatedElement, Str
* destructor from within a derived class constructor or destructor.
*/
abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStructor {
final override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getInstruction(OnlyInstructionTag()) and
kind instanceof GotoEdge
final override Instruction getFirstInstruction() {
result = this.getInstruction(OnlyInstructionTag())
}
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
@@ -902,7 +894,8 @@ abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStru
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = OnlyInstructionTag() and
result = this.getStructorCall().getFirstInstruction(kind)
kind instanceof GotoEdge and
result = this.getStructorCall().getFirstInstruction()
}
final override Instruction getReceiver() { result = this.getInstruction(OnlyInstructionTag()) }
@@ -943,8 +936,8 @@ class TranslatedConstructorDelegationInit extends TranslatedConstructorCallFromC
final override string toString() { result = "delegation construct: " + call.toString() }
final override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getStructorCall().getFirstInstruction(kind)
final override Instruction getFirstInstruction() {
result = this.getStructorCall().getFirstInstruction()
}
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
@@ -1005,9 +998,7 @@ class TranslatedConstructorBareInit extends TranslatedElement, TTranslatedConstr
final override string toString() { result = "construct base (no constructor)" }
override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getParent().getChildSuccessor(this, kind)
}
override Instruction getFirstInstruction() { result = this.getParent().getChildSuccessor(this) }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
none()
@@ -1019,7 +1010,7 @@ class TranslatedConstructorBareInit extends TranslatedElement, TTranslatedConstr
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
override Instruction getChildSuccessor(TranslatedElement child) { none() }
}
TranslatedConstructorBareInit getTranslatedConstructorBareInit(ConstructorInit init) {

View File

@@ -30,9 +30,7 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
final override Locatable getAst() { result = tryExcept.getExcept() }
override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getChild(0).getFirstInstruction(kind)
}
override Instruction getFirstInstruction() { result = this.getChild(0).getFirstInstruction() }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
// t1 = -1
@@ -194,21 +192,23 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
or
// Branch -> Handler (the condition value is always 0, -1 or 1, and we've checked for 0 or -1 already.)
tag = TryExceptCompareOneBranch() and
kind instanceof TrueEdge and
result = this.getTranslatedHandler().getFirstInstruction(any(GotoEdge edge))
(
kind instanceof TrueEdge and
result = this.getTranslatedHandler().getFirstInstruction()
)
or
// Unwind -> Parent
tag = UnwindTag() and
result = this.getParent().getChildSuccessor(this, kind)
kind instanceof GotoEdge and
result = this.getParent().getChildSuccessor(this)
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
kind instanceof GotoEdge and
override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getTranslatedCondition() and
result = this.getInstruction(TryExceptGenerateNegativeOne())
or
child = this.getTranslatedHandler() and
result = this.getParent().getChildSuccessor(this, kind)
result = this.getParent().getChildSuccessor(this)
}
private TranslatedExpr getTranslatedCondition() {
@@ -254,10 +254,7 @@ class TranslatedEmptyStmt extends TranslatedStmt {
override TranslatedElement getChild(int id) { none() }
override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getInstruction(OnlyInstructionTag()) and
kind instanceof GotoEdge
}
override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
tag = OnlyInstructionTag() and
@@ -267,10 +264,11 @@ class TranslatedEmptyStmt extends TranslatedStmt {
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = OnlyInstructionTag() and
result = this.getParent().getChildSuccessor(this, kind)
result = this.getParent().getChildSuccessor(this) and
kind instanceof GotoEdge
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
override Instruction getChildSuccessor(TranslatedElement child) { none() }
}
/**
@@ -287,11 +285,10 @@ class TranslatedDeclStmt extends TranslatedStmt {
none()
}
override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getDeclarationEntry(0).getFirstInstruction(kind)
override Instruction getFirstInstruction() {
result = this.getDeclarationEntry(0).getFirstInstruction()
or
not exists(this.getDeclarationEntry(0)) and
result = this.getParent().getChildSuccessor(this, kind)
not exists(this.getDeclarationEntry(0)) and result = this.getParent().getChildSuccessor(this)
}
private int getChildCount() { result = count(this.getDeclarationEntry(_)) }
@@ -320,12 +317,12 @@ class TranslatedDeclStmt extends TranslatedStmt {
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
override Instruction getChildSuccessor(TranslatedElement child) {
exists(int index |
child = this.getDeclarationEntry(index) and
if index = (this.getChildCount() - 1)
then result = this.getParent().getChildSuccessor(this, kind)
else result = this.getDeclarationEntry(index + 1).getFirstInstruction(kind)
then result = this.getParent().getChildSuccessor(this)
else result = this.getDeclarationEntry(index + 1).getFirstInstruction()
)
}
}
@@ -341,15 +338,13 @@ class TranslatedExprStmt extends TranslatedStmt {
none()
}
override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getExpr().getFirstInstruction(kind)
}
override Instruction getFirstInstruction() { result = this.getExpr().getFirstInstruction() }
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getExpr() and
result = this.getParent().getChildSuccessor(this, kind)
result = this.getParent().getChildSuccessor(this)
}
}
@@ -367,8 +362,8 @@ abstract class TranslatedReturnStmt extends TranslatedStmt {
class TranslatedReturnValueStmt extends TranslatedReturnStmt, TranslatedVariableInitialization {
TranslatedReturnValueStmt() { stmt.hasExpr() and hasReturnValue(stmt.getEnclosingFunction()) }
final override Instruction getInitializationSuccessor(EdgeKind kind) {
result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
final override Instruction getInitializationSuccessor() {
result = this.getEnclosingFunction().getReturnSuccessorInstruction()
}
final override Type getTargetType() { result = this.getEnclosingFunction().getReturnType() }
@@ -395,9 +390,7 @@ class TranslatedReturnVoidExpressionStmt extends TranslatedReturnStmt {
result = this.getExpr()
}
override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getExpr().getFirstInstruction(kind)
}
override Instruction getFirstInstruction() { result = this.getExpr().getFirstInstruction() }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
tag = OnlyInstructionTag() and
@@ -407,13 +400,13 @@ class TranslatedReturnVoidExpressionStmt extends TranslatedReturnStmt {
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = OnlyInstructionTag() and
result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
result = this.getEnclosingFunction().getReturnSuccessorInstruction() and
kind instanceof GotoEdge
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getExpr() and
result = this.getInstruction(OnlyInstructionTag()) and
kind instanceof GotoEdge
result = this.getInstruction(OnlyInstructionTag())
}
private TranslatedExpr getExpr() { result = getTranslatedExpr(stmt.getExpr()) }
@@ -430,10 +423,7 @@ class TranslatedReturnVoidStmt extends TranslatedReturnStmt {
override TranslatedElement getChild(int id) { none() }
override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getInstruction(OnlyInstructionTag()) and
kind instanceof GotoEdge
}
override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
tag = OnlyInstructionTag() and
@@ -443,10 +433,11 @@ class TranslatedReturnVoidStmt extends TranslatedReturnStmt {
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = OnlyInstructionTag() and
result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
result = this.getEnclosingFunction().getReturnSuccessorInstruction() and
kind instanceof GotoEdge
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
override Instruction getChildSuccessor(TranslatedElement child) { none() }
}
/**
@@ -460,8 +451,8 @@ class TranslatedNoValueReturnStmt extends TranslatedReturnStmt, TranslatedVariab
not stmt.hasExpr() and hasReturnValue(stmt.getEnclosingFunction())
}
final override Instruction getInitializationSuccessor(EdgeKind kind) {
result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
final override Instruction getInitializationSuccessor() {
result = this.getEnclosingFunction().getReturnSuccessorInstruction()
}
final override Type getTargetType() { result = this.getEnclosingFunction().getReturnType() }
@@ -533,42 +524,40 @@ class TranslatedTryStmt extends TranslatedStmt {
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getBody().getFirstInstruction(kind)
}
override Instruction getFirstInstruction() { result = this.getBody().getFirstInstruction() }
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
override Instruction getChildSuccessor(TranslatedElement child) {
// 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.
child = [this.getBody(), this.getHandler(_)] and
(
not exists(this.getFinally()) and
result = this.getParent().getChildSuccessor(this, kind)
result = this.getParent().getChildSuccessor(this)
or
result = this.getFinally().getFirstInstruction(kind)
result = this.getFinally().getFirstInstruction()
)
or
// And after the finally block we go to the successor of the `try`.
child = this.getFinally() and
result = this.getParent().getChildSuccessor(this, kind)
result = this.getParent().getChildSuccessor(this)
}
final Instruction getNextHandler(TranslatedHandler handler, EdgeKind kind) {
final Instruction getNextHandler(TranslatedHandler handler) {
exists(int index |
handler = this.getHandler(index) and
result = this.getHandler(index + 1).getFirstInstruction(kind)
result = this.getHandler(index + 1).getFirstInstruction()
)
or
// The last catch clause flows to the exception successor of the parent
// of the `try`, because the exception successor of the `try` itself is
// the first catch clause.
handler = this.getHandler(stmt.getNumberOfCatchClauses() - 1) and
result = this.getParent().getExceptionSuccessorInstruction(kind)
result = this.getParent().getExceptionSuccessorInstruction()
}
final override Instruction getExceptionSuccessorInstruction(EdgeKind kind) {
result = this.getHandler(0).getFirstInstruction(kind)
final override Instruction getExceptionSuccessorInstruction() {
result = this.getHandler(0).getFirstInstruction()
}
private TranslatedElement getHandler(int index) { result = stmt.getTranslatedHandler(index) }
@@ -590,10 +579,10 @@ class TranslatedBlock extends TranslatedStmt {
resultType = getVoidType()
}
override Instruction getFirstInstruction(EdgeKind kind) {
override Instruction getFirstInstruction() {
if this.isEmpty()
then kind instanceof GotoEdge and result = this.getInstruction(OnlyInstructionTag())
else result = this.getStmt(0).getFirstInstruction(kind)
then result = this.getInstruction(OnlyInstructionTag())
else result = this.getStmt(0).getFirstInstruction()
}
private predicate isEmpty() { not exists(stmt.getStmt(0)) }
@@ -604,15 +593,16 @@ class TranslatedBlock extends TranslatedStmt {
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = OnlyInstructionTag() and
result = this.getParent().getChildSuccessor(this, kind)
result = this.getParent().getChildSuccessor(this) and
kind instanceof GotoEdge
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
override Instruction getChildSuccessor(TranslatedElement child) {
exists(int index |
child = this.getStmt(index) and
if index = (this.getStmtCount() - 1)
then result = this.getParent().getChildSuccessor(this, kind)
else result = this.getStmt(index + 1).getFirstInstruction(kind)
then result = this.getParent().getChildSuccessor(this)
else result = this.getStmt(index + 1).getFirstInstruction()
)
}
}
@@ -625,19 +615,16 @@ abstract class TranslatedHandler extends TranslatedStmt {
override TranslatedElement getChild(int id) { id = 1 and result = this.getBlock() }
override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getInstruction(CatchTag()) and
kind instanceof GotoEdge
override Instruction getFirstInstruction() { result = this.getInstruction(CatchTag()) }
override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getBlock() and result = this.getParent().getChildSuccessor(this)
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
child = this.getBlock() and result = this.getParent().getChildSuccessor(this, kind)
}
override Instruction getExceptionSuccessorInstruction(EdgeKind kind) {
override Instruction getExceptionSuccessorInstruction() {
// A throw from within a `catch` block flows to the handler for the parent of
// the `try`.
result = this.getParent().getParent().getExceptionSuccessorInstruction(kind)
result = this.getParent().getParent().getExceptionSuccessorInstruction()
}
TranslatedStmt getBlock() { result = getTranslatedStmt(stmt.getBlock()) }
@@ -662,21 +649,20 @@ class TranslatedCatchByTypeHandler extends TranslatedHandler {
id = 0 and result = this.getParameter()
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
result = super.getChildSuccessor(child, kind)
override Instruction getChildSuccessor(TranslatedElement child) {
result = super.getChildSuccessor(child)
or
child = this.getParameter() and
result = this.getBlock().getFirstInstruction(kind)
child = this.getParameter() and result = this.getBlock().getFirstInstruction()
}
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = CatchTag() and
(
kind instanceof GotoEdge and
result = this.getParameter().getFirstInstruction(kind)
result = this.getParameter().getFirstInstruction()
or
kind instanceof ExceptionEdge and
result = this.getParent().(TranslatedTryStmt).getNextHandler(this, any(GotoEdge edge))
result = this.getParent().(TranslatedTryStmt).getNextHandler(this)
)
}
@@ -704,17 +690,18 @@ class TranslatedCatchAnyHandler extends TranslatedHandler {
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = CatchTag() and
result = this.getBlock().getFirstInstruction(kind)
kind instanceof GotoEdge and
result = this.getBlock().getFirstInstruction()
}
}
class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
override IfStmt stmt;
override Instruction getFirstInstruction(EdgeKind kind) {
override Instruction getFirstInstruction() {
if this.hasInitialization()
then result = this.getInitialization().getFirstInstruction(kind)
else result = this.getFirstConditionInstruction(kind)
then result = this.getInitialization().getFirstInstruction()
else result = this.getFirstConditionInstruction()
}
override TranslatedElement getChild(int id) {
@@ -737,8 +724,8 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
result = getTranslatedCondition(stmt.getCondition().getFullyConverted())
}
private Instruction getFirstConditionInstruction(EdgeKind kind) {
result = this.getCondition().getFirstInstruction(kind)
private Instruction getFirstConditionInstruction() {
result = this.getCondition().getFirstInstruction()
}
private TranslatedStmt getThen() { result = getTranslatedStmt(stmt.getThen()) }
@@ -749,90 +736,24 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
override Instruction getChildTrueSuccessor(TranslatedCondition child, EdgeKind kind) {
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
child = this.getCondition() and
result = this.getThen().getFirstInstruction(kind)
result = this.getThen().getFirstInstruction()
}
override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
child = this.getCondition() and
if this.hasElse()
then result = this.getElse().getFirstInstruction(kind)
else result = this.getParent().getChildSuccessor(this, kind)
then result = this.getElse().getFirstInstruction()
else result = this.getParent().getChildSuccessor(this)
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getInitialization() and
result = this.getFirstConditionInstruction(kind)
result = this.getFirstConditionInstruction()
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()
}
}
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 getChild(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 getInstructionSuccessor(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 getChildSuccessor(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)
result = this.getParent().getChildSuccessor(this)
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
@@ -849,10 +770,10 @@ abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
final TranslatedStmt getBody() { result = getTranslatedStmt(stmt.getStmt()) }
final Instruction getFirstConditionInstruction(EdgeKind kind) {
final Instruction getFirstConditionInstruction() {
if this.hasCondition()
then result = this.getCondition().getFirstInstruction(kind)
else result = this.getBody().getFirstInstruction(kind)
then result = this.getCondition().getFirstInstruction()
else result = this.getBody().getFirstInstruction()
}
final predicate hasCondition() { exists(stmt.getCondition()) }
@@ -869,39 +790,32 @@ abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
final override Instruction getInstructionSuccessor(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 getChildTrueSuccessor(TranslatedCondition child) {
child = this.getCondition() and result = this.getBody().getFirstInstruction()
}
final override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
child = this.getCondition() and
result = this.getParent().getChildSuccessor(this, kind)
final override Instruction getChildFalseSuccessor(TranslatedCondition child) {
child = this.getCondition() and result = this.getParent().getChildSuccessor(this)
}
}
class TranslatedWhileStmt extends TranslatedLoop {
TranslatedWhileStmt() { stmt instanceof WhileStmt }
override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getFirstConditionInstruction(kind)
}
override Instruction getFirstInstruction() { result = this.getFirstConditionInstruction() }
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
child = this.getBody() and
result = this.getFirstConditionInstruction(kind)
override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getBody() and result = this.getFirstConditionInstruction()
}
}
class TranslatedDoStmt extends TranslatedLoop {
TranslatedDoStmt() { stmt instanceof DoStmt }
override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getBody().getFirstInstruction(kind)
}
override Instruction getFirstInstruction() { result = this.getBody().getFirstInstruction() }
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
child = this.getBody() and
result = this.getFirstConditionInstruction(kind)
override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getBody() and result = this.getFirstConditionInstruction()
}
}
@@ -928,24 +842,24 @@ class TranslatedForStmt extends TranslatedLoop {
private predicate hasUpdate() { exists(stmt.getUpdate()) }
override Instruction getFirstInstruction(EdgeKind kind) {
override Instruction getFirstInstruction() {
if this.hasInitialization()
then result = this.getInitialization().getFirstInstruction(kind)
else result = this.getFirstConditionInstruction(kind)
then result = this.getInitialization().getFirstInstruction()
else result = this.getFirstConditionInstruction()
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getInitialization() and
result = this.getFirstConditionInstruction(kind)
result = this.getFirstConditionInstruction()
or
(
child = this.getBody() and
if this.hasUpdate()
then result = this.getUpdate().getFirstInstruction(kind)
else result = this.getFirstConditionInstruction(kind)
then result = this.getUpdate().getFirstInstruction()
else result = this.getFirstConditionInstruction()
)
or
child = this.getUpdate() and result = this.getFirstConditionInstruction(kind)
child = this.getUpdate() and result = this.getFirstConditionInstruction()
}
}
@@ -960,52 +874,39 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
override RangeBasedForStmt stmt;
override TranslatedElement getChild(int id) {
id = 0 and result = this.getInitialization()
or
id = 1 and result = this.getRangeVariableDeclStmt()
id = 0 and result = this.getRangeVariableDeclStmt()
or
// Note: `__begin` and `__end` are declared by the same `DeclStmt`
id = 2 and result = this.getBeginEndVariableDeclStmt()
id = 1 and result = this.getBeginEndVariableDeclStmt()
or
id = 3 and result = this.getCondition()
id = 2 and result = this.getCondition()
or
id = 4 and result = this.getUpdate()
id = 3 and result = this.getUpdate()
or
id = 5 and result = this.getVariableDeclStmt()
id = 4 and result = this.getVariableDeclStmt()
or
id = 6 and result = this.getBody()
id = 5 and result = this.getBody()
}
private predicate hasInitialization() { exists(stmt.getInitialization()) }
private TranslatedStmt getInitialization() {
result = getTranslatedStmt(stmt.getInitialization())
override Instruction getFirstInstruction() {
result = this.getRangeVariableDeclStmt().getFirstInstruction()
}
override Instruction getFirstInstruction(EdgeKind kind) {
if this.hasInitialization()
then result = this.getInitialization().getFirstInstruction(kind)
else result = this.getFirstRangeVariableDeclStmtInstruction(kind)
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
child = this.getInitialization() and
result = this.getFirstRangeVariableDeclStmtInstruction(kind)
or
override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getRangeVariableDeclStmt() and
result = this.getBeginEndVariableDeclStmt().getFirstInstruction(kind)
result = this.getBeginEndVariableDeclStmt().getFirstInstruction()
or
child = this.getBeginEndVariableDeclStmt() and
result = this.getCondition().getFirstInstruction(kind)
result = this.getCondition().getFirstInstruction()
or
child = this.getVariableDeclStmt() and
result = this.getBody().getFirstInstruction(kind)
result = this.getBody().getFirstInstruction()
or
child = this.getBody() and
result = this.getUpdate().getFirstInstruction(kind)
result = this.getUpdate().getFirstInstruction()
or
child = this.getUpdate() and
result = this.getCondition().getFirstInstruction(kind)
result = this.getCondition().getFirstInstruction()
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
@@ -1014,14 +915,12 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
override Instruction getChildTrueSuccessor(TranslatedCondition child, EdgeKind kind) {
child = this.getCondition() and
result = this.getVariableDeclStmt().getFirstInstruction(kind)
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
child = this.getCondition() and result = this.getVariableDeclStmt().getFirstInstruction()
}
override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
child = this.getCondition() and
result = this.getParent().getChildSuccessor(this, kind)
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
child = this.getCondition() and result = this.getParent().getChildSuccessor(this)
}
private TranslatedDeclStmt getRangeVariableDeclStmt() {
@@ -1031,10 +930,6 @@ 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
@@ -1065,10 +960,7 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
class TranslatedJumpStmt extends TranslatedStmt {
override JumpStmt stmt;
override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getInstruction(OnlyInstructionTag()) and
kind instanceof GotoEdge
}
override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) }
override TranslatedElement getChild(int id) { none() }
@@ -1080,10 +972,11 @@ class TranslatedJumpStmt extends TranslatedStmt {
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = OnlyInstructionTag() and
result = getTranslatedStmt(stmt.getTarget()).getFirstInstruction(kind)
kind instanceof GotoEdge and
result = getTranslatedStmt(stmt.getTarget()).getFirstInstruction()
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
override Instruction getChildSuccessor(TranslatedElement child) { none() }
}
private EdgeKind getCaseEdge(SwitchCase switchCase) {
@@ -1102,16 +995,14 @@ class TranslatedSwitchStmt extends TranslatedStmt {
result = getTranslatedExpr(stmt.getExpr().getFullyConverted())
}
private Instruction getFirstExprInstruction(EdgeKind kind) {
result = this.getExpr().getFirstInstruction(kind)
}
private Instruction getFirstExprInstruction() { result = this.getExpr().getFirstInstruction() }
private TranslatedStmt getBody() { result = getTranslatedStmt(stmt.getStmt()) }
override Instruction getFirstInstruction(EdgeKind kind) {
override Instruction getFirstInstruction() {
if this.hasInitialization()
then result = this.getInitialization().getFirstInstruction(kind)
else result = this.getFirstExprInstruction(kind)
then result = this.getInitialization().getFirstInstruction()
else result = this.getFirstExprInstruction()
}
override TranslatedElement getChild(int id) {
@@ -1145,24 +1036,21 @@ class TranslatedSwitchStmt extends TranslatedStmt {
exists(SwitchCase switchCase |
switchCase = stmt.getASwitchCase() and
kind = getCaseEdge(switchCase) and
result = getTranslatedStmt(switchCase).getFirstInstruction(any(GotoEdge edge))
result = getTranslatedStmt(switchCase).getFirstInstruction()
)
or
not stmt.hasDefaultCase() and
tag = SwitchBranchTag() and
kind instanceof DefaultEdge and
result = this.getParent().getChildSuccessor(this, any(GotoEdge edge))
result = this.getParent().getChildSuccessor(this)
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
child = this.getInitialization() and
result = this.getFirstExprInstruction(kind)
override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getInitialization() and result = this.getFirstExprInstruction()
or
kind instanceof GotoEdge and
child = this.getExpr() and
result = this.getInstruction(SwitchBranchTag())
child = this.getExpr() and result = this.getInstruction(SwitchBranchTag())
or
child = this.getBody() and result = this.getParent().getChildSuccessor(this, kind)
child = this.getBody() and result = this.getParent().getChildSuccessor(this)
}
}
@@ -1173,12 +1061,10 @@ class TranslatedAsmStmt extends TranslatedStmt {
result = getTranslatedExpr(stmt.getChild(id).(Expr).getFullyConverted())
}
override Instruction getFirstInstruction(EdgeKind kind) {
override Instruction getFirstInstruction() {
if exists(this.getChild(0))
then result = this.getChild(0).getFirstInstruction(kind)
else (
kind instanceof GotoEdge and result = this.getInstruction(AsmTag())
)
then result = this.getChild(0).getFirstInstruction()
else result = this.getInstruction(AsmTag())
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
@@ -1205,17 +1091,16 @@ class TranslatedAsmStmt extends TranslatedStmt {
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = AsmTag() and
result = this.getParent().getChildSuccessor(this, kind)
result = this.getParent().getChildSuccessor(this) and
kind instanceof GotoEdge
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
override Instruction getChildSuccessor(TranslatedElement child) {
exists(int index |
child = this.getChild(index) and
if exists(this.getChild(index + 1))
then result = this.getChild(index + 1).getFirstInstruction(kind)
else (
kind instanceof GotoEdge and result = this.getInstruction(AsmTag())
)
then result = this.getChild(index + 1).getFirstInstruction()
else result = this.getInstruction(AsmTag())
)
}
}
@@ -1228,9 +1113,7 @@ class TranslatedVlaDimensionStmt extends TranslatedStmt {
result = getTranslatedExpr(stmt.getDimensionExpr().getFullyConverted())
}
override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getChild(0).getFirstInstruction(kind)
}
override Instruction getFirstInstruction() { result = this.getChild(0).getFirstInstruction() }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
none()
@@ -1238,9 +1121,9 @@ class TranslatedVlaDimensionStmt extends TranslatedStmt {
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getChild(0) and
result = this.getParent().getChildSuccessor(this, kind)
result = this.getParent().getChildSuccessor(this)
}
}
@@ -1249,10 +1132,7 @@ class TranslatedVlaDeclarationStmt extends TranslatedStmt {
override TranslatedExpr getChild(int id) { none() }
override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getInstruction(OnlyInstructionTag()) and
kind instanceof GotoEdge
}
override Instruction getFirstInstruction() { 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.
@@ -1264,8 +1144,9 @@ class TranslatedVlaDeclarationStmt extends TranslatedStmt {
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = OnlyInstructionTag() and
result = this.getParent().getChildSuccessor(this, kind)
result = this.getParent().getChildSuccessor(this) and
kind instanceof GotoEdge
}
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
override Instruction getChildSuccessor(TranslatedElement child) { none() }
}

View File

@@ -2125,6 +2125,13 @@ 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

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