Compare commits

..

1 Commits

Author SHA1 Message Date
Florin Coada
4cf5d4178f Changelogx fix for 2.18.0 c/cpp breaking changes 2024-07-29 10:11:26 +01:00
8950 changed files with 203749 additions and 508608 deletions

View File

@@ -24,7 +24,5 @@ common --registry=file:///%workspace%/misc/bazel/registry
common --registry=https://bcr.bazel.build
common --@rules_dotnet//dotnet/settings:strict_deps=false
common --experimental_isolated_extension_usages
common --incompatible_use_plus_in_repo_names
try-import %workspace%/local.bazelrc

View File

@@ -8,4 +8,3 @@ common --registry=https://bcr.bazel.build
# its implementation packages without providing any code itself.
# We either can depend on internal implementation details, or turn of strict deps.
common --@rules_dotnet//dotnet/settings:strict_deps=false
common --experimental_isolated_extension_usages

View File

@@ -1 +1 @@
5f5d70b6c4d2fb1a889479569107f1692239e8a7
7.2.1

4
.github/labeler.yml vendored
View File

@@ -30,10 +30,6 @@ Ruby:
- ruby/**/*
- change-notes/**/*ruby*
Rust:
- rust/**/*
- change-notes/**/*rust*
Swift:
- swift/**/*
- change-notes/**/*swift*

View File

@@ -1,14 +0,0 @@
### Pull Request checklist
#### All query authors
- [ ] A change note is added if necessary. See [the documentation](https://github.com/github/codeql/blob/main/docs/change-notes.md) in this repository.
- [ ] All new queries have appropriate `.qhelp`. See [the documentation](https://github.com/github/codeql/blob/main/docs/query-help-style-guide.md) in this repository.
- [ ] QL tests are added if necessary. See [Testing custom queries](https://docs.github.com/en/code-security/codeql-cli/using-the-advanced-functionality-of-the-codeql-cli/testing-custom-queries) in the GitHub documentation.
- [ ] New and changed queries have correct query metadata. See [the documentation](https://github.com/github/codeql/blob/main/docs/query-metadata-style-guide.md) in this repository.
#### Internal query authors only
- [ ] Autofixes generated based on these changes are valid, only needed if this PR makes significant changes to `.ql`, `.qll`, or `.qhelp` files. See [the documentation](https://github.com/github/codeql-team/blob/main/docs/best-practices/validating-autofix-for-query-changes.md) (internal access required).
- [ ] Changes are validated [at scale](https://github.com/github/codeql-dca/) (internal access required).
- [ ] Adding a new query? Consider also [adding the query to autofix](https://github.com/github/codeml-autofix/blob/main/docs/updating-query-support.md#adding-a-new-query-to-the-query-suite).

View File

@@ -24,5 +24,5 @@ jobs:
extra_args: >
buildifier --all-files 2>&1 ||
(
echo -e "In order to format all bazel files, please run:\n bazel run //misc/bazel/buildifier"; exit 1
echo -e "In order to format all bazel files, please run:\n bazel run //misc/bazel:buildifier"; exit 1
)

View File

@@ -16,12 +16,11 @@ on:
- "shared/**/*.qll"
- "!**/experimental/**"
- "!ql/**"
- "!rust/**"
- ".github/workflows/check-change-note.yml"
jobs:
check-change-note:
env:
env:
REPO: ${{ github.repository }}
PULL_REQUEST_NUMBER: ${{ github.event.number }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -34,7 +33,7 @@ jobs:
!contains(github.event.pull_request.labels.*.name, 'no-change-note-required')
run: |
change_note_files=$(gh api "repos/$REPO/pulls/$PULL_REQUEST_NUMBER/files" --paginate --jq '.[].filename | select(test("/change-notes/.*[.]md$"))')
if [ -z "$change_note_files" ]; then
echo "No change note found. Either add one, or add the 'no-change-note-required' label."
exit 1

View File

@@ -37,7 +37,7 @@ jobs:
with:
languages: cpp
config-file: ./.github/codeql/codeql-config.yml
- name: "[Ubuntu] Remove GCC 13 from runner image"
shell: bash
run: |
@@ -48,7 +48,7 @@ jobs:
- name: "Build Swift extractor using Bazel"
run: |
bazel clean --expunge
bazel run //swift:create-extractor-pack --nouse_action_cache --noremote_accept_cached --noremote_upload_local_results --spawn_strategy=local
bazel run //swift:create-extractor-pack --nouse_action_cache --noremote_accept_cached --noremote_upload_local_results --spawn_strategy=local --features=-layering_check
bazel shutdown
- name: Perform CodeQL Analysis

View File

@@ -29,6 +29,45 @@ permissions:
contents: read
jobs:
qlupgrade:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/fetch-codeql
- name: Check DB upgrade scripts
run: |
echo >empty.trap
codeql dataset import -S ql/lib/upgrades/initial/semmlecode.csharp.dbscheme testdb empty.trap
codeql dataset upgrade testdb --additional-packs ql/lib
diff -q testdb/semmlecode.csharp.dbscheme ql/lib/semmlecode.csharp.dbscheme
- name: Check DB downgrade scripts
run: |
echo >empty.trap
rm -rf testdb; codeql dataset import -S ql/lib/semmlecode.csharp.dbscheme testdb empty.trap
codeql resolve upgrades --format=lines --allow-downgrades --additional-packs downgrades \
--dbscheme=ql/lib/semmlecode.csharp.dbscheme --target-dbscheme=downgrades/initial/semmlecode.csharp.dbscheme |
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
matrix:
slice: ["1/2", "2/2"]
steps:
- uses: actions/checkout@v4
- uses: ./csharp/actions/create-extractor-pack
- name: Cache compilation cache
id: query-cache
uses: ./.github/actions/cache-query-compilation
with:
key: csharp-qltest-${{ matrix.slice }}
- name: Run QL tests
run: |
codeql test run --threads=0 --ram 50000 --slice ${{ matrix.slice }} --search-path "${{ github.workspace }}" --check-databases --check-undefined-labels --check-repeated-labels --check-redefined-labels --consistency-queries ql/consistency-queries ql/test --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
env:
GITHUB_TOKEN: ${{ github.token }}
unit-tests:
strategy:
matrix:

View File

@@ -3,7 +3,6 @@ on:
push:
paths:
- "go/**"
- "shared/**"
- .github/workflows/go-tests.yml
- .github/actions/**
- codeql-workspace.yml
@@ -13,7 +12,6 @@ on:
pull_request:
paths:
- "go/**"
- "shared/**"
- .github/workflows/go-tests.yml
- .github/actions/**
- codeql-workspace.yml

View File

@@ -65,8 +65,8 @@ jobs:
id: cache-extractor
with:
path: |
target/release/codeql-extractor-ruby
target/release/codeql-extractor-ruby.exe
ruby/extractor/target/release/codeql-extractor-ruby
ruby/extractor/target/release/codeql-extractor-ruby.exe
ruby/extractor/ql/lib/codeql/ruby/ast/internal/TreeSitter.qll
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-ruby-extractor-${{ hashFiles('ruby/extractor/rust-toolchain.toml', 'ruby/extractor/Cargo.lock') }}-${{ hashFiles('shared/tree-sitter-extractor') }}-${{ hashFiles('ruby/extractor/**/*.rs') }}
- uses: actions/cache@v3
@@ -75,7 +75,7 @@ jobs:
path: |
~/.cargo/registry
~/.cargo/git
target
ruby/target
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-ruby-rust-cargo-${{ hashFiles('ruby/extractor/rust-toolchain.toml', 'ruby/extractor/**/Cargo.lock') }}
- name: Check formatting
if: steps.cache-extractor.outputs.cache-hit != 'true'
@@ -91,7 +91,7 @@ jobs:
run: cd extractor && cargo build --release
- name: Generate dbscheme
if: ${{ matrix.os == 'ubuntu-latest' && steps.cache-extractor.outputs.cache-hit != 'true'}}
run: ../target/release/codeql-extractor-ruby generate --dbscheme ql/lib/ruby.dbscheme --library ql/lib/codeql/ruby/ast/internal/TreeSitter.qll
run: extractor/target/release/codeql-extractor-ruby generate --dbscheme ql/lib/ruby.dbscheme --library ql/lib/codeql/ruby/ast/internal/TreeSitter.qll
- uses: actions/upload-artifact@v3
if: ${{ matrix.os == 'ubuntu-latest' }}
with:
@@ -106,8 +106,8 @@ jobs:
with:
name: extractor-${{ matrix.os }}
path: |
target/release/codeql-extractor-ruby
target/release/codeql-extractor-ruby.exe
ruby/extractor/target/release/codeql-extractor-ruby
ruby/extractor/target/release/codeql-extractor-ruby.exe
retention-days: 1
compile-queries:
if: github.repository_owner == 'github'
@@ -140,7 +140,6 @@ jobs:
path: |
${{ runner.temp }}/query-packs/*
retention-days: 1
include-hidden-files: true
package:
runs-on: ubuntu-latest
@@ -177,7 +176,6 @@ jobs:
name: codeql-ruby-pack
path: ruby/codeql-ruby.zip
retention-days: 1
include-hidden-files: true
- uses: actions/download-artifact@v3
with:
name: codeql-ruby-queries
@@ -195,7 +193,6 @@ jobs:
name: codeql-ruby-bundle
path: ruby/codeql-ruby-bundle.zip
retention-days: 1
include-hidden-files: true
test:
defaults:

View File

@@ -1,58 +0,0 @@
name: "Rust"
on:
pull_request:
paths:
- "rust/**"
- "misc/bazel/**"
- "misc/codegen/**"
- "shared/**"
- "MODULE.bazel"
- .github/workflows/rust.yml
- .github/actions/**
- codeql-workspace.yml
- "!**/*.md"
- "!**/*.qhelp"
branches:
- rust-experiment
- main
- rc/*
- codeql-cli-*
permissions:
contents: read
jobs:
rust-code:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Format
working-directory: rust/extractor
shell: bash
run: |
cargo fmt --check
- name: Compilation
working-directory: rust/extractor
shell: bash
run: cargo check
- name: Clippy
working-directory: rust/extractor
shell: bash
run: |
cargo clippy --fix
git diff --exit-code
rust-codegen:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install CodeQL
uses: ./.github/actions/fetch-codeql
- name: Code generation
shell: bash
run: |
bazel run //rust/codegen
git add .
git diff --exit-code HEAD

8
.gitignore vendored
View File

@@ -7,8 +7,8 @@
.cache
# qltest projects and artifacts
*.actual
*/ql/test/**/*.testproj
*/ql/test/**/*.actual
*/ql/test/**/go.sum
# Visual studio temporaries, except a file used by QL4VS
@@ -65,9 +65,3 @@ node_modules/
# bazel-built in-tree extractor packs
/*/extractor-pack
# Jetbrains IDE files
.idea
# cargo build directory
/target

View File

@@ -5,9 +5,9 @@ repos:
rev: v3.2.0
hooks:
- id: trailing-whitespace
exclude: /test/.*$(?<!\.qlref)|.*\.patch$|.*\.qll?$
exclude: /test/.*$(?<!\.ql)(?<!\.qll)(?<!\.qlref)|.*\.patch
- id: end-of-file-fixer
exclude: /test/.*$(?<!\.qlref)|.*\.patch$|.*\.qll?$
exclude: /test/.*$(?<!\.ql)(?<!\.qll)(?<!\.qlref)|.*\.patch
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v17.0.6
@@ -15,7 +15,7 @@ repos:
- id: clang-format
- repo: https://github.com/pre-commit/mirrors-autopep8
rev: v2.0.4
rev: v1.6.0
hooks:
- id: autopep8
files: ^misc/codegen/.*\.py
@@ -26,7 +26,7 @@ repos:
name: Format bazel files
files: \.(bazel|bzl)
language: system
entry: bazel run //misc/bazel/buildifier
entry: bazel run //misc/bazel:buildifier
pass_filenames: false
# DISABLED: can be enabled by copying this config and installing `pre-commit` with `--config` on the copy
@@ -45,7 +45,7 @@ repos:
- id: sync-files
name: Fix files required to be identical
files: \.(qll?|qhelp|swift|toml)$|^config/identical-files\.json$
files: \.(qll?|qhelp|swift)$|^config/identical-files\.json$
language: system
entry: python3 config/sync-files.py --latest
pass_filenames: false
@@ -58,7 +58,7 @@ repos:
- id: swift-codegen
name: Run Swift checked in code generation
files: ^misc/codegen/|^swift/(schema.py$|codegen/|.*/generated/|ql/lib/(swift\.dbscheme$|codeql/swift/elements)|ql/\.generated.list)
files: ^swift/(schema.py$|codegen/|.*/generated/|ql/lib/(swift\.dbscheme$|codeql/swift/elements)|ql/\.generated.list)
language: system
entry: bazel run //swift/codegen -- --quiet
pass_filenames: false
@@ -69,17 +69,3 @@ repos:
language: system
entry: bazel test //misc/codegen/test
pass_filenames: false
- id: rust-codegen
name: Run Rust checked in code generation
files: ^misc/codegen/|^rust/(schema.py$|codegen/|.*/generated/|ql/lib/(rust\.dbscheme$|codeql/rust/elements)|\.generated.list)
language: system
entry: bazel run //rust/codegen -- --quiet
pass_filenames: false
- id: rust-lint
name: Run fmt and clippy on Rust code
files: ^rust/extractor/(.*rs|Cargo.toml)$
language: system
entry: python3 rust/lint.py
pass_filenames: false

2686
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,16 +0,0 @@
# This is the shared workspace file for extractor using shared/tree-sitter/extractor
[workspace]
resolver = "2"
members = [
"shared/tree-sitter-extractor",
"ruby/extractor",
"rust/extractor",
"rust/extractor/macros",
"rust/ast-generator",
]
[patch.crates-io]
# patch for build script bug preventing bazel build
# see https://github.com/rust-lang/rustc_apfloat/pull/17
rustc_apfloat = { git = "https://github.com/redsun82/rustc_apfloat.git", rev = "096d585100636bc2e9f09d7eefec38c5b334d47b" }

View File

@@ -1,7 +1,6 @@
module(
name = "ql",
name = "codeql",
version = "0.0",
repo_name = "codeql",
)
# this points to our internal repository when `codeql` is checked out as a submodule thereof
@@ -15,29 +14,27 @@ local_path_override(
# see https://registry.bazel.build/ for a list of available packages
bazel_dep(name = "platforms", version = "0.0.10")
bazel_dep(name = "rules_go", version = "0.50.0")
bazel_dep(name = "rules_pkg", version = "1.0.1")
bazel_dep(name = "rules_go", version = "0.48.0")
bazel_dep(name = "rules_pkg", version = "0.10.1")
bazel_dep(name = "rules_nodejs", version = "6.2.0-codeql.1")
bazel_dep(name = "rules_python", version = "0.35.0")
bazel_dep(name = "rules_python", version = "0.32.2")
bazel_dep(name = "bazel_skylib", version = "1.6.1")
bazel_dep(name = "abseil-cpp", version = "20240116.0", repo_name = "absl")
bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json")
bazel_dep(name = "fmt", version = "10.0.0")
bazel_dep(name = "rules_kotlin", version = "2.0.0-codeql.1")
bazel_dep(name = "gazelle", version = "0.38.0")
bazel_dep(name = "rules_kotlin", version = "1.9.4-codeql.1")
bazel_dep(name = "gazelle", version = "0.37.0")
bazel_dep(name = "rules_dotnet", version = "0.15.1")
bazel_dep(name = "googletest", version = "1.14.0.bcr.1")
bazel_dep(name = "rules_rust", version = "0.52.2")
bazel_dep(name = "rules_rust", version = "0.46.0")
bazel_dep(name = "buildifier_prebuilt", version = "6.4.0", dev_dependency = True)
# crate_py but shortened due to Windows file path considerations
cp = use_extension(
crate = use_extension(
"@rules_rust//crate_universe:extension.bzl",
"crate",
isolate = True,
)
cp.from_cargo(
crate.from_cargo(
name = "py_deps",
cargo_lockfile = "//python/extractor/tsg-python:Cargo.lock",
manifests = [
@@ -45,27 +42,15 @@ cp.from_cargo(
"//python/extractor/tsg-python/tsp:Cargo.toml",
],
)
use_repo(cp, "py_deps")
# deps for ruby+rust, but shortened due to windows file paths
r = use_extension(
"@rules_rust//crate_universe:extension.bzl",
"crate",
isolate = True,
)
r.from_cargo(
name = "r",
cargo_lockfile = "//:Cargo.lock",
crate.from_cargo(
name = "ruby_deps",
cargo_lockfile = "//ruby/extractor:Cargo.lock",
manifests = [
"//:Cargo.toml",
"//ruby/extractor:Cargo.toml",
"//rust/extractor:Cargo.toml",
"//rust/extractor/macros:Cargo.toml",
"//rust/ast-generator:Cargo.toml",
"//shared/tree-sitter-extractor:Cargo.toml",
"//ruby/extractor/codeql-extractor-fake-crate:Cargo.toml",
],
)
use_repo(r, tree_sitter_extractors_deps = "r")
use_repo(crate, "py_deps", "ruby_deps")
dotnet = use_extension("@rules_dotnet//dotnet:extensions.bzl", "dotnet")
dotnet.toolchain(dotnet_version = "8.0.101")
@@ -128,7 +113,6 @@ use_repo(
"kotlin-compiler-1.9.20-Beta",
"kotlin-compiler-2.0.0-RC1",
"kotlin-compiler-2.0.20-Beta2",
"kotlin-compiler-2.1.0-Beta1",
"kotlin-compiler-embeddable-1.5.0",
"kotlin-compiler-embeddable-1.5.10",
"kotlin-compiler-embeddable-1.5.20",
@@ -142,7 +126,6 @@ use_repo(
"kotlin-compiler-embeddable-1.9.20-Beta",
"kotlin-compiler-embeddable-2.0.0-RC1",
"kotlin-compiler-embeddable-2.0.20-Beta2",
"kotlin-compiler-embeddable-2.1.0-Beta1",
"kotlin-stdlib-1.5.0",
"kotlin-stdlib-1.5.10",
"kotlin-stdlib-1.5.20",
@@ -156,11 +139,10 @@ use_repo(
"kotlin-stdlib-1.9.20-Beta",
"kotlin-stdlib-2.0.0-RC1",
"kotlin-stdlib-2.0.20-Beta2",
"kotlin-stdlib-2.1.0-Beta1",
)
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
go_sdk.download(version = "1.23.1")
go_sdk.download(version = "1.22.2")
go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
go_deps.from_file(go_mod = "//go/extractor:go.mod")

View File

@@ -57,6 +57,10 @@
"java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll"
],
"Model as Data Generation Java/C# - CaptureModels": [
"java/ql/src/utils/modelgenerator/internal/CaptureModels.qll",
"csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll"
],
"Sign Java/C#": [
"java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/Sign.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/Sign.qll"
@@ -352,8 +356,8 @@
"python/ql/test/library-tests/dataflow/model-summaries/InlineTaintTest.ext.yml",
"python/ql/test/library-tests/dataflow/model-summaries/NormalDataflowTest.ext.yml"
],
"Diagnostics.qll": [
"ruby/ql/lib/codeql/ruby/Diagnostics.qll",
"rust/ql/lib/codeql/rust/Diagnostics.qll"
"shared tree-sitter extractor cargo.toml": [
"shared/tree-sitter-extractor/Cargo.toml",
"ruby/extractor/codeql-extractor-fake-crate/Cargo.toml"
]
}

View File

@@ -1,17 +0,0 @@
class Expr extends @expr {
string toString() { none() }
}
class Location extends @location_expr {
string toString() { none() }
}
predicate isExprWithNewBuiltin(Expr expr) {
exists(int kind | exprs(expr, kind, _) | 385 <= kind and kind <= 388)
}
from Expr expr, int kind, int kind_new, Location location
where
exprs(expr, kind, location) and
if isExprWithNewBuiltin(expr) then kind_new = 1 else kind_new = kind
select expr, kind_new, location

View File

@@ -1,14 +0,0 @@
class Expr extends @expr {
string toString() { none() }
}
class Type extends @type {
string toString() { none() }
}
from Expr expr, Type type, int kind
where
sizeof_bind(expr, type) and
exprs(expr, kind, _) and
(kind = 93 or kind = 94)
select expr, type

View File

@@ -1,4 +0,0 @@
description: Add new builtin operations
compatibility: partial
exprs.rel: run exprs.qlo
sizeof_bind.rel: run sizeof_bind.qlo

View File

@@ -1,32 +0,0 @@
/*
* Approach: replace conversion expressions of kind 389 (= @c11_generic) by
* conversion expressions of kind 12 (= @parexpr), i.e., a `ParenthesisExpr`,
* and drop the relation which its child expressions, which are just syntactic
* sugar. Parenthesis expressions are equally benign as C11 _Generic expressions,
* and behave similarly in the context of the IR.
*/
class Expr extends @expr {
string toString() { none() }
}
class Location extends @location {
string toString() { none() }
}
class ExprParent extends @exprparent {
string toString() { none() }
}
query predicate new_exprs(Expr expr, int new_kind, Location loc) {
exists(int kind | exprs(expr, kind, loc) | if kind = 389 then new_kind = 12 else new_kind = kind)
}
query predicate new_exprparents(Expr expr, int index, ExprParent expr_parent) {
exprparents(expr, index, expr_parent) and
(
not expr_parent instanceof @expr
or
exists(int kind | exprs(expr_parent.(Expr), kind, _) | kind != 389)
)
}

View File

@@ -1,4 +0,0 @@
description: Expose C11 _Generics
compatibility: partial
exprs.rel: run downgrades.ql new_exprs
exprparents.rel: run downgrades.ql new_exprparents

View File

@@ -1,3 +0,0 @@
description: description: Support explicit(bool) specifiers
compatibility: full
explicit_specifier_exprs.rel: delete

View File

@@ -1,15 +0,0 @@
class Expr extends @expr {
string toString() { none() }
}
class Location extends @location_expr {
string toString() { none() }
}
predicate isExprRequires(Expr expr) { exists(int kind | exprs(expr, kind, _) | kind = 390) }
from Expr expr, int kind, int kind_new, Location location
where
exprs(expr, kind, location) and
if isExprRequires(expr) then kind_new = 1 else kind_new = kind
select expr, kind_new, location

View File

@@ -1,3 +0,0 @@
description: Add requires expr
compatibility: partial
exprs.rel: run exprs.qlo

View File

@@ -1,18 +0,0 @@
class Function extends @function {
string toString() { none() }
}
class Type extends @type {
string toString() { none() }
}
class Variable extends @variable {
string toString() { none() }
}
from Function func, Type traits, Variable handle, Variable promise
where
coroutine(func, traits) and
coroutine_placeholder_variable(handle, 1, func) and
coroutine_placeholder_variable(promise, 2, func)
select func, traits, handle, promise

View File

@@ -1,4 +0,0 @@
description: Improve handling of coroutine placeholder variables
compatibility: full
coroutine.rel: run coroutine.qlo
coroutine_placeholder_variable.rel: delete

View File

@@ -1,3 +0,0 @@
description: Add relation between deduction guides and class templates
compatibility: full
deduction_guide_for_class.rel: delete

View File

@@ -1,17 +0,0 @@
class Expr extends @expr {
string toString() { none() }
}
class Location extends @location_expr {
string toString() { none() }
}
predicate isExprRequirement(Expr expr) {
exists(int kind | exprs(expr, kind, _) | kind = [391, 392, 393])
}
from Expr expr, int kind, int kind_new, Location location
where
exprs(expr, kind, location) and
if isExprRequirement(expr) then kind_new = 1 else kind_new = kind
select expr, kind_new, location

View File

@@ -1,17 +0,0 @@
class Parameter extends @parameter {
string toString() { none() }
}
class ParameterizedElement extends @parameterized_element {
string toString() { none() }
}
class Type extends @type {
string toString() { none() }
}
from Parameter param, ParameterizedElement pe, int index, Type type
where
params(param, pe, index, type) and
not pe instanceof @requires_expr
select param, pe, index, type

View File

@@ -1,5 +0,0 @@
description: Support C++20 requires expressions
compatibility: partial
compound_requirement_is_noexcept.rel: delete
exprs.rel: run exprs.qlo
params.rel: run params.qlo

View File

@@ -1,61 +1,3 @@
## 2.0.2
### Minor Analysis Improvements
* Added taint flow model for `fopen` and related functions.
* The `SimpleRangeAnalysis` library (`semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis`) now generates more precise ranges for calls to `fgetc` and `getc`.
## 2.0.1
No user-facing changes.
## 2.0.0
### Breaking Changes
* Deleted many deprecated taint-tracking configurations based on `TaintTracking::Configuration`.
* Deleted many deprecated dataflow configurations based on `DataFlow::Configuration`.
* Deleted the deprecated `hasQualifiedName` and `isDefined` predicates from the `Declaration` class, use `hasGlobalName` and `hasDefinition` respectively instead.
* Deleted the `getFullSignature` predicate from the `Function` class, use `getIdentityString(Declaration)` from `semmle.code.cpp.Print` instead.
* Deleted the deprecated `freeCall` predicate from `Alloc.qll`. Use `DeallocationExpr` instead.
* Deleted the deprecated `explorationLimit` predicate from `DataFlow::Configuration`, use `FlowExploration<explorationLimit>` instead.
* Deleted the deprecated `getFieldExpr` predicate from `ClassAggregateLiteral`, use `getAFieldExpr` instead.
* Deleted the deprecated `getElementExpr` predicate from `ArrayOrVectorAggregateLiteral`, use `getAnElementExpr` instead.
### New Features
* Added a class `C11GenericExpr` to represent C11 generic selection expressions. The generic selection is represented as a `Conversion` on the expression that will be selected.
* Added subclasses of `BuiltInOperations` for the `__is_scoped_enum`, `__is_trivially_equality_comparable`, and `__is_trivially_relocatable` builtin operations.
* Added a subclass of `Expr` for `__datasizeof` expressions.
### Minor Analysis Improvements
* Added a data flow model for `swap` member functions, which were previously modeled as taint tracking functions. This change improves the precision of queries where flow through `swap` member functions might affect the results.
* Added a data flow model for `realloc`-like functions, which were previously modeled as a taint tracking functions. This change improves the precision of queries where flow through `realloc`-like functions might affect the results.
## 1.4.2
No user-facing changes.
## 1.4.1
No user-facing changes.
## 1.4.0
### New Features
* A `getTemplateClass` predicate was added to the `DeductionGuide` class to get the class template for which the deduction guide is a guide.
* An `isExplicit` predicate was added to the `Function` class that determines whether the function was declared as explicit.
* A `getExplicitExpr` predicate was added to the `Function` class that yields the constant boolean expression (if any) that conditionally determines whether the function is explicit.
* A `isDestroyingDeleteDeallocation` predicate was added to the `NewOrNewArrayExpr` and `DeleteOrDeleteArrayExpr` classes to indicate whether the deallocation function is a destroying delete.
### Minor Analysis Improvements
* The controlling expression of a `constexpr if` is now always recognized as an unevaluated expression.
* Improved performance of alias analysis of large function bodies. In rare cases, alerts that depend on alias analysis of large function bodies may be affected.
* A `UsingEnumDeclarationEntry` class has been added for C++ `using enum` declarations. As part of this, synthesized `UsingDeclarationEntry`s are no longer emitted for individual enumerators of the referenced enumeration.
## 1.3.0
### New Features

View File

@@ -1,4 +0,0 @@
---
category: feature
---
* Added classes `RequiresExpr`, `SimpleRequirementExpr`, `TypeRequirementExpr`, `CompoundRequirementExpr`, and `NestedRequirementExpr` to represent C++20 requires expressions and the simple, type, compound, and nested requirements that can occur in `requires` expressions.

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* A `isDestroyingDeleteDeallocation` predicate was added to the `NewOrNewArrayExpr` and `DeleteOrDeleteArrayExpr` classes to indicate whether the deallocation function is a destroying delete.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* A `UsingEnumDeclarationEntry` class has been added for C++ `using enum` declarations. As part of this, synthesized `UsingDeclarationEntry`s are no longer emitted for individual enumerators of the referenced enumeration.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Improved performance of alias analysis of large function bodies. In rare cases, alerts that depend on alias analysis of large function bodies may be affected.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* The function call target resolution algorithm has been improved to resolve more calls through function pointers. As a result, dataflow queries may have more results.

View File

@@ -1,4 +0,0 @@
---
category: feature
---
* Added a new predicate `DataFlow::getARuntimeTarget` for getting a function that may be invoked by a `Call` expression. Unlike `Call.getTarget` this new predicate may also resolve function pointers.

View File

@@ -1,14 +0,0 @@
## 1.4.0
### New Features
* A `getTemplateClass` predicate was added to the `DeductionGuide` class to get the class template for which the deduction guide is a guide.
* An `isExplicit` predicate was added to the `Function` class that determines whether the function was declared as explicit.
* A `getExplicitExpr` predicate was added to the `Function` class that yields the constant boolean expression (if any) that conditionally determines whether the function is explicit.
* A `isDestroyingDeleteDeallocation` predicate was added to the `NewOrNewArrayExpr` and `DeleteOrDeleteArrayExpr` classes to indicate whether the deallocation function is a destroying delete.
### Minor Analysis Improvements
* The controlling expression of a `constexpr if` is now always recognized as an unevaluated expression.
* Improved performance of alias analysis of large function bodies. In rare cases, alerts that depend on alias analysis of large function bodies may be affected.
* A `UsingEnumDeclarationEntry` class has been added for C++ `using enum` declarations. As part of this, synthesized `UsingDeclarationEntry`s are no longer emitted for individual enumerators of the referenced enumeration.

View File

@@ -1,3 +0,0 @@
## 1.4.1
No user-facing changes.

View File

@@ -1,3 +0,0 @@
## 1.4.2
No user-facing changes.

View File

@@ -1,23 +0,0 @@
## 2.0.0
### Breaking Changes
* Deleted many deprecated taint-tracking configurations based on `TaintTracking::Configuration`.
* Deleted many deprecated dataflow configurations based on `DataFlow::Configuration`.
* Deleted the deprecated `hasQualifiedName` and `isDefined` predicates from the `Declaration` class, use `hasGlobalName` and `hasDefinition` respectively instead.
* Deleted the `getFullSignature` predicate from the `Function` class, use `getIdentityString(Declaration)` from `semmle.code.cpp.Print` instead.
* Deleted the deprecated `freeCall` predicate from `Alloc.qll`. Use `DeallocationExpr` instead.
* Deleted the deprecated `explorationLimit` predicate from `DataFlow::Configuration`, use `FlowExploration<explorationLimit>` instead.
* Deleted the deprecated `getFieldExpr` predicate from `ClassAggregateLiteral`, use `getAFieldExpr` instead.
* Deleted the deprecated `getElementExpr` predicate from `ArrayOrVectorAggregateLiteral`, use `getAnElementExpr` instead.
### New Features
* Added a class `C11GenericExpr` to represent C11 generic selection expressions. The generic selection is represented as a `Conversion` on the expression that will be selected.
* Added subclasses of `BuiltInOperations` for the `__is_scoped_enum`, `__is_trivially_equality_comparable`, and `__is_trivially_relocatable` builtin operations.
* Added a subclass of `Expr` for `__datasizeof` expressions.
### Minor Analysis Improvements
* Added a data flow model for `swap` member functions, which were previously modeled as taint tracking functions. This change improves the precision of queries where flow through `swap` member functions might affect the results.
* Added a data flow model for `realloc`-like functions, which were previously modeled as a taint tracking functions. This change improves the precision of queries where flow through `realloc`-like functions might affect the results.

View File

@@ -1,3 +0,0 @@
## 2.0.1
No user-facing changes.

View File

@@ -1,6 +0,0 @@
## 2.0.2
### Minor Analysis Improvements
* Added taint flow model for `fopen` and related functions.
* The `SimpleRangeAnalysis` library (`semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis`) now generates more precise ranges for calls to `fgetc` and `getc`.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 2.0.2
lastReleaseVersion: 1.3.0

View File

@@ -17,7 +17,6 @@ import semmle.code.cpp.File
import semmle.code.cpp.Linkage
import semmle.code.cpp.Location
import semmle.code.cpp.Compilation
import semmle.code.cpp.Concept
import semmle.code.cpp.Element
import semmle.code.cpp.Namespace
import semmle.code.cpp.Specifier

View File

@@ -36,6 +36,16 @@ module PrivateCleartextWrite {
}
}
deprecated class WriteConfig extends TaintTracking::Configuration {
WriteConfig() { this = "Write configuration" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
}
private module WriteConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }

View File

@@ -1,14 +0,0 @@
extensions:
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*1]", "ReturnValue", "taint", "manual"]
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*2]", "ReturnValue", "taint", "manual"]
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*3]", "ReturnValue", "taint", "manual"]
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*4]", "ReturnValue", "taint", "manual"]
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*5]", "ReturnValue", "taint", "manual"]
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*6]", "ReturnValue", "taint", "manual"]
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*7]", "ReturnValue", "taint", "manual"]
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*8]", "ReturnValue", "taint", "manual"]

View File

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

View File

@@ -1,161 +0,0 @@
/**
* Provides classes for working with C++ concepts.
*/
import semmle.code.cpp.exprs.Expr
/**
* A C++ requires expression.
*
* For example, with `T` and `U` template parameters:
* ```cpp
* requires (T x, U y) { x + y; };
* ```
*/
class RequiresExpr extends Expr, @requires_expr {
override string toString() {
if exists(this.getAParameter())
then result = "requires(...) { ... }"
else result = "requires { ... }"
}
override string getAPrimaryQlClass() { result = "RequiresExpr" }
/**
* Gets a requirement in this requires expression.
*/
RequirementExpr getARequirement() { result = this.getAChild() }
/**
* Gets the nth requirement in this requires expression.
*/
RequirementExpr getRequirement(int n) { result = this.getChild(n) }
/**
* Gets the number of requirements in this requires expression.
*/
int getNumberOfRequirements() { result = count(this.getARequirement()) }
/**
* Gets a parameter of this requires expression, if any.
*/
Parameter getAParameter() { result.getRequiresExpr() = underlyingElement(this) }
/**
* Gets the the nth parameter of this requires expression.
*/
Parameter getParameter(int n) {
result.getRequiresExpr() = underlyingElement(this) and result.getIndex() = n
}
/**
* Gets the number of parameters of this requires expression.
*/
int getNumberOfParameters() { result = count(this.getAParameter()) }
}
/**
* A C++ requirement in a requires expression.
*/
class RequirementExpr extends Expr { }
/**
* A C++ simple requirement in a requires expression.
*
* For example, if:
* ```cpp
* requires(T x, U y) { x + y; };
* ```
* with `T` and `U` template parameters, then `x + y;` is a simple requirement.
*/
class SimpleRequirementExpr extends RequirementExpr {
SimpleRequirementExpr() {
this.getParent() instanceof RequiresExpr and
not this instanceof TypeRequirementExpr and
not this instanceof CompoundRequirementExpr and
not this instanceof NestedRequirementExpr
}
override string getAPrimaryQlClass() { result = "SimpleRequirementExpr" }
}
/**
* A C++ type requirement in a requires expression.
*
* For example, if:
* ```cpp
* requires { typename T::a_field; };
* ```
* with `T` a template parameter, then `typename T::a_field;` is a type requirement.
*/
class TypeRequirementExpr extends RequirementExpr, TypeName {
TypeRequirementExpr() { this.getParent() instanceof RequiresExpr }
override string getAPrimaryQlClass() { result = "TypeRequirementExpr" }
}
/**
* A C++ compound requirement in a requires expression.
*
* For example, if:
* ```cpp
* requires(T x) { { x } noexcept -> std::same_as<int>; };
* ```
* with `T` a template parameter, then `{ x } noexcept -> std::same_as<int>;` is
* a compound requirement.
*/
class CompoundRequirementExpr extends RequirementExpr, @compound_requirement {
override string toString() {
if exists(this.getReturnTypeRequirement())
then result = "{ ... } -> ..."
else result = "{ ... }"
}
override string getAPrimaryQlClass() { result = "CompoundRequirementExpr" }
/**
* Gets the expression from the compound requirement.
*/
Expr getExpr() { result = this.getChild(0) }
/**
* Gets the return type requirement from the compound requirement, if any.
*/
Expr getReturnTypeRequirement() { result = this.getChild(1) }
/**
* Holds if the expression from the compound requirement must not be
* potentially throwing.
*/
predicate isNoExcept() { compound_requirement_is_noexcept(underlyingElement(this)) }
}
/**
* A C++ nested requirement in a requires expression.
*
* For example, if:
* ```cpp
* requires { requires std::is_same<T, int>::value; };
* ```
* with `T` a template parameter, then `requires std::is_same<T, int>::value;` is
* a nested requirement.
*/
class NestedRequirementExpr extends Expr, @nested_requirement {
override string toString() { result = "requires ..." }
override string getAPrimaryQlClass() { result = "NestedRequirementExpr" }
/**
* Gets the constraint from the nested requirement.
*/
Expr getConstraint() { result = this.getChild(0) }
}
/**
* A C++ concept id expression.
*/
class ConceptIdExpr extends RequirementExpr, @concept_id {
override string toString() { result = "concept<...>" }
override string getAPrimaryQlClass() { result = "ConceptIdExpr" }
}

View File

@@ -60,6 +60,18 @@ class Declaration extends Locatable, @declaration {
*/
string getQualifiedName() { result = underlyingElement(this).(Q::Declaration).getQualifiedName() }
/**
* DEPRECATED: Prefer `hasGlobalName` or the 2-argument or 3-argument
* `hasQualifiedName` predicates. To get the exact same results as this
* predicate in all edge cases, use `getQualifiedName()`.
*
* Holds if this declaration has the fully-qualified name `qualifiedName`.
* See `getQualifiedName`.
*/
deprecated predicate hasQualifiedName(string qualifiedName) {
this.getQualifiedName() = qualifiedName
}
/**
* Holds if this declaration has a fully-qualified name with a name-space
* component of `namespaceQualifier`, a declaring type of `typeQualifier`,
@@ -173,6 +185,9 @@ class Declaration extends Locatable, @declaration {
/** Holds if the declaration has a definition. */
predicate hasDefinition() { exists(this.getDefinition()) }
/** DEPRECATED: Use `hasDefinition` instead. */
deprecated predicate isDefined() { this.hasDefinition() }
/** Gets the preferred location of this declaration, if any. */
override Location getLocation() { none() }

View File

@@ -129,7 +129,7 @@ class Element extends ElementBase {
* or certain kinds of `Statement`.
*/
Element getParentScope() {
// result instanceof Class
// result instanceof class
exists(Declaration m |
m = this and
result = m.getDeclaringType() and
@@ -138,40 +138,31 @@ class Element extends ElementBase {
or
exists(TemplateClass tc | this = tc.getATemplateArgument() and result = tc)
or
// result instanceof Namespace
// result instanceof namespace
exists(Namespace n | result = n and n.getADeclaration() = this)
or
exists(FriendDecl d, Namespace n | this = d and n.getADeclaration() = d and result = n)
or
exists(Namespace n | this = n and result = n.getParentNamespace())
or
// result instanceof Stmt
// result instanceof stmt
exists(LocalVariable v |
this = v and
exists(DeclStmt ds | ds.getADeclaration() = v and result = ds.getParent())
)
or
exists(Parameter p |
this = p and
(
result = p.getFunction() or
result = p.getCatchBlock().getParent().(Handler).getParent().(TryStmt).getParent() or
result = p.getRequiresExpr().getEnclosingStmt().getParent()
)
)
exists(Parameter p | this = p and result = p.getFunction())
or
exists(GlobalVariable g, Namespace n | this = g and n.getADeclaration() = g and result = n)
or
exists(TemplateVariable tv | this = tv.getATemplateArgument() and result = tv)
or
exists(EnumConstant e | this = e and result = e.getDeclaringEnum())
or
// result instanceof Block|Function
// result instanceof block|function
exists(BlockStmt b | this = b and blockscope(unresolveElement(b), unresolveElement(result)))
or
exists(TemplateFunction tf | this = tf.getATemplateArgument() and result = tf)
or
// result instanceof Stmt
// result instanceof stmt
exists(ControlStructure s | this = s and result = s.getParent())
or
using_container(unresolveElement(result), underlyingElement(this))

View File

@@ -30,6 +30,46 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
override string getName() { functions(underlyingElement(this), result, _) }
/**
* DEPRECATED: Use `getIdentityString(Declaration)` from `semmle.code.cpp.Print` instead.
* Gets the full signature of this function, including return type, parameter
* types, and template arguments.
*
* For example, in the following code:
* ```
* template<typename T> T min(T x, T y);
* int z = min(5, 7);
* ```
* The full signature of the function called on the last line would be
* `min<int>(int, int) -> int`, and the full signature of the uninstantiated
* template on the first line would be `min<T>(T, T) -> T`.
*/
deprecated string getFullSignature() {
exists(string name, string templateArgs, string args |
result = name + templateArgs + args + " -> " + this.getType().toString() and
name = this.getQualifiedName() and
(
if exists(this.getATemplateArgument())
then
templateArgs =
"<" +
concat(int i |
exists(this.getTemplateArgument(i))
|
this.getTemplateArgument(i).toString(), ", " order by i
) + ">"
else templateArgs = ""
) and
args =
"(" +
concat(int i |
exists(this.getParameter(i))
|
this.getParameter(i).getType().toString(), ", " order by i
) + ")"
)
}
/** Gets a specifier of this function. */
override Specifier getASpecifier() {
funspecifiers(underlyingElement(this), unresolveElement(result)) or
@@ -118,26 +158,6 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
*/
predicate isConsteval() { this.hasSpecifier("is_consteval") }
/**
* Holds if this function is declared to be `explicit`.
*/
predicate isExplicit() { this.hasSpecifier("explicit") }
/**
* Gets the constant expression that determines whether the function is explicit.
*
* For example, for the following code the result is the expression `sizeof(T) == 1`:
* ```
* template<typename T> struct C {
* explicit(sizeof(T) == 1)
* C(const T);
* };
* ```
*/
Expr getExplicitExpr() {
explicit_specifier_exprs(underlyingElement(this), unresolveElement(result))
}
/**
* Holds if this function is declared with `__attribute__((naked))` or
* `__declspec(naked)`.
@@ -500,17 +520,6 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
* Gets the nearest enclosing AccessHolder.
*/
override AccessHolder getEnclosingAccessHolder() { result = this.getDeclaringType() }
/**
* Holds if this function has extraction errors that create an `ErrorExpr`.
*/
predicate hasErrors() {
exists(ErrorExpr e |
e.getEnclosingFunction() = this and
// Exclude the first allocator call argument because it is always extracted as `ErrorExpr`.
not exists(NewOrNewArrayExpr new | e = new.getAllocatorCall().getArgument(0))
)
}
}
pragma[noinline]
@@ -662,8 +671,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
/**
* Holds if this declaration is an implicit function declaration, that is,
* where a function is used before it is declared (under older C standards,
* or when there were parse errors).
* where a function is used before it is declared (under older C standards).
*/
predicate isImplicit() { fun_implicit(underlyingElement(this)) }
@@ -890,11 +898,4 @@ class UserDefinedLiteral extends Function {
*/
class DeductionGuide extends Function {
DeductionGuide() { functions(underlyingElement(this), _, 8) }
/**
* Gets the class template for which this is a deduction guide.
*/
TemplateClass getTemplateClass() {
deduction_guide_for_class(underlyingElement(this), unresolveElement(result))
}
}

View File

@@ -7,8 +7,8 @@ import semmle.code.cpp.Declaration
private import semmle.code.cpp.internal.ResolveClass
/**
* A C/C++ function parameter, catch block parameter, or requires expression parameter.
* For example the function parameter `p` and the catch block parameter `e` in the following
* A C/C++ function parameter or catch block parameter. For example the
* function parameter `p` and the catch block parameter `e` in the following
* code:
* ```
* void myFunction(int p) {
@@ -20,8 +20,8 @@ private import semmle.code.cpp.internal.ResolveClass
* }
* ```
*
* For catch block parameters and expression , there is a one-to-one
* correspondence between the `Parameter` and its `VariableDeclarationEntry`.
* For catch block parameters, there is a one-to-one correspondence between
* the `Parameter` and its `ParameterDeclarationEntry`.
*
* For function parameters, there is a one-to-many relationship between
* `Parameter` and `ParameterDeclarationEntry`, because one function can
@@ -73,8 +73,7 @@ class Parameter extends LocalScopeVariable, @parameter {
}
private VariableDeclarationEntry getANamedDeclarationEntry() {
result = this.getAnEffectiveDeclarationEntry() and
exists(string name | var_decls(unresolveElement(result), _, _, name, _) | name != "")
result = this.getAnEffectiveDeclarationEntry() and result.getName() != ""
}
/**
@@ -119,12 +118,6 @@ class Parameter extends LocalScopeVariable, @parameter {
*/
BlockStmt getCatchBlock() { params(underlyingElement(this), unresolveElement(result), _, _) }
/**
* Gets the requires expression to which the parameter belongs, if it is a
* requires expression parameter.
*/
RequiresExpr getRequiresExpr() { params(underlyingElement(this), unresolveElement(result), _, _) }
/**
* Gets the zero-based index of this parameter.
*

View File

@@ -80,10 +80,6 @@ private Declaration getAnEnclosingDeclaration(Locatable ast) {
or
result = ast.(Parameter).getFunction()
or
result = ast.(Parameter).getCatchBlock().getEnclosingFunction()
or
result = ast.(Parameter).getRequiresExpr().getEnclosingFunction()
or
result = ast.(Expr).getEnclosingDeclaration()
or
result = ast.(Initializer).getDeclaration()
@@ -103,10 +99,7 @@ private newtype TPrintAstNode =
stmt.getADeclarationEntry() = entry and
shouldPrintDeclaration(stmt.getEnclosingFunction())
} or
TFunctionParametersNode(Function func) { shouldPrintDeclaration(func) } or
TRequiresExprParametersNode(RequiresExpr req) {
shouldPrintDeclaration(getAnEnclosingDeclaration(req))
} or
TParametersNode(Function func) { shouldPrintDeclaration(func) } or
TConstructorInitializersNode(Constructor ctor) {
ctor.hasEntryPoint() and
shouldPrintDeclaration(ctor)
@@ -293,6 +286,9 @@ abstract class BaseAstNode extends PrintAstNode {
* Gets the AST represented by this node.
*/
final Locatable getAst() { result = ast }
/** DEPRECATED: Alias for getAst */
deprecated Locatable getAST() { result = this.getAst() }
}
/**
@@ -310,14 +306,14 @@ class ExprNode extends AstNode {
ExprNode() { expr = ast }
override PrintAstNode getChildInternal(int childIndex) {
result.(AstNode).getAst() = expr.getChild(childIndex)
override AstNode getChildInternal(int childIndex) {
result.getAst() = expr.getChild(childIndex)
or
childIndex = max(int index | exists(expr.getChild(index)) or index = 0) + 1 and
result.(AstNode).getAst() = expr.(ConditionDeclExpr).getInitializingExpr()
result.getAst() = expr.(ConditionDeclExpr).getInitializingExpr()
or
exists(int destructorIndex |
result.(AstNode).getAst() = expr.getImplicitDestructorCall(destructorIndex) and
result.getAst() = expr.getImplicitDestructorCall(destructorIndex) and
childIndex = destructorIndex + max(int index | exists(expr.getChild(index)) or index = 0) + 2
)
}
@@ -336,8 +332,7 @@ class ExprNode extends AstNode {
}
override string getChildAccessorPredicateInternal(int childIndex) {
result =
getChildAccessorWithoutConversions(ast, this.getChildInternal(childIndex).(AstNode).getAst())
result = getChildAccessorWithoutConversions(ast, this.getChildInternal(childIndex).getAst())
}
/**
@@ -390,21 +385,6 @@ class CastNode extends ConversionNode {
}
}
/**
* A node representing a `C11GenericExpr`.
*/
class C11GenericNode extends ConversionNode {
C11GenericExpr generic;
C11GenericNode() { generic = conv }
override AstNode getChildInternal(int childIndex) {
result = super.getChildInternal(childIndex - count(generic.getAChild()))
or
result.getAst() = generic.getChild(childIndex)
}
}
/**
* A node representing a `StmtExpr`.
*/
@@ -417,26 +397,6 @@ class StmtExprNode extends ExprNode {
}
}
/**
* A node representing a `RequiresExpr`
*/
class RequiresExprNode extends ExprNode {
override RequiresExpr expr;
override PrintAstNode getChildInternal(int childIndex) {
result = super.getChildInternal(childIndex)
or
childIndex = -1 and
result.(RequiresExprParametersNode).getRequiresExpr() = expr
}
override string getChildAccessorPredicateInternal(int childIndex) {
result = super.getChildAccessorPredicateInternal(childIndex)
or
childIndex = -1 and result = "<params>"
}
}
/**
* A node representing a `DeclarationEntry`.
*/
@@ -538,22 +498,6 @@ class DeclStmtNode extends StmtNode {
}
}
/**
* A node representing a `Handler`.
*/
class HandlerNode extends ChildStmtNode {
Handler handler;
HandlerNode() { handler = stmt }
override BaseAstNode getChildInternal(int childIndex) {
result = super.getChildInternal(childIndex)
or
childIndex = -1 and
result.getAst() = handler.getParameter()
}
}
/**
* A node representing a `Parameter`.
*/
@@ -596,10 +540,10 @@ class InitializerNode extends AstNode {
/**
* A node representing the parameters of a `Function`.
*/
class FunctionParametersNode extends PrintAstNode, TFunctionParametersNode {
class ParametersNode extends PrintAstNode, TParametersNode {
Function func;
FunctionParametersNode() { this = TFunctionParametersNode(func) }
ParametersNode() { this = TParametersNode(func) }
final override string toString() { result = "" }
@@ -620,33 +564,6 @@ class FunctionParametersNode extends PrintAstNode, TFunctionParametersNode {
final Function getFunction() { result = func }
}
/**
* A node representing the parameters of a `RequiresExpr`.
*/
class RequiresExprParametersNode extends PrintAstNode, TRequiresExprParametersNode {
RequiresExpr req;
RequiresExprParametersNode() { this = TRequiresExprParametersNode(req) }
final override string toString() { result = "" }
final override Location getLocation() { result = getRepresentativeLocation(req) }
override AstNode getChildInternal(int childIndex) {
result.getAst() = req.getParameter(childIndex)
}
override string getChildAccessorPredicateInternal(int childIndex) {
exists(this.getChildInternal(childIndex)) and
result = "getParameter(" + childIndex.toString() + ")"
}
/**
* Gets the `RequiresExpr` for which this node represents the parameters.
*/
final RequiresExpr getRequiresExpr() { result = req }
}
/**
* A node representing the initializer list of a `Constructor`.
*/
@@ -750,7 +667,7 @@ class FunctionNode extends FunctionOrGlobalOrNamespaceVariableNode {
override PrintAstNode getChildInternal(int childIndex) {
childIndex = 0 and
result.(FunctionParametersNode).getFunction() = func
result.(ParametersNode).getFunction() = func
or
childIndex = 1 and
result.(ConstructorInitializersNode).getConstructor() = func
@@ -825,8 +742,6 @@ private predicate namedStmtChildPredicates(Locatable s, Element e, string pred)
or
s.(ConstexprIfStmt).getElse() = e and pred = "getElse()"
or
s.(Handler).getParameter() = e and pred = "getParameter()"
or
s.(IfStmt).getInitialization() = e and pred = "getInitialization()"
or
s.(IfStmt).getCondition() = e and pred = "getCondition()"
@@ -945,15 +860,6 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
or
expr.(BuiltInVarArgsStart).getLastNamedParameter() = ele and pred = "getLastNamedParameter()"
or
expr.(C11GenericExpr).getControllingExpr() = ele and pred = "getControllingExpr()"
or
exists(int n |
expr.(C11GenericExpr).getAssociationType(n) = ele.(TypeName).getType() and
pred = "getAssociationType(" + n + ")"
or
expr.(C11GenericExpr).getAssociationExpr(n) = ele and pred = "getAssociationExpr(" + n + ")"
)
or
expr.(Call).getQualifier() = ele and pred = "getQualifier()"
or
exists(int n | expr.(Call).getArgument(n) = ele and pred = "getArgument(" + n.toString() + ")")
@@ -974,11 +880,6 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
or
expr.(CommaExpr).getRightOperand() = ele and pred = "getRightOperand()"
or
expr.(CompoundRequirementExpr).getExpr() = ele and pred = "getExpr()"
or
expr.(CompoundRequirementExpr).getReturnTypeRequirement() = ele and
pred = "getReturnTypeRequirement()"
or
expr.(ConditionDeclExpr).getVariableAccess() = ele and pred = "getVariableAccess()"
or
expr.(ConstructorFieldInit).getExpr() = ele and pred = "getExpr()"
@@ -999,8 +900,6 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
or
expr.(LambdaExpression).getInitializer() = ele and pred = "getInitializer()"
or
expr.(NestedRequirementExpr).getConstraint() = ele and pred = "getConstraint()"
or
expr.(NewOrNewArrayExpr).getAllocatorCall() = ele and pred = "getAllocatorCall()"
or
expr.(NewOrNewArrayExpr).getAlignmentArgument() = ele and pred = "getAlignmentArgument()"
@@ -1040,11 +939,6 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
or
expr.(UnaryOperation).getOperand() = ele and pred = "getOperand()"
or
exists(int n |
expr.(RequiresExpr).getRequirement(n) = ele and
pred = "getRequirement(" + n + ")"
)
or
expr.(SizeofExprOperator).getExprOperand() = ele and pred = "getExprOperand()"
or
expr.(StmtExpr).getStmt() = ele and pred = "getStmt()"

View File

@@ -39,8 +39,8 @@ class Type extends Locatable, @type {
/**
* Gets a specifier of this type, recursively looking through `typedef` and
* `decltype`. For example, in the context of `typedef const int *restrict t`,
* the type `volatile t` has specifiers `volatile` and `restrict` but not
* `decltype`. For example, in the context of `typedef const int *restrict
* t`, the type `volatile t` has specifiers `volatile` and `restrict` but not
* `const` since the `const` is attached to the type being pointed to rather
* than the pointer itself.
*/

View File

@@ -241,10 +241,6 @@ class VariableDeclarationEntry extends DeclarationEntry, @var_decl {
name != "" and result = name
or
name = "" and result = this.getVariable().(LocalVariable).getName()
or
name = "" and
not this instanceof ParameterDeclarationEntry and
result = this.getVariable().(Parameter).getName()
)
)
}
@@ -299,11 +295,19 @@ class ParameterDeclarationEntry extends VariableDeclarationEntry {
private string getAnonymousParameterDescription() {
not exists(this.getName()) and
exists(string anon |
anon = "(unnamed parameter " + this.getIndex().toString() + ")" and
exists(string idx |
idx =
((this.getIndex() + 1).toString() + "th")
.replaceAll("1th", "1st")
.replaceAll("2th", "2nd")
.replaceAll("3th", "3rd")
.replaceAll("11st", "11th")
.replaceAll("12nd", "12th")
.replaceAll("13rd", "13th") and
if exists(this.getCanonicalName())
then result = "declaration of " + this.getCanonicalName() + " as " + anon
else result = "declaration of " + anon
then
result = "declaration of " + this.getCanonicalName() + " as anonymous " + idx + " parameter"
else result = "declaration of " + idx + " parameter"
)
}
@@ -405,18 +409,11 @@ class LocalVariable extends LocalScopeVariable, @localvariable {
exists(ConditionDeclExpr e | e.getVariable() = this and e.getEnclosingFunction() = result)
or
orphaned_variables(underlyingElement(this), unresolveElement(result))
or
coroutine_placeholder_variable(underlyingElement(this), _, unresolveElement(result))
}
override predicate isStatic() {
super.isStatic() or orphaned_variables(underlyingElement(this), _)
}
override predicate isCompilerGenerated() {
super.isCompilerGenerated() or
coroutine_placeholder_variable(underlyingElement(this), _, _)
}
}
/**

View File

@@ -7,6 +7,15 @@ import semmle.code.cpp.models.interfaces.Deallocation
*/
predicate freeFunction(Function f, int argNum) { argNum = f.(DeallocationFunction).getFreedArg() }
/**
* A call to a library routine that frees memory.
*
* DEPRECATED: Use `DeallocationExpr` instead (this also includes `delete` expressions).
*/
deprecated predicate freeCall(FunctionCall fc, Expr arg) {
arg = fc.(DeallocationExpr).getFreedExpr()
}
/**
* Is e some kind of allocation or deallocation (`new`, `alloc`, `realloc`, `delete`, `free` etc)?
*/

View File

@@ -57,7 +57,7 @@ private int isSource(Expr bufferExpr, Element why) {
exists(Type bufferType |
// buffer is the address of a variable
why = bufferExpr.(AddressOfExpr).getAddressable() and
bufferType = why.(Variable).getUnspecifiedType() and
bufferType = why.(Variable).getType() and
result = bufferType.getSize() and
not bufferType instanceof ReferenceType and
not any(Union u).getAMemberVariable() = why

View File

@@ -435,17 +435,12 @@ private predicate elementSpec(
}
/** Gets the fully templated version of `f`. */
private Function getFullyTemplatedFunction(Function f) {
private Function getFullyTemplatedMemberFunction(Function f) {
not f.isFromUninstantiatedTemplate(_) and
(
exists(Class c, Class templateClass, int i |
c.isConstructedFrom(templateClass) and
f = c.getAMember(i) and
result = templateClass.getCanonicalMember(i)
)
or
not exists(f.getDeclaringType()) and
f.isConstructedFrom(result)
exists(Class c, Class templateClass, int i |
c.isConstructedFrom(templateClass) and
f = c.getAMember(i) and
result = templateClass.getCanonicalMember(i)
)
}
@@ -469,14 +464,14 @@ string getParameterTypeWithoutTemplateArguments(Function f, int n) {
*/
private string getTypeNameWithoutFunctionTemplates(Function f, int n, int remaining) {
exists(Function templateFunction |
templateFunction = getFullyTemplatedFunction(f) and
templateFunction = getFullyTemplatedMemberFunction(f) and
remaining = templateFunction.getNumberOfTemplateArguments() and
result = getParameterTypeWithoutTemplateArguments(templateFunction, n)
)
or
exists(string mid, TemplateParameter tp, Function templateFunction |
mid = getTypeNameWithoutFunctionTemplates(f, n, remaining + 1) and
templateFunction = getFullyTemplatedFunction(f) and
templateFunction = getFullyTemplatedMemberFunction(f) and
tp = templateFunction.getTemplateArgument(remaining) and
result = mid.replaceAll(tp.getName(), "func:" + remaining.toString())
)
@@ -487,18 +482,12 @@ private string getTypeNameWithoutFunctionTemplates(Function f, int n, int remain
* with `class:N` (where `N` is the index of the template).
*/
private string getTypeNameWithoutClassTemplates(Function f, int n, int remaining) {
// If there is a declaring type then we start by expanding the function templates
exists(Class template |
f.getDeclaringType().isConstructedFrom(template) and
remaining = template.getNumberOfTemplateArguments() and
result = getTypeNameWithoutFunctionTemplates(f, n, 0)
)
or
// If there is no declaring type we're done after expanding the function templates
not exists(f.getDeclaringType()) and
remaining = 0 and
result = getTypeNameWithoutFunctionTemplates(f, n, 0)
or
exists(string mid, TemplateParameter tp, Class template |
mid = getTypeNameWithoutClassTemplates(f, n, remaining + 1) and
f.getDeclaringType().isConstructedFrom(template) and
@@ -581,6 +570,38 @@ private string getSignatureWithoutFunctionTemplateNames(
)
}
private string paramsStringPart(Function c, int i) {
not c.isFromUninstantiatedTemplate(_) and
(
i = -1 and result = "(" and exists(c)
or
exists(int n, string p | getParameterTypeName(c, n) = p |
i = 2 * n and result = p
or
i = 2 * n - 1 and result = "," and n != 0
)
or
i = 2 * c.getNumberOfParameters() and result = ")"
)
}
/**
* Gets a parenthesized string containing all parameter types of this callable, separated by a comma.
*
* Returns the empty string if the callable has no parameters.
* Parameter types are represented by their type erasure.
*/
cached
private string paramsString(Function c) {
result = concat(int i | | paramsStringPart(c, i) order by i)
}
bindingset[func]
private predicate matchesSignature(Function func, string signature) {
signature = "" or
paramsString(func) = signature
}
/**
* Holds if `elementSpec(_, type, _, name, signature, _)` holds and
* - `typeArgs` represents the named template parameters supplied to `type`, and
@@ -729,17 +750,17 @@ private predicate elementSpecWithArguments0(
/**
* Holds if `elementSpec(namespace, type, subtypes, name, signature, _)` and
* `func`'s signature matches `signature`.
* `method`'s signature matches `signature`.
*
* `signature` may contain template parameter names that are bound by `type` and `name`.
*/
pragma[nomagic]
private predicate elementSpecMatchesSignature(
Function func, string namespace, string type, boolean subtypes, string name, string signature
Function method, string namespace, string type, boolean subtypes, string name, string signature
) {
elementSpec(namespace, pragma[only_bind_into](type), subtypes, pragma[only_bind_into](name),
pragma[only_bind_into](signature), _) and
signatureMatches(func, signature, type, name, 0)
signatureMatches(method, signature, type, name, 0)
}
/**
@@ -755,22 +776,13 @@ private predicate hasClassAndName(Class classWithMethod, Function method, string
)
}
bindingset[name]
pragma[inline_late]
private predicate funcHasQualifiedName(Function func, string namespace, string name) {
exists(string nameWithoutArgs |
parseAngles(name, nameWithoutArgs, _, "") and
func.hasQualifiedName(namespace, nameWithoutArgs)
)
}
/**
* Holds if `namedClass` is in namespace `namespace` and has
* name `type` (excluding any template parameters).
*/
bindingset[type, namespace]
pragma[inline_late]
private predicate classHasQualifiedName(Class namedClass, string namespace, string type) {
private predicate hasQualifiedName(Class namedClass, string namespace, string type) {
exists(string typeWithoutArgs |
parseAngles(type, typeWithoutArgs, _, "") and
namedClass.hasQualifiedName(namespace, typeWithoutArgs)
@@ -792,16 +804,15 @@ private Element interpretElement0(
string namespace, string type, boolean subtypes, string name, string signature
) {
(
// Non-member functions
elementSpec(namespace, type, subtypes, name, signature, _) and
subtypes = false and
type = "" and
(
elementSpecMatchesSignature(result, namespace, type, subtypes, name, signature)
or
signature = "" and
elementSpec(namespace, type, subtypes, name, "", _) and
funcHasQualifiedName(result, namespace, name)
// Non-member functions
exists(Function func |
func.hasQualifiedName(namespace, name) and
type = "" and
matchesSignature(func, signature) and
subtypes = false and
not exists(func.getDeclaringType()) and
result = func
)
or
// Member functions
@@ -814,7 +825,7 @@ private Element interpretElement0(
elementSpec(namespace, type, subtypes, name, "", _) and
hasClassAndName(classWithMethod, result, name)
) and
classHasQualifiedName(namedClass, namespace, type) and
hasQualifiedName(namedClass, namespace, type) and
(
// member declared in the named type or a subtype of it
subtypes = true and
@@ -953,3 +964,21 @@ private class SummarizedCallableAdapter extends SummarizedCallable {
interpretSummary(this, _, _, _, provenance, _)
}
}
// adapter class for converting Mad neutrals to `NeutralCallable`s
private class NeutralCallableAdapter extends NeutralCallable {
string kind;
string provenance_;
NeutralCallableAdapter() {
// Neutral models have not been implemented for CPP.
none() and
exists(this) and
exists(kind) and
exists(provenance_)
}
override string getKind() { result = kind }
override predicate hasProvenance(Provenance provenance) { provenance = provenance_ }
}

View File

@@ -168,6 +168,14 @@ abstract deprecated class Configuration extends string {
*/
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* DEPRECATED: Use `FlowExploration<explorationLimit>` instead.
*
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
* measured in approximate number of interprocedural steps.
*/
deprecated int explorationLimit() { none() }
/**
* Holds if hidden nodes should be included in the data flow graph.
*
@@ -282,9 +290,15 @@ deprecated private module Config implements FullStateConfigSig {
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
predicate sourceGrouping(Node source, string sourceGroup) {
any(Configuration config).sourceGrouping(source, sourceGroup)
}
predicate observeDiffInformedIncrementalMode() { none() }
predicate sinkGrouping(Node sink, string sinkGroup) {
any(Configuration config).sinkGrouping(sink, sinkGroup)
}
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
}
deprecated private import Impl<Config> as I

View File

@@ -168,6 +168,14 @@ abstract deprecated class Configuration extends string {
*/
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* DEPRECATED: Use `FlowExploration<explorationLimit>` instead.
*
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
* measured in approximate number of interprocedural steps.
*/
deprecated int explorationLimit() { none() }
/**
* Holds if hidden nodes should be included in the data flow graph.
*
@@ -282,9 +290,15 @@ deprecated private module Config implements FullStateConfigSig {
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
predicate sourceGrouping(Node source, string sourceGroup) {
any(Configuration config).sourceGrouping(source, sourceGroup)
}
predicate observeDiffInformedIncrementalMode() { none() }
predicate sinkGrouping(Node sink, string sinkGroup) {
any(Configuration config).sinkGrouping(sink, sinkGroup)
}
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
}
deprecated private import Impl<Config> as I

View File

@@ -168,6 +168,14 @@ abstract deprecated class Configuration extends string {
*/
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* DEPRECATED: Use `FlowExploration<explorationLimit>` instead.
*
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
* measured in approximate number of interprocedural steps.
*/
deprecated int explorationLimit() { none() }
/**
* Holds if hidden nodes should be included in the data flow graph.
*
@@ -282,9 +290,15 @@ deprecated private module Config implements FullStateConfigSig {
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
predicate sourceGrouping(Node source, string sourceGroup) {
any(Configuration config).sourceGrouping(source, sourceGroup)
}
predicate observeDiffInformedIncrementalMode() { none() }
predicate sinkGrouping(Node sink, string sinkGroup) {
any(Configuration config).sinkGrouping(sink, sinkGroup)
}
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
}
deprecated private import Impl<Config> as I

View File

@@ -168,6 +168,14 @@ abstract deprecated class Configuration extends string {
*/
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* DEPRECATED: Use `FlowExploration<explorationLimit>` instead.
*
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
* measured in approximate number of interprocedural steps.
*/
deprecated int explorationLimit() { none() }
/**
* Holds if hidden nodes should be included in the data flow graph.
*
@@ -282,9 +290,15 @@ deprecated private module Config implements FullStateConfigSig {
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
predicate sourceGrouping(Node source, string sourceGroup) {
any(Configuration config).sourceGrouping(source, sourceGroup)
}
predicate observeDiffInformedIncrementalMode() { none() }
predicate sinkGrouping(Node sink, string sinkGroup) {
any(Configuration config).sinkGrouping(sink, sinkGroup)
}
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
}
deprecated private import Impl<Config> as I

View File

@@ -168,6 +168,14 @@ abstract deprecated class Configuration extends string {
*/
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* DEPRECATED: Use `FlowExploration<explorationLimit>` instead.
*
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
* measured in approximate number of interprocedural steps.
*/
deprecated int explorationLimit() { none() }
/**
* Holds if hidden nodes should be included in the data flow graph.
*
@@ -282,9 +290,15 @@ deprecated private module Config implements FullStateConfigSig {
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
predicate sourceGrouping(Node source, string sourceGroup) {
any(Configuration config).sourceGrouping(source, sourceGroup)
}
predicate observeDiffInformedIncrementalMode() { none() }
predicate sinkGrouping(Node sink, string sinkGroup) {
any(Configuration config).sinkGrouping(sink, sinkGroup)
}
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
}
deprecated private import Impl<Config> as I

View File

@@ -1885,59 +1885,3 @@ class BuiltInOperationIsWinInterface extends BuiltInOperation, @iswininterface {
override string getAPrimaryQlClass() { result = "BuiltInOperationIsWinInterface" }
}
/**
* A C++ `__is_trivially_equality_comparable` built-in operation.
*
* Returns `true` if comparing two objects of type `_Tp` is equivalent to
* comparing their object representations.
*
* ```
* template<typename _Tp>
* struct is_trivially_equality_comparable
* : public integral_constant<bool, __is_trivially_equality_comparable(_Tp)>
* {};
* ```
*/
class BuiltInOperationIsTriviallyEqualityComparable extends BuiltInOperation,
@istriviallyequalitycomparable
{
override string toString() { result = "__is_trivially_equality_comparable" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyEqualityComparable" }
}
/**
* A C++ `__is_scoped_enum` built-in operation (used by some implementations
* of the `<type_traits>` header).
*
* Returns `true` if a type is a scoped enum.
* ```
* template<typename _Tp>
* constexpr bool is_scoped_enum = __is_scoped_enum(_Tp);
* ```
*/
class BuiltInOperationIsScopedEnum extends BuiltInOperation, @isscopedenum {
override string toString() { result = "__is_scoped_enum" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsScopedEnum" }
}
/**
* A C++ `__is_trivially_relocatable` built-in operation.
*
* Returns `true` if moving an object of type `_Tp` is equivalent to
* copying the underlying bytes.
*
* ```
* template<typename _Tp>
* struct is_trivially_relocatable
* : public integral_constant<bool, __is_trivially_relocatable(_Tp)>
* {};
* ```
*/
class BuiltInOperationIsTriviallyRelocatable extends BuiltInOperation, @istriviallyrelocatable {
override string toString() { result = "__is_trivially_relocatable" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyRelocatable" }
}

View File

@@ -791,53 +791,6 @@ class AlignofTypeOperator extends AlignofOperator {
override string toString() { result = "alignof(" + this.getTypeOperand().getName() + ")" }
}
/**
* A C++ `__datasizeof` expression (used by some implementations
* of the `<type_traits>` header).
*
* The `__datasizeof` expression behaves identically to `sizeof` except
* that the result ignores tail padding.
*/
class DatasizeofOperator extends Expr, @datasizeof {
override int getPrecedence() { result = 16 }
}
/**
* A C++ `__datasizeof` expression whose operand is an expression.
*/
class DatasizeofExprOperator extends DatasizeofOperator {
DatasizeofExprOperator() { exists(this.getChild(0)) }
override string getAPrimaryQlClass() { result = "DatasizeofExprOperator" }
/** Gets the contained expression. */
Expr getExprOperand() { result = this.getChild(0) }
override string toString() { result = "__datasizeof(<expr>)" }
override predicate mayBeImpure() { this.getExprOperand().mayBeImpure() }
override predicate mayBeGloballyImpure() { this.getExprOperand().mayBeGloballyImpure() }
}
/**
* A C++ `__datasizeof` expression whose operand is a type name.
*/
class DatasizeofTypeOperator extends DatasizeofOperator {
DatasizeofTypeOperator() { sizeof_bind(underlyingElement(this), _) }
override string getAPrimaryQlClass() { result = "DatasizeofTypeOperator" }
/** Gets the contained type. */
Type getTypeOperand() { sizeof_bind(underlyingElement(this), unresolveElement(result)) }
override string toString() { result = "__datasizeof(" + this.getTypeOperand().getName() + ")" }
override predicate mayBeImpure() { none() }
override predicate mayBeGloballyImpure() { none() }
}
/**
* A C/C++ array to pointer conversion.
*

View File

@@ -304,15 +304,9 @@ class Expr extends StmtParent, @expr {
e instanceof NoExceptExpr
or
e instanceof AlignofOperator
or
e instanceof DatasizeofOperator
)
or
exists(Decltype d | d.getExpr() = this.getParentWithConversions*())
or
exists(ConstexprIfStmt constIf |
constIf.getControllingExpr() = this.getParentWithConversions*()
)
}
/**
@@ -632,106 +626,6 @@ class ParenthesisExpr extends Conversion, @parexpr {
override string getAPrimaryQlClass() { result = "ParenthesisExpr" }
}
/**
* A node representing a C11 `_Generic` selection expression.
*
* For example:
* ```
* _Generic(e, int: "int", default: "unknown")
* ```
*/
class C11GenericExpr extends Conversion, @c11_generic {
int associationCount;
C11GenericExpr() { associationCount = (count(this.getAChild()) - 1) / 2 }
override string toString() { result = "_Generic" }
override string getAPrimaryQlClass() { result = "C11GenericExpr" }
/**
* Gets the controlling expression of the generic selection.
*
* For example, for
* ```
* _Generic(e, int: "a", default: "b")
* ```
* the result is `e`.
*/
Expr getControllingExpr() { result = this.getChild(0) }
/**
* Gets the type of the `n`th element in the association list of the generic selection.
*
* For example, for
* ```
* _Generic(e, int: "a", default: "b")
* ```
* the type of the 0th element is `int`. In the case of the default element the
* type will an instance of `VoidType`.
*/
Type getAssociationType(int n) {
n in [0 .. associationCount - 1] and
result = this.getChild(n * 2 + 1).(TypeName).getType()
}
/**
* Gets the type of an element in the association list of the generic selection.
*/
Type getAnAssociationType() { result = this.getAssociationType(_) }
/**
* Gets the expression of the `n`th element in the association list of
* the generic selection.
*
* For example, for
* ```
* _Generic(e, int: "a", default: "b")
* ```
* the expression for 0th element is `"a"`, and the expression for the
* 1st element is `"b"`. For the selected expression, this predicate
* will yield a `ReuseExpr`, such that
* ```
* this.getAssociationExpr(n).(ReuseExpr).getReusedExpr() = this.getExpr()
* ```
*/
Expr getAssociationExpr(int n) {
n in [0 .. associationCount - 1] and
result = this.getChild(n * 2 + 2)
}
/**
* Gets the expression of an element in the association list of the generic selection.
*/
Expr getAnAssociationExpr() { result = this.getAssociationExpr(_) }
/**
* Holds if the `n`th element of the association list of the generic selection is the
* default element.
*
* For example, for
* ```
* _Generic(e, int: "a", default: "b")
* ```
* this holds for 1.
*/
predicate isDefaultAssociation(int n) { this.getAssociationType(n) instanceof VoidType }
/**
* Holds if the `n`th element of the association list of the generic selection is the
* one whose expression was selected.
*
* For example, with `e` of type `int` and
* ```
* _Generic(e, int: "a", default: "b")
* ```
* this holds for 0.
*/
predicate isSelectedAssociation(int n) {
this.getAssociationExpr(n).(ReuseExpr).getReusedExpr() = this.getExpr()
}
}
/**
* A C/C++ expression that could not be resolved, or that can no longer be
* represented due to a database upgrade or downgrade.
@@ -768,8 +662,6 @@ class AssumeExpr extends Expr, @assume {
/**
* A C/C++ comma expression.
*
* For example:
* ```
* int c = compute1(), compute2(), resulting_value;
* ```

View File

@@ -195,6 +195,17 @@ class ClassAggregateLiteral extends AggregateLiteral {
*/
Expr getAFieldExpr(Field field) { result = this.getFieldExpr(field, _) }
/**
* DEPRECATED: Use `getAFieldExpr` instead.
*
* Gets the expression within the aggregate literal that is used to initialize
* field `field`, if present.
*
* This predicate may have multiple results since a field can be initialized
* multiple times in the same initializer.
*/
deprecated Expr getFieldExpr(Field field) { result = this.getFieldExpr(field, _) }
/**
* Gets the expression within the aggregate literal that is used to initialize
* field `field`, if present. The expression is the `position`'th entry in the
@@ -289,6 +300,17 @@ class ArrayOrVectorAggregateLiteral extends AggregateLiteral {
*/
Expr getAnElementExpr(int elementIndex) { result = this.getElementExpr(elementIndex, _) }
/**
* DEPRECATED: Use `getAnElementExpr` instead.
*
* Gets the expression within the aggregate literal that is used to initialize
* element `elementIndex`, if present.
*
* This predicate may have multiple results since an element can be initialized
* multiple times in the same initializer.
*/
deprecated Expr getElementExpr(int elementIndex) { result = this.getElementExpr(elementIndex, _) }
/**
* Gets the expression within the aggregate literal that is used to initialize
* element `elementIndex`, if present. The expression is the `position`'th entry

View File

@@ -181,7 +181,12 @@ class VariableDeclarationEntry extends @var_decl {
string getName() { var_decls(this, _, _, result, _) and result != "" }
}
class Parameter extends LocalScopeVariable, @parameter { }
class Parameter extends LocalScopeVariable, @parameter {
@functionorblock function;
int index;
Parameter() { params(this, function, index, _) }
}
class GlobalOrNamespaceVariable extends Variable, @globalvariable { }

View File

@@ -168,6 +168,14 @@ abstract deprecated class Configuration extends string {
*/
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* DEPRECATED: Use `FlowExploration<explorationLimit>` instead.
*
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
* measured in approximate number of interprocedural steps.
*/
deprecated int explorationLimit() { none() }
/**
* Holds if hidden nodes should be included in the data flow graph.
*
@@ -282,9 +290,15 @@ deprecated private module Config implements FullStateConfigSig {
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
predicate sourceGrouping(Node source, string sourceGroup) {
any(Configuration config).sourceGrouping(source, sourceGroup)
}
predicate observeDiffInformedIncrementalMode() { none() }
predicate sinkGrouping(Node sink, string sinkGroup) {
any(Configuration config).sinkGrouping(sink, sinkGroup)
}
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
}
deprecated private import Impl<Config> as I

View File

@@ -168,6 +168,14 @@ abstract deprecated class Configuration extends string {
*/
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* DEPRECATED: Use `FlowExploration<explorationLimit>` instead.
*
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
* measured in approximate number of interprocedural steps.
*/
deprecated int explorationLimit() { none() }
/**
* Holds if hidden nodes should be included in the data flow graph.
*
@@ -282,9 +290,15 @@ deprecated private module Config implements FullStateConfigSig {
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
predicate sourceGrouping(Node source, string sourceGroup) {
any(Configuration config).sourceGrouping(source, sourceGroup)
}
predicate observeDiffInformedIncrementalMode() { none() }
predicate sinkGrouping(Node sink, string sinkGroup) {
any(Configuration config).sinkGrouping(sink, sinkGroup)
}
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
}
deprecated private import Impl<Config> as I

View File

@@ -168,6 +168,14 @@ abstract deprecated class Configuration extends string {
*/
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* DEPRECATED: Use `FlowExploration<explorationLimit>` instead.
*
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
* measured in approximate number of interprocedural steps.
*/
deprecated int explorationLimit() { none() }
/**
* Holds if hidden nodes should be included in the data flow graph.
*
@@ -282,9 +290,15 @@ deprecated private module Config implements FullStateConfigSig {
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
predicate sourceGrouping(Node source, string sourceGroup) {
any(Configuration config).sourceGrouping(source, sourceGroup)
}
predicate observeDiffInformedIncrementalMode() { none() }
predicate sinkGrouping(Node sink, string sinkGroup) {
any(Configuration config).sinkGrouping(sink, sinkGroup)
}
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
}
deprecated private import Impl<Config> as I

View File

@@ -168,6 +168,14 @@ abstract deprecated class Configuration extends string {
*/
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
/**
* DEPRECATED: Use `FlowExploration<explorationLimit>` instead.
*
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
* measured in approximate number of interprocedural steps.
*/
deprecated int explorationLimit() { none() }
/**
* Holds if hidden nodes should be included in the data flow graph.
*
@@ -282,9 +290,15 @@ deprecated private module Config implements FullStateConfigSig {
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
predicate sourceGrouping(Node source, string sourceGroup) {
any(Configuration config).sourceGrouping(source, sourceGroup)
}
predicate observeDiffInformedIncrementalMode() { none() }
predicate sinkGrouping(Node sink, string sinkGroup) {
any(Configuration config).sinkGrouping(sink, sinkGroup)
}
predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() }
}
deprecated private import Impl<Config> as I

View File

@@ -1328,10 +1328,7 @@ predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c)
/** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
(
call.(SummaryCall).getReceiver() = receiver.(FlowSummaryNode).getSummaryNode() or
call.asCallInstruction().getCallTargetOperand() = receiver.asOperand()
) and
call.(SummaryCall).getReceiver() = receiver.(FlowSummaryNode).getSummaryNode() and
exists(kind)
}

View File

@@ -17,7 +17,6 @@ private import SsaInternals as Ssa
private import DataFlowImplCommon as DataFlowImplCommon
private import codeql.util.Unit
private import Node0ToString
private import DataFlowDispatch as DataFlowDispatch
import ExprNodes
/**
@@ -2498,16 +2497,3 @@ class AdditionalCallTarget extends Unit {
*/
abstract Declaration viableTarget(Call call);
}
/**
* Gets a function that may be called by `call`.
*
* Note that `call` may be a call to a function pointer expression.
*/
Function getARuntimeTarget(Call call) {
exists(DataFlowCall dfCall | dfCall.asCallInstruction().getUnconvertedResultExpression() = call |
result = DataFlowDispatch::viableCallable(dfCall).asSourceCallable()
or
result = DataFlowImplCommon::viableCallableLambda(dfCall, _).asSourceCallable()
)
}

View File

@@ -546,7 +546,7 @@ module ProductFlow {
Flow1::PathGraph::edges(pred1, succ1, _, _) and
exists(ReturnKindExt returnKind |
succ1.getNode() = returnKind.getAnOutNode(call) and
returnKind = getParamReturnPosition(_, pred1.asParameterReturnNode()).getKind()
paramReturnNode(_, pred1.asParameterReturnNode(), _, returnKind)
)
}
@@ -574,7 +574,7 @@ module ProductFlow {
Flow2::PathGraph::edges(pred2, succ2, _, _) and
exists(ReturnKindExt returnKind |
succ2.getNode() = returnKind.getAnOutNode(call) and
returnKind = getParamReturnPosition(_, pred2.asParameterReturnNode()).getKind()
paramReturnNode(_, pred2.asParameterReturnNode(), _, returnKind)
)
}

View File

@@ -50,6 +50,9 @@ abstract private class AbstractIRVariable extends TIRVariable {
*/
abstract Language::AST getAst();
/** DEPRECATED: Alias for getAst */
deprecated Language::AST getAST() { result = this.getAst() }
/**
* Gets an identifier string for the variable. This identifier is unique
* within the function.
@@ -93,6 +96,9 @@ class IRUserVariable extends AbstractIRVariable, TIRUserVariable {
final override Language::AST getAst() { result = var }
/** DEPRECATED: Alias for getAst */
deprecated override Language::AST getAST() { result = this.getAst() }
final override string getUniqueId() {
result = this.getVariable().toString() + " " + this.getVariable().getLocation().toString()
}
@@ -157,6 +163,9 @@ abstract private class AbstractIRGeneratedVariable extends AbstractIRVariable {
final override Language::AST getAst() { result = ast }
/** DEPRECATED: Alias for getAst */
deprecated override Language::AST getAST() { result = this.getAst() }
override string toString() { result = this.getBaseString() + this.getLocationString() }
override string getUniqueId() { none() }

View File

@@ -6,112 +6,6 @@
* uses, however, it is better to write a query that imports `PrintIR.qll`, extends
* `PrintIRConfiguration`, and overrides `shouldPrintDeclaration()` to select a subset of declarations
* to dump.
*
* Anatomy of a printed IR instruction
*
* An instruction:
*
* ```
* # 2281| v2281_19(void) = Call[~String] : func:r2281_18, this:r2281_17
* ```
*
* The prefix `# 2281|` specifies that this instruction was generated by the C++ source code on line 2281.
* Scrolling up in the printed output, one will eventually find the name of the file to which the line
* belongs.
*
* `v2281_19(void)` is the result of the instruction. Here, `v` means this is a void result or operand (so
* there should be no later uses of the result; see below for other possible values). The `2281_19` is a
* unique ID for the result. This is usually just the line number plus a small integer suffix to make it
* unique within the function. The type of the result is `void`. In this case, it is `void`, because
* `~String` returns `void`. The type of the result is usually just the name of the appropriate C++ type,
* but it will sometimes be a type like `glval<int>`, which means result holds a glvalue, which at the
* IR level works like a pointer. In other words, in the source code the type was `int`, but it is really
* more like an `int*`. We see this, for example, in `x = y;`, where `x` is a glvalue.
*
* `Call` is the opcode of the instruction. Common opcodes include:
*
* * Arithmetic operations: `Add`, `Sub`, `Mul`, etc.
* * Memory access operations: `Load`, `Store`.
* * Function calls: `Call`.
* * Literals: `Constant`.
* * Variable addresses: `VariableAddress`.
* * Function entry points: `EnterFunction`.
* * Return from a function: `Return`, `ReturnVoid`. Note that the value being returned is set separately by a
* `Store` to a special `#return` variable.
* * Stack unwinding for C++ function that throw and where the exception escapes the function: `Unwind`.
* * Common exit point for `Unwind` and `Return`: `ExitFunction`.
* * SSA-related opcodes: `Phi`, `Chi`.
*
* `[~String]` denotes additional information. The information might be present earlier in the IR, as is the case
* for `Call`, where it is the name of the called function. This is also the case for `Load` and `Store`, where it
* is the name of the variable that loaded or stored (if known). In the case of `Constant`, `FieldAddress`, and
* `VariableAddress`, the information between brackets does not occur earlier.
*
* `func:r2281_18` and `this:r28281_17` are the operands of the instruction. The `func:` prefix denotes the operand
* that holds the address of the called function. The `this:` prefix denotes the argument to the special `this`
* parameter of an instance member function. `r2281_18`, `r2281_17` are the unique IDs of the operands. Each of these
* matches the ID of a previously seen result, showing where that value came from. The `r` means that these are
* "register" operands (see below).
*
* Result and operand kinds:
*
* Every result and operand is one of these three kinds:
*
* * `r` "register". These operands are not stored in any particular memory location. We can think of them as
* temporary values created during the evaluation of an expression. A register operand almost always has one
* use, often in the same block as its definition.
* * `m` "memory". These operands represents accesses to a specific memory location. The location could be a
* local variable, a global variable, a field of an object, an element of an array, or any memory that we happen
* to have a pointer to. These only occur as the result of a `Store`, the source operand of a `Load` or on the
* SSA instructions (`Phi`, `Chi`).
* * `v` "void". Really just a register operand, but we mark register operands of type void with this special prefix
* so we know that there is no actual value there.
*
* Branches in the IR:
*
* The IR is divided into basic blocks. At the end of each block, there are one or more edges showing the possible
* control flow successors of the block.
*
* ```
* # 44| v44_3(void) = ConditionalBranch : r44_2
* #-----| False -> Block 4
* #-----| True -> Block 3
* ```
* Here we have a block that ends with a conditional branch. The two edges show where the control flows to depending
* on whether the condition is true or false.
*
* SSA instructions:
*
* We use `Phi` instructions in SSA to create a single definition for a variable that might be assigned on multiple
* control flow paths. The `Phi` instruction merges the potential values of that variable from each predecessor edge,
* and the resulting definition is then used wherever that variable is accessed later on.
*
* When dealing with aliased memory, we use the `Chi` instruction to create a single definition for memory that might
* or might not have been updated by a store, depending on the actual address that was written to. For example, take:
*
* ```cpp
* int x = 5;
* int y = 7;
* int* p = condition ? &x : &y;
* *p = 6;
* return x;
* ```
*
* At the point where we store to `*p`, we do not know whether `p` points to `x` or `y`. Thus, we do not know whether
* `return x;` is going to return the value that `x` was originally initialized to (5), or whether it will return 6,
* because it was overwritten by `*p = 6;`. We insert a `Chi` instruction immediately after the store to `*p`:
*
* ```
* r2(int) = Constant[6]
* r3(int*) = <<value of p>>
* m4(int) = Store : &r3, r2 // Stores the constant 6 to *p
* m5(unknown) = Chi : total:m1, partial:m4
* ```
* The `partial:` operand represents the memory that was just stored. The `total:` operand represents the previous
* contents of all of the memory that `p` might have pointed to (in this case, both `x` and `y`). The result of the
* `Chi` represents the new contents of whatever memory the `total:` operand referred to. We usually do not know exactly
* which parts of that memory were overwritten, but it does model that any of that memory could have been modified, so
* that later instructions do not assume that the memory was unchanged.
*/
private import internal.IRInternal

View File

@@ -285,6 +285,9 @@ abstract private class MemoryLocation0 extends TMemoryLocation {
predicate isAlwaysAllocatedOnStack() { none() }
final predicate canReuseSsa() { none() }
/** DEPRECATED: Alias for canReuseSsa */
deprecated predicate canReuseSSA() { this.canReuseSsa() }
}
/**
@@ -683,13 +686,8 @@ private Overlap getExtentOverlap(MemoryLocation0 def, MemoryLocation0 use) {
def.getVirtualVariable() = use.getVirtualVariable() and
def instanceof EntireAllocationMemoryLocation and
(
// EntireAllocationMemoryLocation exactly overlaps any EntireAllocationMemoryLocation for the
// same allocation. Checking the allocation, rather than the memory location itself, ensures
// that we get the right relationship between the "must" and "may" memory locations for that
// allocation.
// Note that if one of the locations is a "may" access, the overlap will be downgraded to
// `MustTotallyOverlap` or `MayPartialOverlap` in `getOverlap()`.
use.(EntireAllocationMemoryLocation).getAnAllocation() = def.getAnAllocation() and
// EntireAllocationMemoryLocation exactly overlaps itself.
use instanceof EntireAllocationMemoryLocation and
result instanceof MustExactlyOverlap
or
not use instanceof EntireAllocationMemoryLocation and

View File

@@ -50,6 +50,9 @@ abstract private class AbstractIRVariable extends TIRVariable {
*/
abstract Language::AST getAst();
/** DEPRECATED: Alias for getAst */
deprecated Language::AST getAST() { result = this.getAst() }
/**
* Gets an identifier string for the variable. This identifier is unique
* within the function.
@@ -93,6 +96,9 @@ class IRUserVariable extends AbstractIRVariable, TIRUserVariable {
final override Language::AST getAst() { result = var }
/** DEPRECATED: Alias for getAst */
deprecated override Language::AST getAST() { result = this.getAst() }
final override string getUniqueId() {
result = this.getVariable().toString() + " " + this.getVariable().getLocation().toString()
}
@@ -157,6 +163,9 @@ abstract private class AbstractIRGeneratedVariable extends AbstractIRVariable {
final override Language::AST getAst() { result = ast }
/** DEPRECATED: Alias for getAst */
deprecated override Language::AST getAST() { result = this.getAst() }
override string toString() { result = this.getBaseString() + this.getLocationString() }
override string getUniqueId() { none() }

View File

@@ -6,112 +6,6 @@
* uses, however, it is better to write a query that imports `PrintIR.qll`, extends
* `PrintIRConfiguration`, and overrides `shouldPrintDeclaration()` to select a subset of declarations
* to dump.
*
* Anatomy of a printed IR instruction
*
* An instruction:
*
* ```
* # 2281| v2281_19(void) = Call[~String] : func:r2281_18, this:r2281_17
* ```
*
* The prefix `# 2281|` specifies that this instruction was generated by the C++ source code on line 2281.
* Scrolling up in the printed output, one will eventually find the name of the file to which the line
* belongs.
*
* `v2281_19(void)` is the result of the instruction. Here, `v` means this is a void result or operand (so
* there should be no later uses of the result; see below for other possible values). The `2281_19` is a
* unique ID for the result. This is usually just the line number plus a small integer suffix to make it
* unique within the function. The type of the result is `void`. In this case, it is `void`, because
* `~String` returns `void`. The type of the result is usually just the name of the appropriate C++ type,
* but it will sometimes be a type like `glval<int>`, which means result holds a glvalue, which at the
* IR level works like a pointer. In other words, in the source code the type was `int`, but it is really
* more like an `int*`. We see this, for example, in `x = y;`, where `x` is a glvalue.
*
* `Call` is the opcode of the instruction. Common opcodes include:
*
* * Arithmetic operations: `Add`, `Sub`, `Mul`, etc.
* * Memory access operations: `Load`, `Store`.
* * Function calls: `Call`.
* * Literals: `Constant`.
* * Variable addresses: `VariableAddress`.
* * Function entry points: `EnterFunction`.
* * Return from a function: `Return`, `ReturnVoid`. Note that the value being returned is set separately by a
* `Store` to a special `#return` variable.
* * Stack unwinding for C++ function that throw and where the exception escapes the function: `Unwind`.
* * Common exit point for `Unwind` and `Return`: `ExitFunction`.
* * SSA-related opcodes: `Phi`, `Chi`.
*
* `[~String]` denotes additional information. The information might be present earlier in the IR, as is the case
* for `Call`, where it is the name of the called function. This is also the case for `Load` and `Store`, where it
* is the name of the variable that loaded or stored (if known). In the case of `Constant`, `FieldAddress`, and
* `VariableAddress`, the information between brackets does not occur earlier.
*
* `func:r2281_18` and `this:r28281_17` are the operands of the instruction. The `func:` prefix denotes the operand
* that holds the address of the called function. The `this:` prefix denotes the argument to the special `this`
* parameter of an instance member function. `r2281_18`, `r2281_17` are the unique IDs of the operands. Each of these
* matches the ID of a previously seen result, showing where that value came from. The `r` means that these are
* "register" operands (see below).
*
* Result and operand kinds:
*
* Every result and operand is one of these three kinds:
*
* * `r` "register". These operands are not stored in any particular memory location. We can think of them as
* temporary values created during the evaluation of an expression. A register operand almost always has one
* use, often in the same block as its definition.
* * `m` "memory". These operands represents accesses to a specific memory location. The location could be a
* local variable, a global variable, a field of an object, an element of an array, or any memory that we happen
* to have a pointer to. These only occur as the result of a `Store`, the source operand of a `Load` or on the
* SSA instructions (`Phi`, `Chi`).
* * `v` "void". Really just a register operand, but we mark register operands of type void with this special prefix
* so we know that there is no actual value there.
*
* Branches in the IR:
*
* The IR is divided into basic blocks. At the end of each block, there are one or more edges showing the possible
* control flow successors of the block.
*
* ```
* # 44| v44_3(void) = ConditionalBranch : r44_2
* #-----| False -> Block 4
* #-----| True -> Block 3
* ```
* Here we have a block that ends with a conditional branch. The two edges show where the control flows to depending
* on whether the condition is true or false.
*
* SSA instructions:
*
* We use `Phi` instructions in SSA to create a single definition for a variable that might be assigned on multiple
* control flow paths. The `Phi` instruction merges the potential values of that variable from each predecessor edge,
* and the resulting definition is then used wherever that variable is accessed later on.
*
* When dealing with aliased memory, we use the `Chi` instruction to create a single definition for memory that might
* or might not have been updated by a store, depending on the actual address that was written to. For example, take:
*
* ```cpp
* int x = 5;
* int y = 7;
* int* p = condition ? &x : &y;
* *p = 6;
* return x;
* ```
*
* At the point where we store to `*p`, we do not know whether `p` points to `x` or `y`. Thus, we do not know whether
* `return x;` is going to return the value that `x` was originally initialized to (5), or whether it will return 6,
* because it was overwritten by `*p = 6;`. We insert a `Chi` instruction immediately after the store to `*p`:
*
* ```
* r2(int) = Constant[6]
* r3(int*) = <<value of p>>
* m4(int) = Store : &r3, r2 // Stores the constant 6 to *p
* m5(unknown) = Chi : total:m1, partial:m4
* ```
* The `partial:` operand represents the memory that was just stored. The `total:` operand represents the previous
* contents of all of the memory that `p` might have pointed to (in this case, both `x` and `y`). The result of the
* `Chi` represents the new contents of whatever memory the `total:` operand referred to. We usually do not know exactly
* which parts of that memory were overwritten, but it does model that any of that memory could have been modified, so
* that later instructions do not assume that the memory was unchanged.
*/
private import internal.IRInternal

View File

@@ -216,6 +216,9 @@ abstract class TranslatedSideEffects extends TranslatedElement {
final override Locatable getAst() { result = this.getExpr() }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override Declaration getFunction() { result = getEnclosingDeclaration(this.getExpr()) }
final override TranslatedElement getChild(int i) {
@@ -613,6 +616,9 @@ class TranslatedArgumentExprSideEffect extends TranslatedArgumentSideEffect,
final override Locatable getAst() { result = arg }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override Type getIndirectionType() {
result = arg.getUnspecifiedType().(DerivedType).getBaseType()
or
@@ -645,6 +651,9 @@ class TranslatedStructorQualifierSideEffect extends TranslatedArgumentSideEffect
final override Locatable getAst() { result = call }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override Type getIndirectionType() { result = call.getTarget().getDeclaringType() }
final override string getArgString() { result = "this" }
@@ -666,6 +675,9 @@ class TranslatedCallSideEffect extends TranslatedSideEffect, TTranslatedCallSide
override Locatable getAst() { result = expr }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
override Expr getPrimaryExpr() { result = expr }
override predicate sortOrder(int group, int indexInGroup) {
@@ -704,6 +716,9 @@ class TranslatedAllocationSideEffect extends TranslatedSideEffect, TTranslatedAl
override Locatable getAst() { result = expr }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
override Expr getPrimaryExpr() { result = expr }
override predicate sortOrder(int group, int indexInGroup) {

View File

@@ -29,6 +29,9 @@ abstract class TranslatedCondition extends TranslatedElement {
final override Locatable getAst() { result = expr }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final ConditionContext getConditionContext() { result = this.getParent() }
final Expr getExpr() { result = expr }

View File

@@ -45,6 +45,9 @@ abstract class TranslatedDeclarationEntry extends TranslatedElement, TTranslated
final override string toString() { result = entry.toString() }
final override Locatable getAst() { result = entry.getAst() }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
}
/**
@@ -245,6 +248,9 @@ class TranslatedStaticLocalVariableInitialization extends TranslatedElement,
final override Locatable getAst() { result = entry.getAst() }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override LocalVariable getVariable() { result = var }
final override Declaration getFunction() { result = var.getFunction() }
@@ -271,6 +277,9 @@ class TranslatedConditionDecl extends TranslatedLocalVariableDeclaration, TTrans
override Locatable getAst() { result = conditionDeclExpr }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
override Declaration getFunction() { result = getEnclosingFunction(conditionDeclExpr) }
override LocalVariable getVariable() { result = conditionDeclExpr.getVariable() }

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