Initial merge from main

This commit is contained in:
Dave Bartolomeo
2024-09-15 08:55:31 -04:00
2602 changed files with 114048 additions and 76664 deletions

View File

@@ -1 +1 @@
7.2.1 5f5d70b6c4d2fb1a889479569107f1692239e8a7

4
.github/labeler.yml vendored
View File

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

14
.github/pull_request_template.md vendored Normal file
View File

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

View File

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

View File

@@ -29,45 +29,6 @@ permissions:
contents: read contents: read
jobs: 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: unit-tests:
strategy: strategy:
matrix: matrix:

View File

@@ -65,8 +65,8 @@ jobs:
id: cache-extractor id: cache-extractor
with: with:
path: | path: |
ruby/extractor/target/release/codeql-extractor-ruby target/release/codeql-extractor-ruby
ruby/extractor/target/release/codeql-extractor-ruby.exe target/release/codeql-extractor-ruby.exe
ruby/extractor/ql/lib/codeql/ruby/ast/internal/TreeSitter.qll 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') }} 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 - uses: actions/cache@v3
@@ -75,7 +75,7 @@ jobs:
path: | path: |
~/.cargo/registry ~/.cargo/registry
~/.cargo/git ~/.cargo/git
ruby/target target
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-ruby-rust-cargo-${{ hashFiles('ruby/extractor/rust-toolchain.toml', 'ruby/extractor/**/Cargo.lock') }} key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-ruby-rust-cargo-${{ hashFiles('ruby/extractor/rust-toolchain.toml', 'ruby/extractor/**/Cargo.lock') }}
- name: Check formatting - name: Check formatting
if: steps.cache-extractor.outputs.cache-hit != 'true' if: steps.cache-extractor.outputs.cache-hit != 'true'
@@ -91,7 +91,7 @@ jobs:
run: cd extractor && cargo build --release run: cd extractor && cargo build --release
- name: Generate dbscheme - name: Generate dbscheme
if: ${{ matrix.os == 'ubuntu-latest' && steps.cache-extractor.outputs.cache-hit != 'true'}} if: ${{ matrix.os == 'ubuntu-latest' && steps.cache-extractor.outputs.cache-hit != 'true'}}
run: extractor/target/release/codeql-extractor-ruby generate --dbscheme ql/lib/ruby.dbscheme --library ql/lib/codeql/ruby/ast/internal/TreeSitter.qll run: ../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 - uses: actions/upload-artifact@v3
if: ${{ matrix.os == 'ubuntu-latest' }} if: ${{ matrix.os == 'ubuntu-latest' }}
with: with:
@@ -106,8 +106,8 @@ jobs:
with: with:
name: extractor-${{ matrix.os }} name: extractor-${{ matrix.os }}
path: | path: |
ruby/extractor/target/release/codeql-extractor-ruby target/release/codeql-extractor-ruby
ruby/extractor/target/release/codeql-extractor-ruby.exe target/release/codeql-extractor-ruby.exe
retention-days: 1 retention-days: 1
compile-queries: compile-queries:
if: github.repository_owner == 'github' if: github.repository_owner == 'github'

58
.github/workflows/rust.yml vendored Normal file
View File

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

View File

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

2610
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

14
Cargo.toml Normal file
View File

@@ -0,0 +1,14 @@
# 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",
]
[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

@@ -16,9 +16,9 @@ local_path_override(
bazel_dep(name = "platforms", version = "0.0.10") bazel_dep(name = "platforms", version = "0.0.10")
bazel_dep(name = "rules_go", version = "0.50.0") bazel_dep(name = "rules_go", version = "0.50.0")
bazel_dep(name = "rules_pkg", version = "0.10.1") bazel_dep(name = "rules_pkg", version = "1.0.1")
bazel_dep(name = "rules_nodejs", version = "6.2.0-codeql.1") bazel_dep(name = "rules_nodejs", version = "6.2.0-codeql.1")
bazel_dep(name = "rules_python", version = "0.32.2") bazel_dep(name = "rules_python", version = "0.35.0")
bazel_dep(name = "bazel_skylib", version = "1.6.1") bazel_dep(name = "bazel_skylib", version = "1.6.1")
bazel_dep(name = "abseil-cpp", version = "20240116.0", repo_name = "absl") 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 = "nlohmann_json", version = "3.11.3", repo_name = "json")
@@ -27,7 +27,7 @@ bazel_dep(name = "rules_kotlin", version = "1.9.4-codeql.1")
bazel_dep(name = "gazelle", version = "0.38.0") bazel_dep(name = "gazelle", version = "0.38.0")
bazel_dep(name = "rules_dotnet", version = "0.15.1") bazel_dep(name = "rules_dotnet", version = "0.15.1")
bazel_dep(name = "googletest", version = "1.14.0.bcr.1") bazel_dep(name = "googletest", version = "1.14.0.bcr.1")
bazel_dep(name = "rules_rust", version = "0.49.1") bazel_dep(name = "rules_rust", version = "0.50.0")
bazel_dep(name = "buildifier_prebuilt", version = "6.4.0", dev_dependency = True) bazel_dep(name = "buildifier_prebuilt", version = "6.4.0", dev_dependency = True)
@@ -47,21 +47,23 @@ cp.from_cargo(
) )
use_repo(cp, "py_deps") use_repo(cp, "py_deps")
# crate_ruby, but shortened due to windows file paths # deps for ruby+rust, but shortened due to windows file paths
r = use_extension( r = use_extension(
"@rules_rust//crate_universe:extension.bzl", "@rules_rust//crate_universe:extension.bzl",
"crate", "crate",
isolate = True, isolate = True,
) )
r.from_cargo( r.from_cargo(
name = "rd", name = "r",
cargo_lockfile = "//ruby/extractor:Cargo.lock", cargo_lockfile = "//:Cargo.lock",
manifests = [ manifests = [
"//:Cargo.toml",
"//ruby/extractor:Cargo.toml", "//ruby/extractor:Cargo.toml",
"//ruby/extractor/codeql-extractor-fake-crate:Cargo.toml", "//rust/extractor:Cargo.toml",
"//shared/tree-sitter-extractor:Cargo.toml",
], ],
) )
use_repo(r, ruby_deps = "rd") use_repo(r, tree_sitter_extractors_deps = "r")
dotnet = use_extension("@rules_dotnet//dotnet:extensions.bzl", "dotnet") dotnet = use_extension("@rules_dotnet//dotnet:extensions.bzl", "dotnet")
dotnet.toolchain(dotnet_version = "8.0.101") dotnet.toolchain(dotnet_version = "8.0.101")

View File

@@ -355,9 +355,5 @@
"Python model summaries test extension": [ "Python model summaries test extension": [
"python/ql/test/library-tests/dataflow/model-summaries/InlineTaintTest.ext.yml", "python/ql/test/library-tests/dataflow/model-summaries/InlineTaintTest.ext.yml",
"python/ql/test/library-tests/dataflow/model-summaries/NormalDataflowTest.ext.yml" "python/ql/test/library-tests/dataflow/model-summaries/NormalDataflowTest.ext.yml"
],
"shared tree-sitter extractor cargo.toml": [
"shared/tree-sitter-extractor/Cargo.toml",
"ruby/extractor/codeql-extractor-fake-crate/Cargo.toml"
] ]
} }

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

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

View File

@@ -0,0 +1,32 @@
/*
* 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)
)
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -0,0 +1,5 @@
---
category: feature
---
* 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.

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* 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.

View File

@@ -0,0 +1,11 @@
---
category: breaking
---
* 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.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* 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

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* 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.

View File

@@ -36,16 +36,6 @@ 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 { private module WriteConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source } predicate isSource(DataFlow::Node source) { source instanceof Source }

View File

@@ -60,18 +60,6 @@ class Declaration extends Locatable, @declaration {
*/ */
string getQualifiedName() { result = underlyingElement(this).(Q::Declaration).getQualifiedName() } 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 * Holds if this declaration has a fully-qualified name with a name-space
* component of `namespaceQualifier`, a declaring type of `typeQualifier`, * component of `namespaceQualifier`, a declaring type of `typeQualifier`,
@@ -185,9 +173,6 @@ class Declaration extends Locatable, @declaration {
/** Holds if the declaration has a definition. */ /** Holds if the declaration has a definition. */
predicate hasDefinition() { exists(this.getDefinition()) } predicate hasDefinition() { exists(this.getDefinition()) }
/** DEPRECATED: Use `hasDefinition` instead. */
deprecated predicate isDefined() { this.hasDefinition() }
/** Gets the preferred location of this declaration, if any. */ /** Gets the preferred location of this declaration, if any. */
override Location getLocation() { none() } override Location getLocation() { none() }

View File

@@ -30,46 +30,6 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
override string getName() { functions(underlyingElement(this), result, _) } 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. */ /** Gets a specifier of this function. */
override Specifier getASpecifier() { override Specifier getASpecifier() {
funspecifiers(underlyingElement(this), unresolveElement(result)) or funspecifiers(underlyingElement(this), unresolveElement(result)) or

View File

@@ -286,9 +286,6 @@ abstract class BaseAstNode extends PrintAstNode {
* Gets the AST represented by this node. * Gets the AST represented by this node.
*/ */
final Locatable getAst() { result = ast } final Locatable getAst() { result = ast }
/** DEPRECATED: Alias for getAst */
deprecated Locatable getAST() { result = this.getAst() }
} }
/** /**
@@ -385,6 +382,21 @@ 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`. * A node representing a `StmtExpr`.
*/ */
@@ -860,6 +872,15 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
or or
expr.(BuiltInVarArgsStart).getLastNamedParameter() = ele and pred = "getLastNamedParameter()" expr.(BuiltInVarArgsStart).getLastNamedParameter() = ele and pred = "getLastNamedParameter()"
or 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()" expr.(Call).getQualifier() = ele and pred = "getQualifier()"
or or
exists(int n | expr.(Call).getArgument(n) = ele and pred = "getArgument(" + n.toString() + ")") exists(int n | expr.(Call).getArgument(n) = ele and pred = "getArgument(" + n.toString() + ")")

View File

@@ -409,11 +409,18 @@ class LocalVariable extends LocalScopeVariable, @localvariable {
exists(ConditionDeclExpr e | e.getVariable() = this and e.getEnclosingFunction() = result) exists(ConditionDeclExpr e | e.getVariable() = this and e.getEnclosingFunction() = result)
or or
orphaned_variables(underlyingElement(this), unresolveElement(result)) orphaned_variables(underlyingElement(this), unresolveElement(result))
or
coroutine_placeholder_variable(underlyingElement(this), _, unresolveElement(result))
} }
override predicate isStatic() { override predicate isStatic() {
super.isStatic() or orphaned_variables(underlyingElement(this), _) super.isStatic() or orphaned_variables(underlyingElement(this), _)
} }
override predicate isCompilerGenerated() {
super.isCompilerGenerated() or
coroutine_placeholder_variable(underlyingElement(this), _, _)
}
} }
/** /**

View File

@@ -7,15 +7,6 @@ import semmle.code.cpp.models.interfaces.Deallocation
*/ */
predicate freeFunction(Function f, int argNum) { argNum = f.(DeallocationFunction).getFreedArg() } 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)? * 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 | exists(Type bufferType |
// buffer is the address of a variable // buffer is the address of a variable
why = bufferExpr.(AddressOfExpr).getAddressable() and why = bufferExpr.(AddressOfExpr).getAddressable() and
bufferType = why.(Variable).getType() and bufferType = why.(Variable).getUnspecifiedType() and
result = bufferType.getSize() and result = bufferType.getSize() and
not bufferType instanceof ReferenceType and not bufferType instanceof ReferenceType and
not any(Union u).getAMemberVariable() = why not any(Union u).getAMemberVariable() = why

View File

@@ -168,14 +168,6 @@ abstract deprecated class Configuration extends string {
*/ */
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } 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. * Holds if hidden nodes should be included in the data flow graph.
* *

View File

@@ -168,14 +168,6 @@ abstract deprecated class Configuration extends string {
*/ */
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } 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. * Holds if hidden nodes should be included in the data flow graph.
* *

View File

@@ -168,14 +168,6 @@ abstract deprecated class Configuration extends string {
*/ */
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } 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. * Holds if hidden nodes should be included in the data flow graph.
* *

View File

@@ -168,14 +168,6 @@ abstract deprecated class Configuration extends string {
*/ */
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } 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. * Holds if hidden nodes should be included in the data flow graph.
* *

View File

@@ -168,14 +168,6 @@ abstract deprecated class Configuration extends string {
*/ */
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } 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. * Holds if hidden nodes should be included in the data flow graph.
* *

View File

@@ -1885,3 +1885,59 @@ class BuiltInOperationIsWinInterface extends BuiltInOperation, @iswininterface {
override string getAPrimaryQlClass() { result = "BuiltInOperationIsWinInterface" } 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,6 +791,53 @@ class AlignofTypeOperator extends AlignofOperator {
override string toString() { result = "alignof(" + this.getTypeOperand().getName() + ")" } 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. * A C/C++ array to pointer conversion.
* *

View File

@@ -304,6 +304,8 @@ class Expr extends StmtParent, @expr {
e instanceof NoExceptExpr e instanceof NoExceptExpr
or or
e instanceof AlignofOperator e instanceof AlignofOperator
or
e instanceof DatasizeofOperator
) )
or or
exists(Decltype d | d.getExpr() = this.getParentWithConversions*()) exists(Decltype d | d.getExpr() = this.getParentWithConversions*())
@@ -630,6 +632,106 @@ class ParenthesisExpr extends Conversion, @parexpr {
override string getAPrimaryQlClass() { result = "ParenthesisExpr" } 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 * A C/C++ expression that could not be resolved, or that can no longer be
* represented due to a database upgrade or downgrade. * represented due to a database upgrade or downgrade.
@@ -666,6 +768,8 @@ class AssumeExpr extends Expr, @assume {
/** /**
* A C/C++ comma expression. * A C/C++ comma expression.
*
* For example:
* ``` * ```
* int c = compute1(), compute2(), resulting_value; * int c = compute1(), compute2(), resulting_value;
* ``` * ```

View File

@@ -195,17 +195,6 @@ class ClassAggregateLiteral extends AggregateLiteral {
*/ */
Expr getAFieldExpr(Field field) { result = this.getFieldExpr(field, _) } 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 * 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 * field `field`, if present. The expression is the `position`'th entry in the
@@ -300,17 +289,6 @@ class ArrayOrVectorAggregateLiteral extends AggregateLiteral {
*/ */
Expr getAnElementExpr(int elementIndex) { result = this.getElementExpr(elementIndex, _) } 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 * Gets the expression within the aggregate literal that is used to initialize
* element `elementIndex`, if present. The expression is the `position`'th entry * element `elementIndex`, if present. The expression is the `position`'th entry

View File

@@ -168,14 +168,6 @@ abstract deprecated class Configuration extends string {
*/ */
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } 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. * Holds if hidden nodes should be included in the data flow graph.
* *

View File

@@ -168,14 +168,6 @@ abstract deprecated class Configuration extends string {
*/ */
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } 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. * Holds if hidden nodes should be included in the data flow graph.
* *

View File

@@ -168,14 +168,6 @@ abstract deprecated class Configuration extends string {
*/ */
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } 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. * Holds if hidden nodes should be included in the data flow graph.
* *

View File

@@ -168,14 +168,6 @@ abstract deprecated class Configuration extends string {
*/ */
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } 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. * Holds if hidden nodes should be included in the data flow graph.
* *

View File

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

View File

@@ -285,9 +285,6 @@ abstract private class MemoryLocation0 extends TMemoryLocation {
predicate isAlwaysAllocatedOnStack() { none() } predicate isAlwaysAllocatedOnStack() { none() }
final predicate canReuseSsa() { none() } final predicate canReuseSsa() { none() }
/** DEPRECATED: Alias for canReuseSsa */
deprecated predicate canReuseSSA() { this.canReuseSsa() }
} }
/** /**

View File

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

View File

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

View File

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

View File

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

View File

@@ -128,6 +128,9 @@ private predicate ignoreExprAndDescendants(Expr expr) {
vaStartExpr.getLastNamedParameter().getFullyConverted() = expr vaStartExpr.getLastNamedParameter().getFullyConverted() = expr
) )
or or
// The children of C11 _Generic expressions are just surface syntax.
exists(C11GenericExpr generic | generic.getAChild() = expr)
or
// Do not translate implicit destructor calls for unnamed temporary variables that are // Do not translate implicit destructor calls for unnamed temporary variables that are
// conditionally constructed (until we have a mechanism for calling these only when the // conditionally constructed (until we have a mechanism for calling these only when the
// temporary's constructor was run) // temporary's constructor was run)
@@ -432,6 +435,9 @@ predicate ignoreLoad(Expr expr) {
// The load is duplicated from the right operand. // The load is duplicated from the right operand.
isExtractorFrontendVersion65OrHigher() and expr instanceof CommaExpr isExtractorFrontendVersion65OrHigher() and expr instanceof CommaExpr
or or
// The load is duplicated from the chosen expression.
expr instanceof C11GenericExpr
or
expr.(PointerDereferenceExpr).getOperand().getFullyConverted().getType().getUnspecifiedType() expr.(PointerDereferenceExpr).getOperand().getFullyConverted().getType().getUnspecifiedType()
instanceof FunctionPointerType instanceof FunctionPointerType
or or
@@ -761,7 +767,10 @@ newtype TTranslatedElement =
} or } or
// A statement // A statement
TTranslatedStmt(Stmt stmt) { translateStmt(stmt) } or TTranslatedStmt(Stmt stmt) { translateStmt(stmt) } or
// The `__except` block of a `__try __except` statement
TTranslatedMicrosoftTryExceptHandler(MicrosoftTryExceptStmt stmt) or TTranslatedMicrosoftTryExceptHandler(MicrosoftTryExceptStmt stmt) or
// The `__finally` block of a `__try __finally` statement
TTranslatedMicrosoftTryFinallyHandler(MicrosoftTryFinallyStmt stmt) or
// A function // A function
TTranslatedFunction(Function func) { translateFunction(func) } or TTranslatedFunction(Function func) { translateFunction(func) } or
// A constructor init list // A constructor init list
@@ -920,9 +929,6 @@ abstract class TranslatedElement extends TTranslatedElement {
*/ */
abstract Locatable getAst(); abstract Locatable getAst();
/** DEPRECATED: Alias for getAst */
deprecated Locatable getAST() { result = this.getAst() }
/** Gets the location of this element. */ /** Gets the location of this element. */
Location getLocation() { result = this.getAst().getLocation() } Location getLocation() { result = this.getAst().getLocation() }

View File

@@ -893,7 +893,8 @@ class TranslatedTransparentConversion extends TranslatedTransparentExpr {
( (
expr instanceof ParenthesisExpr or expr instanceof ParenthesisExpr or
expr instanceof ReferenceDereferenceExpr or expr instanceof ReferenceDereferenceExpr or
expr instanceof ReferenceToExpr expr instanceof ReferenceToExpr or
expr instanceof C11GenericExpr
) )
} }

View File

@@ -67,9 +67,6 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
final override Locatable getAst() { result = func } final override Locatable getAst() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
/** /**
* Gets the function being translated. * Gets the function being translated.
*/ */
@@ -212,8 +209,13 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
( (
// Only generate the `Unwind` instruction if there is any exception // Only generate the `Unwind` instruction if there is any exception
// handling present in the function. // handling present in the function.
exists(TryStmt try | try.getEnclosingFunction() = func) or exists(TryOrMicrosoftTryStmt try | try.getEnclosingFunction() = func)
or
exists(ThrowExpr throw | throw.getEnclosingFunction() = func) exists(ThrowExpr throw | throw.getEnclosingFunction() = func)
or
exists(FunctionCall call | call.getEnclosingFunction() = func |
getTranslatedExpr(call).(TranslatedCallExpr).mayThrowException()
)
) )
or or
tag = AliasedUseTag() and tag = AliasedUseTag() and
@@ -483,9 +485,6 @@ class TranslatedThisParameter extends TranslatedParameter, TTranslatedThisParame
final override Locatable getAst() { result = func } final override Locatable getAst() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override Function getFunction() { result = func } final override Function getFunction() { result = func }
final override predicate hasIndirection() { any() } final override predicate hasIndirection() { any() }
@@ -518,9 +517,6 @@ class TranslatedPositionalParameter extends TranslatedParameter, TTranslatedPara
final override Locatable getAst() { result = param } final override Locatable getAst() { result = param }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override Function getFunction() { final override Function getFunction() {
result = param.getFunction() or result = param.getFunction() or
result = param.getCatchBlock().getEnclosingFunction() result = param.getCatchBlock().getEnclosingFunction()
@@ -558,9 +554,6 @@ class TranslatedEllipsisParameter extends TranslatedParameter, TTranslatedEllips
final override Locatable getAst() { result = func } final override Locatable getAst() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override Function getFunction() { result = func } final override Function getFunction() { result = func }
final override predicate hasIndirection() { any() } final override predicate hasIndirection() { any() }
@@ -597,9 +590,6 @@ class TranslatedConstructorInitList extends TranslatedElement, InitializationCon
override Locatable getAst() { result = func } override Locatable getAst() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
override TranslatedElement getChild(int id) { override TranslatedElement getChild(int id) {
exists(ConstructorFieldInit fieldInit | exists(ConstructorFieldInit fieldInit |
fieldInit = func.(Constructor).getInitializer(id) and fieldInit = func.(Constructor).getInitializer(id) and
@@ -677,9 +667,6 @@ class TranslatedDestructorDestructionList extends TranslatedElement,
override Locatable getAst() { result = func } override Locatable getAst() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
override TranslatedElement getChild(int id) { override TranslatedElement getChild(int id) {
exists(DestructorFieldDestruction fieldDestruction | exists(DestructorFieldDestruction fieldDestruction |
fieldDestruction = func.(Destructor).getDestruction(id) and fieldDestruction = func.(Destructor).getDestruction(id) and
@@ -733,9 +720,6 @@ class TranslatedReadEffects extends TranslatedElement, TTranslatedReadEffects {
override Locatable getAst() { result = func } override Locatable getAst() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
override Function getFunction() { result = func } override Function getFunction() { result = func }
override string toString() { result = "read effects: " + func.toString() } override string toString() { result = "read effects: " + func.toString() }
@@ -839,9 +823,6 @@ class TranslatedThisReadEffect extends TranslatedReadEffect, TTranslatedThisRead
override Locatable getAst() { result = func } override Locatable getAst() { result = func }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
override Function getFunction() { result = func } override Function getFunction() { result = func }
override string toString() { result = "read effect: this" } override string toString() { result = "read effect: this" }
@@ -865,9 +846,6 @@ class TranslatedParameterReadEffect extends TranslatedReadEffect, TTranslatedPar
override Locatable getAst() { result = param } override Locatable getAst() { result = param }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
override string toString() { result = "read effect: " + param.toString() } override string toString() { result = "read effect: " + param.toString() }
override Function getFunction() { result = param.getFunction() } override Function getFunction() { result = param.getFunction() }

View File

@@ -153,9 +153,6 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn
final override Locatable getAst() { result = expr } final override Locatable getAst() { result = expr }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
/** /**
* Gets the expression that is doing the initialization. * Gets the expression that is doing the initialization.
*/ */
@@ -528,9 +525,6 @@ abstract class TranslatedFieldInitialization extends TranslatedElement {
final override Locatable getAst() { result = ast } final override Locatable getAst() { result = ast }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override Declaration getFunction() { final override Declaration getFunction() {
result = getEnclosingFunction(ast) or result = getEnclosingFunction(ast) or
result = getEnclosingVariable(ast).(GlobalOrNamespaceVariable) or result = getEnclosingVariable(ast).(GlobalOrNamespaceVariable) or
@@ -701,9 +695,6 @@ abstract class TranslatedElementInitialization extends TranslatedElement {
final override Locatable getAst() { result = initList } final override Locatable getAst() { result = initList }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override Declaration getFunction() { final override Declaration getFunction() {
result = getEnclosingFunction(initList) result = getEnclosingFunction(initList)
or or
@@ -912,9 +903,6 @@ abstract class TranslatedStructorCallFromStructor extends TranslatedElement, Str
final override Locatable getAst() { result = call } final override Locatable getAst() { result = call }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override TranslatedElement getChild(int id) { final override TranslatedElement getChild(int id) {
id = 0 and id = 0 and
result = this.getStructorCall() result = this.getStructorCall()
@@ -1058,9 +1046,6 @@ class TranslatedConstructorBareInit extends TranslatedElement, TTranslatedConstr
override Locatable getAst() { result = init } override Locatable getAst() { result = init }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override string toString() { result = "construct base (no constructor)" } final override string toString() { result = "construct base (no constructor)" }
override Instruction getFirstInstruction(EdgeKind kind) { override Instruction getFirstInstruction(EdgeKind kind) {

View File

@@ -79,11 +79,6 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
tag = TryExceptCompareOneBranch() and tag = TryExceptCompareOneBranch() and
opcode instanceof Opcode::ConditionalBranch and opcode instanceof Opcode::ConditionalBranch and
resultType = getVoidType() resultType = getVoidType()
or
// unwind stack
tag = UnwindTag() and
opcode instanceof Opcode::Unwind and
resultType = getVoidType()
} }
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
@@ -156,7 +151,7 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
// TODO: This is not really correct. The semantics of `EXCEPTION_CONTINUE_EXECUTION` is that // TODO: This is not really correct. The semantics of `EXCEPTION_CONTINUE_EXECUTION` is that
// we should continue execution at the point where the exception occurred. But we don't have // we should continue execution at the point where the exception occurred. But we don't have
// any instruction to model this behavior. // any instruction to model this behavior.
result = this.getInstruction(UnwindTag()) result = this.getExceptionSuccessorInstruction(any(GotoEdge edge))
or or
kind instanceof FalseEdge and kind instanceof FalseEdge and
result = this.getInstruction(TryExceptGenerateZero()) result = this.getInstruction(TryExceptGenerateZero())
@@ -176,7 +171,7 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
tag = TryExceptCompareZeroBranch() and tag = TryExceptCompareZeroBranch() and
( (
kind instanceof TrueEdge and kind instanceof TrueEdge and
result = this.getInstruction(UnwindTag()) result = this.getExceptionSuccessorInstruction(any(GotoEdge edge))
or or
kind instanceof FalseEdge and kind instanceof FalseEdge and
result = this.getInstruction(TryExceptGenerateOne()) result = this.getInstruction(TryExceptGenerateOne())
@@ -196,10 +191,6 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
tag = TryExceptCompareOneBranch() and tag = TryExceptCompareOneBranch() and
kind instanceof TrueEdge and kind instanceof TrueEdge and
result = this.getTranslatedHandler().getFirstInstruction(any(GotoEdge edge)) result = this.getTranslatedHandler().getFirstInstruction(any(GotoEdge edge))
or
// Unwind -> Parent
tag = UnwindTag() and
result = this.getParent().getChildSuccessor(this, kind)
} }
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
@@ -215,8 +206,6 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
override Instruction getALastInstructionInternal() { override Instruction getALastInstructionInternal() {
result = this.getTranslatedHandler().getALastInstruction() result = this.getTranslatedHandler().getALastInstruction()
or
result = this.getInstruction(UnwindTag())
} }
private TranslatedExpr getTranslatedCondition() { private TranslatedExpr getTranslatedCondition() {
@@ -236,6 +225,68 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
} }
final override Function getFunction() { result = tryExcept.getEnclosingFunction() } final override Function getFunction() { result = tryExcept.getEnclosingFunction() }
override Instruction getExceptionSuccessorInstruction(EdgeKind kind) {
// A throw from within a `__except` block flows to the handler for the parent of
// the `__try`.
result = this.getParent().getParent().getExceptionSuccessorInstruction(kind)
}
}
TranslatedMicrosoftTryFinallyHandler getTranslatedMicrosoftTryFinallyHandler(
MicrosoftTryFinallyStmt tryFinally
) {
result.getAst() = tryFinally.getFinally()
}
class TranslatedMicrosoftTryFinallyHandler extends TranslatedElement,
TTranslatedMicrosoftTryFinallyHandler
{
MicrosoftTryFinallyStmt tryFinally;
TranslatedMicrosoftTryFinallyHandler() {
this = TTranslatedMicrosoftTryFinallyHandler(tryFinally)
}
final override string toString() { result = tryFinally.toString() }
final override Locatable getAst() { result = tryFinally.getFinally() }
override Instruction getFirstInstruction(EdgeKind kind) {
result = this.getTranslatedFinally().getFirstInstruction(kind)
}
override Instruction getALastInstructionInternal() {
result = this.getTranslatedFinally().getALastInstruction()
}
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
child = this.getTranslatedFinally() and
result = this.getParent().getChildSuccessor(this, kind)
}
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
override TranslatedElement getChild(int id) {
id = 0 and
result = this.getTranslatedFinally()
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
none()
}
final override Function getFunction() { result = tryFinally.getEnclosingFunction() }
private TranslatedStmt getTranslatedFinally() {
result = getTranslatedStmt(tryFinally.getFinally())
}
override Instruction getExceptionSuccessorInstruction(EdgeKind kind) {
// A throw from within a `__finally` block flows to the handler for the parent of
// the `__try`.
result = this.getParent().getParent().getExceptionSuccessorInstruction(kind)
}
} }
abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt { abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt {
@@ -268,9 +319,6 @@ abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt {
final override Locatable getAst() { result = stmt } final override Locatable getAst() { result = stmt }
/** DEPRECATED: Alias for getAst */
deprecated override Locatable getAST() { result = this.getAst() }
final override Function getFunction() { result = stmt.getEnclosingFunction() } final override Function getFunction() { result = stmt.getEnclosingFunction() }
} }
@@ -586,7 +634,7 @@ class TranslatedNoValueReturnStmt extends TranslatedReturnStmt, TranslatedVariab
/** /**
* A C/C++ `try` statement, or a `__try __except` or `__try __finally` statement. * A C/C++ `try` statement, or a `__try __except` or `__try __finally` statement.
*/ */
private class TryOrMicrosoftTryStmt extends Stmt { class TryOrMicrosoftTryStmt extends Stmt {
TryOrMicrosoftTryStmt() { TryOrMicrosoftTryStmt() {
this instanceof TryStmt or this instanceof TryStmt or
this instanceof MicrosoftTryStmt this instanceof MicrosoftTryStmt
@@ -619,7 +667,9 @@ private class TryOrMicrosoftTryStmt extends Stmt {
} }
/** Gets the `finally` statement (usually a BlockStmt), if any. */ /** Gets the `finally` statement (usually a BlockStmt), if any. */
Stmt getFinally() { result = this.(MicrosoftTryFinallyStmt).getFinally() } TranslatedElement getTranslatedFinally() {
result = getTranslatedMicrosoftTryFinallyHandler(this)
}
} }
/** /**
@@ -689,11 +739,14 @@ class TranslatedTryStmt extends TranslatedStmt {
final override Instruction getExceptionSuccessorInstruction(EdgeKind kind) { final override Instruction getExceptionSuccessorInstruction(EdgeKind kind) {
result = this.getHandler(0).getFirstInstruction(kind) result = this.getHandler(0).getFirstInstruction(kind)
or
not exists(this.getHandler(_)) and
result = this.getFinally().getFirstInstruction(kind)
} }
private TranslatedElement getHandler(int index) { result = stmt.getTranslatedHandler(index) } private TranslatedElement getHandler(int index) { result = stmt.getTranslatedHandler(index) }
private TranslatedStmt getFinally() { result = getTranslatedStmt(stmt.getFinally()) } private TranslatedElement getFinally() { result = stmt.getTranslatedFinally() }
private TranslatedStmt getBody() { result = getTranslatedStmt(stmt.getStmt()) } private TranslatedStmt getBody() { result = getTranslatedStmt(stmt.getStmt()) }
} }

View File

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

View File

@@ -71,9 +71,6 @@ class MemoryLocation extends TMemoryLocation {
final string getUniqueId() { result = var.getUniqueId() } final string getUniqueId() { result = var.getUniqueId() }
final predicate canReuseSsa() { canReuseSsaForVariable(var) } final predicate canReuseSsa() { canReuseSsaForVariable(var) }
/** DEPRECATED: Alias for canReuseSsa */
deprecated predicate canReuseSSA() { this.canReuseSsa() }
} }
predicate canReuseSsaForOldResult(Instruction instr) { none() } predicate canReuseSsaForOldResult(Instruction instr) { none() }

View File

@@ -42,6 +42,7 @@ private import implementations.Accept
private import implementations.Poll private import implementations.Poll
private import implementations.Select private import implementations.Select
private import implementations.MySql private import implementations.MySql
private import implementations.NoexceptFunction
private import implementations.ODBC private import implementations.ODBC
private import implementations.SqLite3 private import implementations.SqLite3
private import implementations.PostgreSql private import implementations.PostgreSql

View File

@@ -5,13 +5,13 @@
*/ */
import semmle.code.cpp.models.interfaces.Allocation import semmle.code.cpp.models.interfaces.Allocation
import semmle.code.cpp.models.interfaces.Taint import semmle.code.cpp.models.interfaces.DataFlow
/** /**
* An allocation function (such as `realloc`) that has an argument for the size * An allocation function (such as `realloc`) that has an argument for the size
* in bytes, and an argument for an existing pointer that is to be reallocated. * in bytes, and an argument for an existing pointer that is to be reallocated.
*/ */
private class ReallocAllocationFunction extends AllocationFunction, TaintFunction { private class ReallocAllocationFunction extends AllocationFunction, DataFlowFunction {
int sizeArg; int sizeArg;
int reallocArg; int reallocArg;
@@ -44,7 +44,7 @@ private class ReallocAllocationFunction extends AllocationFunction, TaintFunctio
override int getReallocPtrArg() { result = reallocArg } override int getReallocPtrArg() { result = reallocArg }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isParameterDeref(this.getReallocPtrArg()) and output.isReturnValueDeref() input.isParameterDeref(this.getReallocPtrArg()) and output.isReturnValueDeref()
} }
} }

View File

@@ -9,13 +9,14 @@ import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Alias import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.Taint import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.NonThrowing
/** /**
* The standard functions `memcpy`, `memmove` and `bcopy`; and the gcc variant * The standard functions `memcpy`, `memmove` and `bcopy`; and the gcc variant
* `__builtin___memcpy_chk`. * `__builtin___memcpy_chk`.
*/ */
private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffectFunction, private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffectFunction,
AliasFunction AliasFunction, NonThrowingFunction
{ {
MemcpyFunction() { MemcpyFunction() {
// memcpy(dest, src, num) // memcpy(dest, src, num)

View File

@@ -8,9 +8,10 @@ import semmle.code.cpp.models.interfaces.ArrayFunction
import semmle.code.cpp.models.interfaces.DataFlow import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Alias import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.NonThrowing
private class MemsetFunctionModel extends ArrayFunction, DataFlowFunction, AliasFunction, private class MemsetFunctionModel extends ArrayFunction, DataFlowFunction, AliasFunction,
SideEffectFunction SideEffectFunction, NonThrowingFunction
{ {
MemsetFunctionModel() { MemsetFunctionModel() {
this.hasGlobalOrStdOrBslName("memset") this.hasGlobalOrStdOrBslName("memset")

View File

@@ -0,0 +1,11 @@
import semmle.code.cpp.models.interfaces.NonThrowing
/**
* A function that is annotated with a `noexcept` specifier (or the equivalent
* `throw()` specifier) guaranteeing that the function can not throw exceptions.
*
* Note: The `throw` specifier was deprecated in C++11 and removed in C++17.
*/
class NoexceptFunction extends NonThrowingFunction {
NoexceptFunction() { this.isNoExcept() or this.isNoThrow() }
}

View File

@@ -8,11 +8,12 @@
import semmle.code.cpp.models.interfaces.FormattingFunction import semmle.code.cpp.models.interfaces.FormattingFunction
import semmle.code.cpp.models.interfaces.Alias import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.NonThrowing
/** /**
* The standard functions `printf`, `wprintf` and their glib variants. * The standard functions `printf`, `wprintf` and their glib variants.
*/ */
private class Printf extends FormattingFunction, AliasFunction { private class Printf extends FormattingFunction, AliasFunction, NonThrowingFunction {
Printf() { Printf() {
this instanceof TopLevelFunction and this instanceof TopLevelFunction and
( (
@@ -36,7 +37,7 @@ private class Printf extends FormattingFunction, AliasFunction {
/** /**
* The standard functions `fprintf`, `fwprintf` and their glib variants. * The standard functions `fprintf`, `fwprintf` and their glib variants.
*/ */
private class Fprintf extends FormattingFunction { private class Fprintf extends FormattingFunction, NonThrowingFunction {
Fprintf() { Fprintf() {
this instanceof TopLevelFunction and this instanceof TopLevelFunction and
( (
@@ -54,7 +55,7 @@ private class Fprintf extends FormattingFunction {
/** /**
* The standard function `sprintf` and its Microsoft and glib variants. * The standard function `sprintf` and its Microsoft and glib variants.
*/ */
private class Sprintf extends FormattingFunction { private class Sprintf extends FormattingFunction, NonThrowingFunction {
Sprintf() { Sprintf() {
this instanceof TopLevelFunction and this instanceof TopLevelFunction and
( (
@@ -97,7 +98,7 @@ private class Sprintf extends FormattingFunction {
/** /**
* Implements `Snprintf`. * Implements `Snprintf`.
*/ */
private class SnprintfImpl extends Snprintf, AliasFunction, SideEffectFunction { private class SnprintfImpl extends Snprintf, AliasFunction, SideEffectFunction, NonThrowingFunction {
SnprintfImpl() { SnprintfImpl() {
this instanceof TopLevelFunction and this instanceof TopLevelFunction and
( (
@@ -204,7 +205,7 @@ private class StringCchPrintf extends FormattingFunction {
/** /**
* The standard function `syslog`. * The standard function `syslog`.
*/ */
private class Syslog extends FormattingFunction { private class Syslog extends FormattingFunction, NonThrowingFunction {
Syslog() { Syslog() {
this instanceof TopLevelFunction and this instanceof TopLevelFunction and
this.hasGlobalName("syslog") and this.hasGlobalName("syslog") and

View File

@@ -7,13 +7,16 @@ import semmle.code.cpp.models.interfaces.ArrayFunction
import semmle.code.cpp.models.interfaces.DataFlow import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Taint import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.SideEffect import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.NonThrowing
/** /**
* The standard function `strcat` and its wide, sized, and Microsoft variants. * The standard function `strcat` and its wide, sized, and Microsoft variants.
* *
* Does not include `strlcat`, which is covered by `StrlcatFunction` * Does not include `strlcat`, which is covered by `StrlcatFunction`
*/ */
class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, SideEffectFunction { class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, SideEffectFunction,
NonThrowingFunction
{
StrcatFunction() { StrcatFunction() {
this.hasGlobalOrStdOrBslName([ this.hasGlobalOrStdOrBslName([
"strcat", // strcat(dst, src) "strcat", // strcat(dst, src)

View File

@@ -7,11 +7,14 @@ import semmle.code.cpp.models.interfaces.ArrayFunction
import semmle.code.cpp.models.interfaces.DataFlow import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Taint import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.SideEffect import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.NonThrowing
/** /**
* The standard function `strcpy` and its wide, sized, and Microsoft variants. * The standard function `strcpy` and its wide, sized, and Microsoft variants.
*/ */
class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction { class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction,
NonThrowingFunction
{
StrcpyFunction() { StrcpyFunction() {
this.hasGlobalOrStdOrBslName([ this.hasGlobalOrStdOrBslName([
"strcpy", // strcpy(dst, src) "strcpy", // strcpy(dst, src)

View File

@@ -26,7 +26,7 @@ private class Swap extends DataFlowFunction {
* obj1.swap(obj2) * obj1.swap(obj2)
* ``` * ```
*/ */
private class MemberSwap extends TaintFunction, MemberFunction, AliasFunction { private class MemberSwap extends DataFlowFunction, MemberFunction, AliasFunction {
MemberSwap() { MemberSwap() {
this.hasName("swap") and this.hasName("swap") and
this.getNumberOfParameters() = 1 and this.getNumberOfParameters() = 1 and
@@ -34,7 +34,7 @@ private class MemberSwap extends TaintFunction, MemberFunction, AliasFunction {
this.getDeclaringType() this.getDeclaringType()
} }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierObject() and input.isQualifierObject() and
output.isParameterDeref(0) output.isParameterDeref(0)
or or

View File

@@ -0,0 +1,11 @@
/**
* Provides an abstract class for modeling functions that never throw.
*/
import semmle.code.cpp.Function
import semmle.code.cpp.models.Models
/**
* A function that is guaranteed to never throw.
*/
abstract class NonThrowingFunction extends Function { }

View File

@@ -14,7 +14,11 @@ int getPointedSize(Type t) {
* BufferWrite differ. * BufferWrite differ.
*/ */
abstract class BufferAccess extends Expr { abstract class BufferAccess extends Expr {
BufferAccess() { not this.isUnevaluated() } BufferAccess() {
not this.isUnevaluated() and
//A buffer access must be reachable (not in dead code)
reachable(this)
}
abstract string getName(); abstract string getName();
@@ -26,6 +30,8 @@ abstract class BufferAccess extends Expr {
* - 1 = buffer range [0, getSize) is accessed entirely. * - 1 = buffer range [0, getSize) is accessed entirely.
* - 2 = buffer range [0, getSize) may be accessed partially or entirely. * - 2 = buffer range [0, getSize) may be accessed partially or entirely.
* - 3 = buffer is accessed at offset getSize - 1. * - 3 = buffer is accessed at offset getSize - 1.
* - 4 = buffer is accessed with null terminator read protections
* (does not read past null terminator, regardless of access size)
*/ */
abstract Expr getBuffer(string bufferDesc, int accessType); abstract Expr getBuffer(string bufferDesc, int accessType);
@@ -128,7 +134,7 @@ class StrncpyBA extends BufferAccess {
or or
result = this.(FunctionCall).getArgument(1) and result = this.(FunctionCall).getArgument(1) and
bufferDesc = "source buffer" and bufferDesc = "source buffer" and
accessType = 2 accessType = 4
} }
override Expr getSizeExpr() { result = this.(FunctionCall).getArgument(2) } override Expr getSizeExpr() { result = this.(FunctionCall).getArgument(2) }

View File

@@ -353,22 +353,6 @@ module BoostorgAsio {
} }
//////////////////////// Dataflow ///////////////////// //////////////////////// Dataflow /////////////////////
/**
* Abstract class for flows of protocol values to the first argument of a context
* constructor.
*/
abstract deprecated class SslContextCallAbstractConfig extends DataFlow::Configuration {
bindingset[this]
SslContextCallAbstractConfig() { any() }
override predicate isSink(DataFlow::Node sink) {
exists(ConstructorCall cc, SslContextClass c, Expr e | e = sink.asExpr() |
c.getAContructorCall() = cc and
cc.getArgument(0) = e
)
}
}
/** /**
* Signature for flows of protocol values to the first argument of a context * Signature for flows of protocol values to the first argument of a context
* constructor. * constructor.
@@ -402,20 +386,6 @@ module BoostorgAsio {
import DataFlow::Global<C> import DataFlow::Global<C>
} }
/**
* Any protocol value that flows to the first argument of a context constructor.
*/
deprecated class SslContextCallConfig extends SslContextCallAbstractConfig {
SslContextCallConfig() { this = "SslContextCallConfig" }
override predicate isSource(DataFlow::Node source) {
exists(Expr e | e = source.asExpr() |
e.fromSource() and
not e.getLocation().getFile().toString().matches("%/boost/asio/%")
)
}
}
/** /**
* Any protocol value that flows to the first argument of a context constructor. * Any protocol value that flows to the first argument of a context constructor.
*/ */
@@ -430,21 +400,6 @@ module BoostorgAsio {
module SslContextCallFlow = SslContextCallGlobal<SslContextCallConfig>; module SslContextCallFlow = SslContextCallGlobal<SslContextCallConfig>;
/**
* A banned protocol value that flows to the first argument of a context constructor.
*/
deprecated class SslContextCallBannedProtocolConfig extends SslContextCallAbstractConfig {
SslContextCallBannedProtocolConfig() { this = "SslContextCallBannedProtocolConfig" }
override predicate isSource(DataFlow::Node source) {
exists(Expr e | e = source.asExpr() |
e.fromSource() and
not e.getLocation().getFile().toString().matches("%/boost/asio/%") and
isExprBannedBoostProtocol(e)
)
}
}
/** /**
* A banned protocol value that flows to the first argument of a context constructor. * A banned protocol value that flows to the first argument of a context constructor.
*/ */
@@ -461,21 +416,6 @@ module BoostorgAsio {
module SslContextCallBannedProtocolFlow = module SslContextCallBannedProtocolFlow =
SslContextCallGlobal<SslContextCallBannedProtocolConfig>; SslContextCallGlobal<SslContextCallBannedProtocolConfig>;
/**
* A TLS 1.2 protocol value that flows to the first argument of a context constructor.
*/
deprecated class SslContextCallTls12ProtocolConfig extends SslContextCallAbstractConfig {
SslContextCallTls12ProtocolConfig() { this = "SslContextCallTls12ProtocolConfig" }
override predicate isSource(DataFlow::Node source) {
exists(Expr e | e = source.asExpr() |
e.fromSource() and
not e.getLocation().getFile().toString().matches("%/boost/asio/%") and
isExprTls12BoostProtocol(e)
)
}
}
/** /**
* A TLS 1.2 protocol value that flows to the first argument of a context constructor. * A TLS 1.2 protocol value that flows to the first argument of a context constructor.
*/ */
@@ -491,21 +431,6 @@ module BoostorgAsio {
module SslContextCallTls12ProtocolFlow = SslContextCallGlobal<SslContextCallTls12ProtocolConfig>; module SslContextCallTls12ProtocolFlow = SslContextCallGlobal<SslContextCallTls12ProtocolConfig>;
/**
* A TLS 1.3 protocol value that flows to the first argument of a context constructor.
*/
deprecated class SslContextCallTls13ProtocolConfig extends SslContextCallAbstractConfig {
SslContextCallTls13ProtocolConfig() { this = "SslContextCallTls12ProtocolConfig" }
override predicate isSource(DataFlow::Node source) {
exists(Expr e | e = source.asExpr() |
e.fromSource() and
not e.getLocation().getFile().toString().matches("%/boost/asio/%") and
isExprTls13BoostProtocol(e)
)
}
}
/** /**
* A TLS 1.3 protocol value that flows to the first argument of a context constructor. * A TLS 1.3 protocol value that flows to the first argument of a context constructor.
*/ */
@@ -521,21 +446,6 @@ module BoostorgAsio {
module SslContextCallTls13ProtocolFlow = SslContextCallGlobal<SslContextCallTls13ProtocolConfig>; module SslContextCallTls13ProtocolFlow = SslContextCallGlobal<SslContextCallTls13ProtocolConfig>;
/**
* A generic TLS protocol value that flows to the first argument of a context constructor.
*/
deprecated class SslContextCallTlsProtocolConfig extends SslContextCallAbstractConfig {
SslContextCallTlsProtocolConfig() { this = "SslContextCallTlsProtocolConfig" }
override predicate isSource(DataFlow::Node source) {
exists(Expr e | e = source.asExpr() |
e.fromSource() and
not e.getLocation().getFile().toString().matches("%/boost/asio/%") and
isExprTlsBoostProtocol(e)
)
}
}
/** /**
* A generic TLS protocol value that flows to the first argument of a context constructor. * A generic TLS protocol value that flows to the first argument of a context constructor.
*/ */
@@ -551,30 +461,6 @@ module BoostorgAsio {
module SslContextCallTlsProtocolFlow = SslContextCallGlobal<SslContextCallTlsProtocolConfig>; module SslContextCallTlsProtocolFlow = SslContextCallGlobal<SslContextCallTlsProtocolConfig>;
/**
* A context constructor call that flows to a call to `SetOptions()`.
*/
deprecated class SslContextFlowsToSetOptionConfig extends DataFlow::Configuration {
SslContextFlowsToSetOptionConfig() { this = "SslContextFlowsToSetOptionConfig" }
override predicate isSource(DataFlow::Node source) {
exists(SslContextClass c, ConstructorCall cc |
cc = source.asExpr() and
c.getAContructorCall() = cc
)
}
override predicate isSink(DataFlow::Node sink) {
exists(FunctionCall fc, SslSetOptionsFunction f, Variable v, VariableAccess va |
va = sink.asExpr()
|
f.getACallToThisFunction() = fc and
v.getAnAccess() = va and
va = fc.getQualifier()
)
}
}
/** /**
* A context constructor call that flows to a call to `SetOptions()`. * A context constructor call that flows to a call to `SetOptions()`.
*/ */
@@ -599,28 +485,6 @@ module BoostorgAsio {
module SslContextFlowsToSetOptionFlow = DataFlow::Global<SslContextFlowsToSetOptionConfig>; module SslContextFlowsToSetOptionFlow = DataFlow::Global<SslContextFlowsToSetOptionConfig>;
/**
* An option value that flows to the first parameter of a call to `SetOptions()`.
*/
deprecated class SslOptionConfig extends DataFlow::Configuration {
SslOptionConfig() { this = "SslOptionConfig" }
override predicate isSource(DataFlow::Node source) {
exists(Expr e | e = source.asExpr() |
e.fromSource() and
not e.getLocation().getFile().toString().matches("%/boost/asio/%")
)
}
override predicate isSink(DataFlow::Node sink) {
exists(SslSetOptionsFunction f, FunctionCall call |
sink.asExpr() = call.getArgument(0) and
f.getACallToThisFunction() = call and
not sink.getLocation().getFile().toString().matches("%/boost/asio/%")
)
}
}
/** /**
* An option value that flows to the first parameter of a call to `SetOptions()`. * An option value that flows to the first parameter of a call to `SetOptions()`.
*/ */

View File

@@ -384,11 +384,23 @@ function_return_type(
*/ */
coroutine( coroutine(
unique int function: @function ref, unique int function: @function ref,
int traits: @type ref, int traits: @type ref
int handle: @variable ref,
int promise: @variable ref
); );
/*
case @coroutine_placeholder_variable.kind of
1 = @handle
| 2 = @promise
| 3 = @init_await_resume
;
*/
coroutine_placeholder_variable(
unique int placeholder_variable: @variable ref,
int kind: int ref,
int function: @function ref
)
/** The `new` function used for allocating the coroutine state, if any. */ /** The `new` function used for allocating the coroutine state, if any. */
coroutine_new( coroutine_new(
unique int function: @function ref, unique int function: @function ref,
@@ -829,22 +841,6 @@ variable_template_argument_value(
int arg_value: @expr ref int arg_value: @expr ref
); );
/*
Fixed point types
precision(1) = short, precision(2) = default, precision(3) = long
is_unsigned(1) = unsigned is_unsigned(2) = signed
is_fract_type(1) = declared with _Fract
saturating(1) = declared with _Sat
*/
/* TODO
fixedpointtypes(
unique int id: @fixedpointtype,
int precision: int ref,
int is_unsigned: int ref,
int is_fract_type: int ref,
int saturating: int ref);
*/
routinetypes( routinetypes(
unique int id: @routinetype, unique int id: @routinetype,
int return_type: @type ref int return_type: @type ref
@@ -1210,6 +1206,7 @@ conversionkinds(
| @reference_to | @reference_to
| @ref_indirect | @ref_indirect
| @temp_init | @temp_init
| @c11_generic
; ;
/* /*
@@ -1788,6 +1785,11 @@ case @expr.kind of
| 382 = @isvalidwinrttype | 382 = @isvalidwinrttype
| 383 = @iswinclass | 383 = @iswinclass
| 384 = @iswininterface | 384 = @iswininterface
| 385 = @istriviallyequalitycomparable
| 386 = @isscopedenum
| 387 = @istriviallyrelocatable
| 388 = @datasizeof
| 389 = @c11_generic
; ;
@var_args_expr = @vastartexpr @var_args_expr = @vastartexpr
@@ -1901,6 +1903,9 @@ case @expr.kind of
| @isvalidwinrttype | @isvalidwinrttype
| @iswinclass | @iswinclass
| @iswininterface | @iswininterface
| @istriviallyequalitycomparable
| @isscopedenum
| @istriviallyrelocatable
; ;
new_allocated_type( new_allocated_type(
@@ -1961,7 +1966,7 @@ uuidof_bind(
int type_id: @type ref int type_id: @type ref
); );
@runtime_sizeof_or_alignof = @runtime_sizeof | @runtime_alignof; @runtime_sizeof_or_alignof = @runtime_sizeof | @runtime_alignof | @datasizeof;
sizeof_bind( sizeof_bind(
unique int expr: @runtime_sizeof_or_alignof ref, unique int expr: @runtime_sizeof_or_alignof ref,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Expose C11 _Generics
compatibility: backwards

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
description: Improve handling of coroutine placeholder variables
compatibility: partial
coroutine.rel: run upgrades.qlo new_coroutine
coroutine_placeholder_variable.rel: run upgrades.qlo new_coroutine_placeholder_variable

View File

@@ -0,0 +1,19 @@
class Function extends @function {
string toString() { none() }
}
class Type extends @type {
string toString() { none() }
}
class Variable extends @variable {
string toString() { none() }
}
query predicate new_coroutine(Function func, Type traits) { coroutine(func, traits, _, _) }
query predicate new_coroutine_placeholder_variable(Variable var, int kind, Function func) {
coroutine(func, _, var, _) and kind = 1
or
coroutine(func, _, _, var) and kind = 2
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Add new builtin operations
compatibility: backwards

View File

@@ -42,7 +42,9 @@ class BufferAccess extends ArrayExpr {
not exists(Macro m | not exists(Macro m |
m.getName() = "strcmp" and m.getName() = "strcmp" and
m.getAnInvocation().getAnExpandedElement() = this m.getAnInvocation().getAnExpandedElement() = this
) ) and
//A buffer access must be reachable (not in dead code)
reachable(this)
} }
int bufferSize() { staticBuffer(this.getArrayBase(), _, result) } int bufferSize() { staticBuffer(this.getArrayBase(), _, result) }

View File

@@ -205,20 +205,6 @@ class ChecksForLeapYearFunctionCall extends FunctionCall {
ChecksForLeapYearFunctionCall() { this.getTarget() instanceof ChecksForLeapYearFunction } ChecksForLeapYearFunctionCall() { this.getTarget() instanceof ChecksForLeapYearFunction }
} }
/**
* Data flow configuration for finding a variable access that would flow into
* a function call that includes an operation to check for leap year.
*/
deprecated class LeapYearCheckConfiguration extends DataFlow::Configuration {
LeapYearCheckConfiguration() { this = "LeapYearCheckConfiguration" }
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof VariableAccess }
override predicate isSink(DataFlow::Node sink) {
exists(ChecksForLeapYearFunctionCall fc | sink.asExpr() = fc.getAnArgument())
}
}
/** /**
* Data flow configuration for finding a variable access that would flow into * Data flow configuration for finding a variable access that would flow into
* a function call that includes an operation to check for leap year. * a function call that includes an operation to check for leap year.
@@ -233,33 +219,6 @@ private module LeapYearCheckConfig implements DataFlow::ConfigSig {
module LeapYearCheckFlow = DataFlow::Global<LeapYearCheckConfig>; module LeapYearCheckFlow = DataFlow::Global<LeapYearCheckConfig>;
/**
* Data flow configuration for finding an operation with hardcoded 365 that will flow into
* a `FILEINFO` field.
*/
deprecated class FiletimeYearArithmeticOperationCheckConfiguration extends DataFlow::Configuration {
FiletimeYearArithmeticOperationCheckConfiguration() {
this = "FiletimeYearArithmeticOperationCheckConfiguration"
}
override predicate isSource(DataFlow::Node source) {
exists(Expr e, Operation op | e = source.asExpr() |
op.getAChild*().getValue().toInt() = 365 and
op.getAChild*() = e
)
}
override predicate isSink(DataFlow::Node sink) {
exists(StructLikeClass dds, FieldAccess fa, AssignExpr aexpr, Expr e | e = sink.asExpr() |
dds instanceof PackedTimeType and
fa.getQualifier().getUnderlyingType() = dds and
fa.isModified() and
aexpr.getAChild() = fa and
aexpr.getChild(1).getAChild*() = e
)
}
}
/** /**
* Data flow configuration for finding an operation with hardcoded 365 that will flow into * Data flow configuration for finding an operation with hardcoded 365 that will flow into
* a `FILEINFO` field. * a `FILEINFO` field.
@@ -286,51 +245,6 @@ private module FiletimeYearArithmeticOperationCheckConfig implements DataFlow::C
module FiletimeYearArithmeticOperationCheckFlow = module FiletimeYearArithmeticOperationCheckFlow =
DataFlow::Global<FiletimeYearArithmeticOperationCheckConfig>; DataFlow::Global<FiletimeYearArithmeticOperationCheckConfig>;
/**
* Taint configuration for finding an operation with hardcoded 365 that will flow into any known date/time field.
*/
deprecated class PossibleYearArithmeticOperationCheckConfiguration extends TaintTracking::Configuration
{
PossibleYearArithmeticOperationCheckConfiguration() {
this = "PossibleYearArithmeticOperationCheckConfiguration"
}
override predicate isSource(DataFlow::Node source) {
exists(Operation op | op = source.asExpr() |
op.getAChild*().getValue().toInt() = 365 and
(
not op.getParent() instanceof Expr or
op.getParent() instanceof Assignment
)
)
}
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
// flow from anything on the RHS of an assignment to a time/date structure to that
// assignment.
exists(StructLikeClass dds, FieldAccess fa, Assignment aexpr, Expr e |
e = node1.asExpr() and
fa = node2.asExpr()
|
(dds instanceof PackedTimeType or dds instanceof UnpackedTimeType) and
fa.getQualifier().getUnderlyingType() = dds and
aexpr.getLValue() = fa and
aexpr.getRValue().getAChild*() = e
)
}
override predicate isSink(DataFlow::Node sink) {
exists(StructLikeClass dds, FieldAccess fa, AssignExpr aexpr |
aexpr.getRValue() = sink.asExpr()
|
(dds instanceof PackedTimeType or dds instanceof UnpackedTimeType) and
fa.getQualifier().getUnderlyingType() = dds and
fa.isModified() and
aexpr.getLValue() = fa
)
}
}
/** /**
* Taint configuration for finding an operation with hardcoded 365 that will flow into any known date/time field. * Taint configuration for finding an operation with hardcoded 365 that will flow into any known date/time field.
*/ */

View File

@@ -129,24 +129,6 @@ class NetworkFunctionCall extends FunctionCall {
NetworkFunctionCall() { this.getTarget().hasName(["ntohd", "ntohf", "ntohl", "ntohll", "ntohs"]) } NetworkFunctionCall() { this.getTarget().hasName(["ntohd", "ntohf", "ntohl", "ntohll", "ntohs"]) }
} }
deprecated class NetworkToBufferSizeConfiguration extends DataFlow::Configuration {
NetworkToBufferSizeConfiguration() { this = "NetworkToBufferSizeConfiguration" }
override predicate isSource(DataFlow::Node node) { node.asExpr() instanceof NetworkFunctionCall }
override predicate isSink(DataFlow::Node node) {
node.asExpr() = any(BufferAccess ba).getAccessedLength()
}
override predicate isBarrier(DataFlow::Node node) {
exists(GuardCondition gc, GVN gvn |
gc.getAChild*() = gvn.getAnExpr() and
globalValueNumber(node.asExpr()) = gvn and
gc.controls(node.asExpr().getBasicBlock(), _)
)
}
}
private module NetworkToBufferSizeConfig implements DataFlow::ConfigSig { private module NetworkToBufferSizeConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { node.asExpr() instanceof NetworkFunctionCall } predicate isSource(DataFlow::Node node) { node.asExpr() instanceof NetworkFunctionCall }

View File

@@ -41,20 +41,6 @@ class ExternalApiDataNode extends DataFlow::Node {
string getFunctionDescription() { result = this.getExternalFunction().toString() } string getFunctionDescription() { result = this.getExternalFunction().toString() }
} }
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
deprecated class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration {
UntrustedDataToExternalApiConfig() { this = "UntrustedDataToExternalAPIConfig" }
override predicate isSource(DataFlow::Node source) {
exists(RemoteFlowSourceFunction remoteFlow |
remoteFlow = source.asExpr().(Call).getTarget() and
remoteFlow.hasRemoteFlowSource(_, _)
)
}
override predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode }
}
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */ /** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
private module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig { private module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { predicate isSource(DataFlow::Node source) {

View File

@@ -41,15 +41,6 @@ class ExternalApiDataNode extends DataFlow::Node {
string getFunctionDescription() { result = this.getExternalFunction().toString() } string getFunctionDescription() { result = this.getExternalFunction().toString() }
} }
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
deprecated class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration {
UntrustedDataToExternalApiConfig() { this = "UntrustedDataToExternalAPIConfigIR" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode }
}
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */ /** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */
private module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig { private module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }

View File

@@ -26,6 +26,7 @@ from
BufferAccess ba, string bufferDesc, int accessSize, int accessType, Element bufferAlloc, BufferAccess ba, string bufferDesc, int accessSize, int accessType, Element bufferAlloc,
int bufferSize, string message int bufferSize, string message
where where
accessType != 4 and
accessSize = ba.getSize() and accessSize = ba.getSize() and
bufferSize = getBufferSize(ba.getBuffer(bufferDesc, accessType), bufferAlloc) and bufferSize = getBufferSize(ba.getBuffer(bufferDesc, accessType), bufferAlloc) and
( (

View File

@@ -1,6 +1,6 @@
/** /**
* This file provides the `bounded` predicate that is used in both `cpp/uncontrolled-arithmetic` * This file provides the `bounded` predicate that is used in `cpp/uncontrolled-arithmetic`,
* and `cpp/tainted-arithmetic`. * `cpp/tainted-arithmetic` and `cpp/uncontrolled-allocation-size`.
*/ */
private import cpp private import cpp
@@ -8,20 +8,18 @@ private import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
private import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils private import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
/** /**
* An operand `e` of a bitwise and expression `andExpr` (i.e., `andExpr` is either an `BitwiseAndExpr` * An operand `operand` of a bitwise and expression `andExpr` (i.e., `andExpr` is either a
* or an `AssignAndExpr`) with operands `operand1` and `operand2` is the operand that is not `e` is upper * `BitwiseAndExpr` or an `AssignAndExpr`) is upper bounded by some number that is less than the
* bounded by some number that is less than the maximum integer allowed by the result type of `andExpr`. * maximum integer allowed by the result type of `andExpr`.
*/ */
pragma[inline] pragma[inline]
private predicate boundedBitwiseAnd(Expr e, Expr andExpr, Expr operand1, Expr operand2) { private predicate boundedBitwiseAnd(Expr operand, Expr andExpr) {
operand1 != operand2 and upperBound(operand.getFullyConverted()) < exprMaxVal(andExpr.getFullyConverted())
e = operand1 and
upperBound(operand2.getFullyConverted()) < exprMaxVal(andExpr.getFullyConverted())
} }
/** /**
* Holds if `e` is an arithmetic expression that cannot overflow, or if `e` is an operand of an * Holds if `e` is an arithmetic expression that cannot overflow, or if `e` is an operation that
* operation that may greatly reduce the range of possible values. * may greatly reduce the range of possible values.
*/ */
predicate bounded(Expr e) { predicate bounded(Expr e) {
// There can be two separate reasons for `convertedExprMightOverflow` not holding: // There can be two separate reasons for `convertedExprMightOverflow` not holding:
@@ -35,25 +33,25 @@ predicate bounded(Expr e) {
) and ) and
not convertedExprMightOverflow(e) not convertedExprMightOverflow(e)
or or
// Optimistically assume that a remainder expression always yields a much smaller value. // Optimistically assume that the following operations always yields a much smaller value.
e = any(RemExpr rem).getLeftOperand() e instanceof RemExpr
or or
e = any(AssignRemExpr rem).getLValue() e instanceof DivExpr
or
e instanceof RShiftExpr
or or
exists(BitwiseAndExpr andExpr | exists(BitwiseAndExpr andExpr |
boundedBitwiseAnd(e, andExpr, andExpr.getAnOperand(), andExpr.getAnOperand()) e = andExpr and boundedBitwiseAnd(andExpr.getAnOperand(), andExpr)
) )
or or
exists(AssignAndExpr andExpr | // For the assignment variant of the operations we place the barrier on the assigned lvalue.
boundedBitwiseAnd(e, andExpr, andExpr.getAnOperand(), andExpr.getAnOperand()) e = any(AssignRemExpr rem).getLValue()
)
or
// Optimistically assume that a division always yields a much smaller value.
e = any(DivExpr div).getLeftOperand()
or or
e = any(AssignDivExpr div).getLValue() e = any(AssignDivExpr div).getLValue()
or or
e = any(RShiftExpr shift).getLeftOperand()
or
e = any(AssignRShiftExpr div).getLValue() e = any(AssignRShiftExpr div).getLValue()
or
exists(AssignAndExpr andExpr |
e = andExpr.getLValue() and boundedBitwiseAnd(andExpr.getRValue(), andExpr)
)
} }

View File

@@ -16,6 +16,7 @@
import cpp import cpp
import semmle.code.cpp.valuenumbering.GlobalValueNumbering import semmle.code.cpp.valuenumbering.GlobalValueNumbering
import semmle.code.cpp.controlflow.Guards import semmle.code.cpp.controlflow.Guards
import semmle.code.cpp.models.implementations.NoexceptFunction
/** Gets the `Constructor` invoked when `newExpr` allocates memory. */ /** Gets the `Constructor` invoked when `newExpr` allocates memory. */
Constructor getConstructorForAllocation(NewOrNewArrayExpr newExpr) { Constructor getConstructorForAllocation(NewOrNewArrayExpr newExpr) {
@@ -44,9 +45,8 @@ predicate deleteMayThrow(DeleteOrDeleteArrayExpr deleteExpr) {
* like it might throw an exception, and the function does not have a `noexcept` or `throw()` specifier. * like it might throw an exception, and the function does not have a `noexcept` or `throw()` specifier.
*/ */
predicate functionMayThrow(Function f) { predicate functionMayThrow(Function f) {
(not exists(f.getBlock()) or stmtMayThrow(f.getBlock())) and not f instanceof NonThrowingFunction and
not f.isNoExcept() and (not exists(f.getBlock()) or stmtMayThrow(f.getBlock()))
not f.isNoThrow()
} }
/** Holds if the evaluation of `stmt` may throw an exception. */ /** Holds if the evaluation of `stmt` may throw an exception. */
@@ -172,8 +172,7 @@ class ThrowingAllocator extends Function {
not exists(Parameter p | p = this.getAParameter() | not exists(Parameter p | p = this.getAParameter() |
p.getUnspecifiedType().stripType() instanceof NoThrowType p.getUnspecifiedType().stripType() instanceof NoThrowType
) and ) and
not this.isNoExcept() and not this instanceof NoexceptFunction
not this.isNoThrow()
) )
} }
} }

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Add modeling of C functions that don't throw, thereby increasing the precision of the `cpp/incorrect-allocation-error-handling` ("Incorrect allocation-error handling") query. The query now produces additional true positives.

View File

@@ -0,0 +1,5 @@
---
category: minorAnalysis
---
* Removed false positives caused by buffer accesses in unreachable code
* Removed false positives caused by inconsistent type checking

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