mirror of
https://github.com/github/codeql.git
synced 2026-05-27 01:21:23 +02:00
Compare commits
5 Commits
calumgrant
...
criemen/ru
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8fba481a04 | ||
|
|
9433201b58 | ||
|
|
c097397c32 | ||
|
|
3d5d1bc59e | ||
|
|
007fc89543 |
@@ -1 +1 @@
|
||||
7.1.0
|
||||
6.5.0
|
||||
|
||||
2
.github/labeler.yml
vendored
2
.github/labeler.yml
vendored
@@ -20,7 +20,7 @@ JS:
|
||||
|
||||
Kotlin:
|
||||
- java/kotlin-extractor/**/*
|
||||
- java/ql/test-kotlin*/**/*
|
||||
- java/ql/test/kotlin/**/*
|
||||
|
||||
Python:
|
||||
- python/**/*
|
||||
|
||||
15
.github/workflows/codeql-analysis.yml
vendored
15
.github/workflows/codeql-analysis.yml
vendored
@@ -40,7 +40,7 @@ jobs:
|
||||
uses: github/codeql-action/init@main
|
||||
# Override language selection by uncommenting this and choosing your languages
|
||||
with:
|
||||
languages: csharp, cpp
|
||||
languages: csharp
|
||||
config-file: ./.github/codeql/codeql-config.yml
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
@@ -57,19 +57,6 @@ jobs:
|
||||
|
||||
- run: |
|
||||
dotnet build csharp
|
||||
|
||||
- name: "[Ubuntu] Remove GCC 13 from runner image"
|
||||
shell: bash
|
||||
run: |
|
||||
sudo rm -f /etc/apt/sources.list.d/ubuntu-toolchain-r-ubuntu-test-jammy.list
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --allow-downgrades libc6=2.35-* libc6-dev=2.35-* libstdc++6=12.3.0-* libgcc-s1=12.3.0-*
|
||||
|
||||
- name: "Build Swift extractor using Bazel"
|
||||
run: |
|
||||
bazel clean --expunge
|
||||
bazel run //swift:create-extractor-pack --nouse_action_cache --noremote_accept_cached --noremote_upload_local_results --spawn_strategy=local --features=-layering_check
|
||||
bazel shutdown
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@main
|
||||
|
||||
2
.github/workflows/compile-queries.yml
vendored
2
.github/workflows/compile-queries.yml
vendored
@@ -28,7 +28,7 @@ jobs:
|
||||
with:
|
||||
key: all-queries
|
||||
- name: check formatting
|
||||
run: find shared */ql -type f \( -name "*.qll" -o -name "*.ql" \) -print0 | xargs -0 -n 3000 -P 10 codeql query format -q --check-only
|
||||
run: find */ql -type f \( -name "*.qll" -o -name "*.ql" \) -print0 | xargs -0 -n 3000 -P 10 codeql query format -q --check-only
|
||||
- name: compile queries - check-only
|
||||
# run with --check-only if running in a PR (github.sha != main)
|
||||
if : ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -39,9 +39,6 @@
|
||||
# local bazel options
|
||||
/local.bazelrc
|
||||
|
||||
# generated cmake directory
|
||||
/.bazel-cmake
|
||||
|
||||
# CLion project files
|
||||
/.clwb
|
||||
|
||||
|
||||
18
MODULE.bazel
18
MODULE.bazel
@@ -18,9 +18,10 @@ bazel_dep(name = "rules_pkg", version = "0.9.1")
|
||||
bazel_dep(name = "rules_nodejs", version = "6.0.3")
|
||||
bazel_dep(name = "rules_python", version = "0.31.0")
|
||||
bazel_dep(name = "bazel_skylib", version = "1.5.0")
|
||||
bazel_dep(name = "abseil-cpp", version = "20240116.1", 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 = "fmt", version = "10.0.0")
|
||||
bazel_dep(name = "rules_rust", version = "0.39.0")
|
||||
|
||||
pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
|
||||
pip.parse(
|
||||
@@ -51,3 +52,18 @@ use_repo(node, "nodejs", "nodejs_toolchains")
|
||||
register_toolchains(
|
||||
"@nodejs_toolchains//:all",
|
||||
)
|
||||
|
||||
crate = use_extension(
|
||||
"@rules_rust//crate_universe:extension.bzl",
|
||||
"crate",
|
||||
)
|
||||
|
||||
crate.from_cargo(
|
||||
name = "r", # short name due to long path issues on windows
|
||||
cargo_lockfile = "//ruby/extractor:Cargo.lock",
|
||||
manifests = [
|
||||
"//ruby/extractor:Cargo.toml",
|
||||
],
|
||||
)
|
||||
|
||||
use_repo(crate, "r")
|
||||
|
||||
@@ -6,7 +6,6 @@ provide:
|
||||
- "*/ql/consistency-queries/qlpack.yml"
|
||||
- "*/ql/automodel/src/qlpack.yml"
|
||||
- "*/ql/automodel/test/qlpack.yml"
|
||||
- "python/extractor/qlpack.yml"
|
||||
- "shared/**/qlpack.yml"
|
||||
- "cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml"
|
||||
- "go/ql/config/legacy-support/qlpack.yml"
|
||||
|
||||
@@ -88,46 +88,123 @@
|
||||
"IR Instruction": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll"
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll"
|
||||
],
|
||||
"IR IRBlock": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRBlock.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRBlock.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll"
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/raw/IRBlock.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRBlock.qll"
|
||||
],
|
||||
"IR IRVariable": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRVariable.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll"
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/raw/IRVariable.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRVariable.qll"
|
||||
],
|
||||
"IR IRFunction": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRFunction.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRFunction.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRFunction.qll"
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRFunction.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/raw/IRFunction.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRFunction.qll"
|
||||
],
|
||||
"IR Operand": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Operand.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll"
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/raw/Operand.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Operand.qll"
|
||||
],
|
||||
"IR IRType": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/IRType.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/IRType.qll"
|
||||
],
|
||||
"IR IRConfiguration": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/IRConfiguration.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/IRConfiguration.qll"
|
||||
],
|
||||
"IR UseSoundEscapeAnalysis": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/UseSoundEscapeAnalysis.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/UseSoundEscapeAnalysis.qll"
|
||||
],
|
||||
"IR IRFunctionBase": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/IRFunctionBase.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/internal/IRFunctionBase.qll"
|
||||
],
|
||||
"IR Operand Tag": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/OperandTag.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/internal/OperandTag.qll"
|
||||
],
|
||||
"IR TInstruction": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TInstruction.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/internal/TInstruction.qll"
|
||||
],
|
||||
"IR TIRVariable": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TIRVariable.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/internal/TIRVariable.qll"
|
||||
],
|
||||
"IR IR": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IR.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IR.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IR.qll"
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IR.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/raw/IR.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IR.qll"
|
||||
],
|
||||
"IR IRConsistency": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRConsistency.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRConsistency.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRConsistency.qll"
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRConsistency.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/raw/IRConsistency.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRConsistency.qll"
|
||||
],
|
||||
"IR PrintIR": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/PrintIR.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll"
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/raw/PrintIR.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/PrintIR.qll"
|
||||
],
|
||||
"IR IntegerConstant": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/internal/IntegerConstant.qll",
|
||||
"csharp/ql/src/experimental/ir/internal/IntegerConstant.qll"
|
||||
],
|
||||
"IR IntegerInteval": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/internal/IntegerInterval.qll",
|
||||
"csharp/ql/src/experimental/ir/internal/IntegerInterval.qll"
|
||||
],
|
||||
"IR IntegerPartial": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/internal/IntegerPartial.qll",
|
||||
"csharp/ql/src/experimental/ir/internal/IntegerPartial.qll"
|
||||
],
|
||||
"IR Overlap": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/internal/Overlap.qll",
|
||||
"csharp/ql/src/experimental/ir/internal/Overlap.qll"
|
||||
],
|
||||
"IR EdgeKind": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/EdgeKind.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/EdgeKind.qll"
|
||||
],
|
||||
"IR MemoryAccessKind": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/MemoryAccessKind.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/MemoryAccessKind.qll"
|
||||
],
|
||||
"IR TempVariableTag": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/TempVariableTag.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/TempVariableTag.qll"
|
||||
],
|
||||
"IR Opcode": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/Opcode.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/Opcode.qll"
|
||||
],
|
||||
"IR SSAConsistency": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConsistency.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConsistency.qll"
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConsistency.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConsistency.qll"
|
||||
],
|
||||
"C++ IR InstructionImports": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/InstructionImports.qll",
|
||||
@@ -175,7 +252,8 @@
|
||||
],
|
||||
"SSA AliasAnalysis": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll"
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll"
|
||||
],
|
||||
"SSA PrintAliasAnalysis": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/PrintAliasAnalysis.qll",
|
||||
@@ -190,28 +268,44 @@
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingImports.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingImports.qll"
|
||||
],
|
||||
"IR SSA SimpleSSA": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll"
|
||||
],
|
||||
"IR AliasConfiguration (unaliased_ssa)": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasConfiguration.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/AliasConfiguration.qll"
|
||||
],
|
||||
"IR SSA SSAConstruction": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll"
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll"
|
||||
],
|
||||
"IR SSA PrintSSA": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/PrintSSA.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/PrintSSA.qll"
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/PrintSSA.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/PrintSSA.qll"
|
||||
],
|
||||
"IR ValueNumberInternal": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingInternal.qll"
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingInternal.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll"
|
||||
],
|
||||
"C++ IR ValueNumber": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/ValueNumbering.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/ValueNumbering.qll"
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/ValueNumbering.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/raw/gvn/ValueNumbering.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll"
|
||||
],
|
||||
"C++ IR PrintValueNumbering": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/PrintValueNumbering.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/PrintValueNumbering.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/PrintValueNumbering.qll"
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/PrintValueNumbering.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/raw/gvn/PrintValueNumbering.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/PrintValueNumbering.qll"
|
||||
],
|
||||
"C++ IR ConstantAnalysis": [
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/constant/ConstantAnalysis.qll",
|
||||
@@ -239,6 +333,38 @@
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/reachability/PrintDominance.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/PrintDominance.qll"
|
||||
],
|
||||
"C# IR InstructionImports": [
|
||||
"csharp/ql/src/experimental/ir/implementation/raw/internal/InstructionImports.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/InstructionImports.qll"
|
||||
],
|
||||
"C# IR IRImports": [
|
||||
"csharp/ql/src/experimental/ir/implementation/raw/internal/IRImports.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/IRImports.qll"
|
||||
],
|
||||
"C# IR IRBlockImports": [
|
||||
"csharp/ql/src/experimental/ir/implementation/raw/internal/IRBlockImports.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/IRBlockImports.qll"
|
||||
],
|
||||
"C# IR IRFunctionImports": [
|
||||
"csharp/ql/src/experimental/ir/implementation/raw/internal/IRFunctionImports.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/IRFunctionImports.qll"
|
||||
],
|
||||
"C# IR IRVariableImports": [
|
||||
"csharp/ql/src/experimental/ir/implementation/raw/internal/IRVariableImports.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/IRVariableImports.qll"
|
||||
],
|
||||
"C# IR OperandImports": [
|
||||
"csharp/ql/src/experimental/ir/implementation/raw/internal/OperandImports.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/OperandImports.qll"
|
||||
],
|
||||
"C# IR PrintIRImports": [
|
||||
"csharp/ql/src/experimental/ir/implementation/raw/internal/PrintIRImports.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/PrintIRImports.qll"
|
||||
],
|
||||
"C# IR ValueNumberingImports": [
|
||||
"csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingImports.qll",
|
||||
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingImports.qll"
|
||||
],
|
||||
"C# ControlFlowReachability": [
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/ControlFlowReachability.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/ControlFlowReachability.qll"
|
||||
@@ -255,6 +381,7 @@
|
||||
"cpp/ql/lib/semmle/code/cpp/XML.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/XML.qll",
|
||||
"java/ql/lib/semmle/code/xml/XML.qll",
|
||||
"javascript/ql/lib/semmle/javascript/XML.qll",
|
||||
"python/ql/lib/semmle/python/xml/XML.qll"
|
||||
],
|
||||
"DuplicationProblems.inc.qhelp": [
|
||||
@@ -304,6 +431,13 @@
|
||||
"java/ql/src/experimental/Security/CWE/CWE-400/LocalThreadResourceAbuse.qhelp",
|
||||
"java/ql/src/experimental/Security/CWE/CWE-400/ThreadResourceAbuse.qhelp"
|
||||
],
|
||||
"IDE Contextual Queries": [
|
||||
"cpp/ql/lib/IDEContextual.qll",
|
||||
"csharp/ql/lib/IDEContextual.qll",
|
||||
"java/ql/lib/IDEContextual.qll",
|
||||
"javascript/ql/lib/IDEContextual.qll",
|
||||
"python/ql/lib/analysis/IDEContextual.qll"
|
||||
],
|
||||
"CryptoAlgorithms Python/JS/Ruby": [
|
||||
"javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll",
|
||||
"python/ql/lib/semmle/python/concepts/CryptoAlgorithms.qll",
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
|
||||
using Semmle.Autobuild.Shared;
|
||||
using Semmle.Util;
|
||||
|
||||
namespace Semmle.Autobuild.Cpp
|
||||
{
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
class Expr extends @expr {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Location extends @location_expr {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
from Expr expr, int kind, int kind_new, Location loc
|
||||
where
|
||||
exprs(expr, kind, loc) and
|
||||
if kind = 363 then kind_new = 1 else kind_new = kind
|
||||
select expr, kind_new, loc
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,4 +0,0 @@
|
||||
description: Introduce re-use expressions
|
||||
compatibility: partial
|
||||
expr_reuse.rel: delete
|
||||
exprs.rel: run exprs.qlo
|
||||
@@ -1,13 +1,3 @@
|
||||
## 0.12.8
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.12.7
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Added destructors for named objects to the intermediate representation.
|
||||
|
||||
## 0.12.6
|
||||
|
||||
### New Features
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*/
|
||||
|
||||
import semmle.files.FileSystem
|
||||
private import codeql.util.FileSystem
|
||||
|
||||
/**
|
||||
* Returns the `File` matching the given source file name as encoded by the VS
|
||||
@@ -11,5 +10,13 @@ private import codeql.util.FileSystem
|
||||
*/
|
||||
cached
|
||||
File getFileBySourceArchiveName(string name) {
|
||||
result = IdeContextual<File>::getFileBySourceArchiveName(name)
|
||||
// The name provided for a file in the source archive by the VS Code extension
|
||||
// has some differences from the absolute path in the database:
|
||||
// 1. colons are replaced by underscores
|
||||
// 2. there's a leading slash, even for Windows paths: "C:/foo/bar" ->
|
||||
// "/C_/foo/bar"
|
||||
// 3. double slashes in UNC prefixes are replaced with a single slash
|
||||
// We can handle 2 and 3 together by unconditionally adding a leading slash
|
||||
// before replacing double slashes.
|
||||
name = ("/" + result.getAbsolutePath().replaceAll(":", "_")).replaceAll("//", "/")
|
||||
}
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Added a predicate `GuardCondition.valueControls` to query whether a basic block is guarded by a particular `case` of a `switch` statement.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Added a predicate `GuardCondition.comparesLt/4` to query whether an expression is compared to a constant.
|
||||
* Added a predicate `GuardCondition.ensuresLt/4` to query whether a basic block is guarded by an expression being less than a constant.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Added a predicate `GuardCondition.comparesEq/4` to query whether an expression is compared to a constant.
|
||||
* Added a predicate `GuardCondition.ensuresEq/4` to query whether a basic block is guarded by an expression being equal to a constant.
|
||||
@@ -1,5 +0,0 @@
|
||||
## 0.12.7
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Added destructors for named objects to the intermediate representation.
|
||||
@@ -1,3 +0,0 @@
|
||||
## 0.12.8
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.12.8
|
||||
lastReleaseVersion: 0.12.6
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.12.9-dev
|
||||
version: 0.12.7-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -60,6 +60,4 @@ Element exprEnclosingElement(Expr e) {
|
||||
)
|
||||
else result = de.getDeclaration()
|
||||
)
|
||||
or
|
||||
result.(Stmt).getAnImplicitDestructorCall() = e
|
||||
}
|
||||
|
||||
@@ -309,12 +309,9 @@ class ExprNode extends AstNode {
|
||||
override AstNode getChildInternal(int childIndex) {
|
||||
result.getAst() = expr.getChild(childIndex)
|
||||
or
|
||||
childIndex = max(int index | exists(expr.getChild(index)) or index = 0) + 1 and
|
||||
result.getAst() = expr.(ConditionDeclExpr).getInitializingExpr()
|
||||
or
|
||||
exists(int destructorIndex |
|
||||
result.getAst() = expr.getImplicitDestructorCall(destructorIndex) and
|
||||
childIndex = destructorIndex + max(int index | exists(expr.getChild(index)) or index = 0) + 2
|
||||
childIndex = destructorIndex + max(int index | exists(expr.getChild(index)) or index = 0) + 1
|
||||
)
|
||||
}
|
||||
|
||||
@@ -689,8 +686,6 @@ private string getChildAccessorWithoutConversions(Locatable parent, Element chil
|
||||
not namedExprChildPredicates(expr, child, _) and
|
||||
exists(int n | expr.getChild(n) = child and result = "getChild(" + n + ")")
|
||||
or
|
||||
expr.(ConditionDeclExpr).getInitializingExpr() = child and result = "getInitializingExpr()"
|
||||
or
|
||||
exists(int n |
|
||||
expr.getImplicitDestructorCall(n) = child and
|
||||
result = "getImplicitDestructorCall(" + n + ")"
|
||||
|
||||
@@ -20,44 +20,6 @@ private predicate isUnreachedBlock(IRBlock block) {
|
||||
block.getFirstInstruction() instanceof UnreachedInstruction
|
||||
}
|
||||
|
||||
private newtype TAbstractValue =
|
||||
TBooleanValue(boolean b) { b = true or b = false } or
|
||||
TMatchValue(CaseEdge c)
|
||||
|
||||
/**
|
||||
* An abstract value. This is either a boolean value, or a `switch` case.
|
||||
*/
|
||||
abstract class AbstractValue extends TAbstractValue {
|
||||
/** Gets an abstract value that represents the dual of this value, if any. */
|
||||
abstract AbstractValue getDualValue();
|
||||
|
||||
/** Gets a textual representation of this abstract value. */
|
||||
abstract string toString();
|
||||
}
|
||||
|
||||
/** A Boolean value. */
|
||||
class BooleanValue extends AbstractValue, TBooleanValue {
|
||||
/** Gets the underlying Boolean value. */
|
||||
boolean getValue() { this = TBooleanValue(result) }
|
||||
|
||||
override BooleanValue getDualValue() { result.getValue() = this.getValue().booleanNot() }
|
||||
|
||||
override string toString() { result = this.getValue().toString() }
|
||||
}
|
||||
|
||||
/** A value that represents a match against a specific `switch` case. */
|
||||
class MatchValue extends AbstractValue, TMatchValue {
|
||||
/** Gets the case. */
|
||||
CaseEdge getCase() { this = TMatchValue(result) }
|
||||
|
||||
override MatchValue getDualValue() {
|
||||
// A `MatchValue` has no dual.
|
||||
none()
|
||||
}
|
||||
|
||||
override string toString() { result = this.getCase().toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A Boolean condition in the AST that guards one or more basic blocks. This includes
|
||||
* operands of logical operators but not switch statements.
|
||||
@@ -72,15 +34,6 @@ class GuardCondition extends Expr {
|
||||
this.(BinaryLogicalOperation).getAnOperand() instanceof GuardCondition
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this condition controls `controlled`, meaning that `controlled` is only
|
||||
* entered if the value of this condition is `v`.
|
||||
*
|
||||
* For details on what "controls" mean, see the QLDoc for `controls`.
|
||||
*/
|
||||
cached
|
||||
predicate valueControls(BasicBlock controlled, AbstractValue v) { none() }
|
||||
|
||||
/**
|
||||
* Holds if this condition controls `controlled`, meaning that `controlled` is only
|
||||
* entered if the value of this condition is `testIsTrue`.
|
||||
@@ -108,9 +61,7 @@ class GuardCondition extends Expr {
|
||||
* true (for `&&`) or false (for `||`) branch.
|
||||
*/
|
||||
cached
|
||||
final predicate controls(BasicBlock controlled, boolean testIsTrue) {
|
||||
this.valueControls(controlled, any(BooleanValue bv | bv.getValue() = testIsTrue))
|
||||
}
|
||||
predicate controls(BasicBlock controlled, boolean testIsTrue) { none() }
|
||||
|
||||
/** Holds if (determined by this guard) `left < right + k` evaluates to `isLessThan` if this expression evaluates to `testIsTrue`. */
|
||||
cached
|
||||
@@ -125,20 +76,6 @@ class GuardCondition extends Expr {
|
||||
cached
|
||||
predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) { none() }
|
||||
|
||||
/**
|
||||
* Holds if (determined by this guard) `e < k` evaluates to `isLessThan` if
|
||||
* this expression evaluates to `value`.
|
||||
*/
|
||||
cached
|
||||
predicate comparesLt(Expr e, int k, boolean isLessThan, AbstractValue value) { none() }
|
||||
|
||||
/**
|
||||
* Holds if (determined by this guard) `e < k` must be `isLessThan` in `block`.
|
||||
* If `isLessThan = false` then this implies `e >= k`.
|
||||
*/
|
||||
cached
|
||||
predicate ensuresLt(Expr e, int k, BasicBlock block, boolean isLessThan) { none() }
|
||||
|
||||
/** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */
|
||||
cached
|
||||
predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) {
|
||||
@@ -151,17 +88,6 @@ class GuardCondition extends Expr {
|
||||
*/
|
||||
cached
|
||||
predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) { none() }
|
||||
|
||||
/** Holds if (determined by this guard) `e == k` evaluates to `areEqual` if this expression evaluates to `value`. */
|
||||
cached
|
||||
predicate comparesEq(Expr e, int k, boolean areEqual, AbstractValue value) { none() }
|
||||
|
||||
/**
|
||||
* Holds if (determined by this guard) `e == k` must be `areEqual` in `block`.
|
||||
* If `areEqual = false` then this implies `e != k`.
|
||||
*/
|
||||
cached
|
||||
predicate ensuresEq(Expr e, int k, BasicBlock block, boolean areEqual) { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,13 +98,13 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition {
|
||||
this.(BinaryLogicalOperation).getAnOperand() instanceof GuardCondition
|
||||
}
|
||||
|
||||
override predicate valueControls(BasicBlock controlled, AbstractValue v) {
|
||||
override predicate controls(BasicBlock controlled, boolean testIsTrue) {
|
||||
exists(BinaryLogicalOperation binop, GuardCondition lhs, GuardCondition rhs |
|
||||
this = binop and
|
||||
lhs = binop.getLeftOperand() and
|
||||
rhs = binop.getRightOperand() and
|
||||
lhs.valueControls(controlled, v) and
|
||||
rhs.valueControls(controlled, v)
|
||||
lhs.controls(controlled, testIsTrue) and
|
||||
rhs.controls(controlled, testIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -190,27 +116,12 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate comparesLt(Expr e, int k, boolean isLessThan, AbstractValue value) {
|
||||
exists(BooleanValue partValue, GuardCondition part |
|
||||
this.(BinaryLogicalOperation)
|
||||
.impliesValue(part, partValue.getValue(), value.(BooleanValue).getValue())
|
||||
|
|
||||
part.comparesLt(e, k, isLessThan, partValue)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) {
|
||||
exists(boolean testIsTrue |
|
||||
this.comparesLt(left, right, k, isLessThan, testIsTrue) and this.controls(block, testIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate ensuresLt(Expr e, int k, BasicBlock block, boolean isLessThan) {
|
||||
exists(AbstractValue value |
|
||||
this.comparesLt(e, k, isLessThan, value) and this.valueControls(block, value)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) {
|
||||
exists(boolean partIsTrue, GuardCondition part |
|
||||
this.(BinaryLogicalOperation).impliesValue(part, partIsTrue, testIsTrue)
|
||||
@@ -224,21 +135,6 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition {
|
||||
this.comparesEq(left, right, k, areEqual, testIsTrue) and this.controls(block, testIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate comparesEq(Expr e, int k, boolean areEqual, AbstractValue value) {
|
||||
exists(BooleanValue partValue, GuardCondition part |
|
||||
this.(BinaryLogicalOperation)
|
||||
.impliesValue(part, partValue.getValue(), value.(BooleanValue).getValue())
|
||||
|
|
||||
part.comparesEq(e, k, areEqual, partValue)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate ensuresEq(Expr e, int k, BasicBlock block, boolean areEqual) {
|
||||
exists(AbstractValue value |
|
||||
this.comparesEq(e, k, areEqual, value) and this.valueControls(block, value)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -250,12 +146,13 @@ private class GuardConditionFromIR extends GuardCondition {
|
||||
|
||||
GuardConditionFromIR() { this = ir.getUnconvertedResultExpression() }
|
||||
|
||||
override predicate valueControls(BasicBlock controlled, AbstractValue v) {
|
||||
override predicate controls(BasicBlock controlled, boolean testIsTrue) {
|
||||
// This condition must determine the flow of control; that is, this
|
||||
// node must be a top-level condition.
|
||||
this.controlsBlock(controlled, v)
|
||||
this.controlsBlock(controlled, testIsTrue)
|
||||
}
|
||||
|
||||
/** Holds if (determined by this guard) `left < right + k` evaluates to `isLessThan` if this expression evaluates to `testIsTrue`. */
|
||||
override predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) {
|
||||
exists(Instruction li, Instruction ri |
|
||||
li.getUnconvertedResultExpression() = left and
|
||||
@@ -264,13 +161,10 @@ private class GuardConditionFromIR extends GuardCondition {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate comparesLt(Expr e, int k, boolean isLessThan, AbstractValue value) {
|
||||
exists(Instruction i |
|
||||
i.getUnconvertedResultExpression() = e and
|
||||
ir.comparesLt(i.getAUse(), k, isLessThan, value)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if (determined by this guard) `left < right + k` must be `isLessThan` in `block`.
|
||||
* If `isLessThan = false` then this implies `left >= right + k`.
|
||||
*/
|
||||
override predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) {
|
||||
exists(Instruction li, Instruction ri, boolean testIsTrue |
|
||||
li.getUnconvertedResultExpression() = left and
|
||||
@@ -280,14 +174,7 @@ private class GuardConditionFromIR extends GuardCondition {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate ensuresLt(Expr e, int k, BasicBlock block, boolean isLessThan) {
|
||||
exists(Instruction i, AbstractValue value |
|
||||
i.getUnconvertedResultExpression() = e and
|
||||
ir.comparesLt(i.getAUse(), k, isLessThan, value) and
|
||||
this.valueControls(block, value)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */
|
||||
override predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) {
|
||||
exists(Instruction li, Instruction ri |
|
||||
li.getUnconvertedResultExpression() = left and
|
||||
@@ -296,6 +183,10 @@ private class GuardConditionFromIR extends GuardCondition {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if (determined by this guard) `left == right + k` must be `areEqual` in `block`.
|
||||
* If `areEqual = false` then this implies `left != right + k`.
|
||||
*/
|
||||
override predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) {
|
||||
exists(Instruction li, Instruction ri, boolean testIsTrue |
|
||||
li.getUnconvertedResultExpression() = left and
|
||||
@@ -305,30 +196,15 @@ private class GuardConditionFromIR extends GuardCondition {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate comparesEq(Expr e, int k, boolean areEqual, AbstractValue value) {
|
||||
exists(Instruction i |
|
||||
i.getUnconvertedResultExpression() = e and
|
||||
ir.comparesEq(i.getAUse(), k, areEqual, value)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate ensuresEq(Expr e, int k, BasicBlock block, boolean areEqual) {
|
||||
exists(Instruction i, AbstractValue value |
|
||||
i.getUnconvertedResultExpression() = e and
|
||||
ir.comparesEq(i.getAUse(), k, areEqual, value) and
|
||||
this.valueControls(block, value)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this condition controls `block`, meaning that `block` is only
|
||||
* entered if the value of this condition is `v`. This helper
|
||||
* entered if the value of this condition is `testIsTrue`. This helper
|
||||
* predicate does not necessarily hold for binary logical operations like
|
||||
* `&&` and `||`. See the detailed explanation on predicate `controls`.
|
||||
*/
|
||||
private predicate controlsBlock(BasicBlock controlled, AbstractValue v) {
|
||||
private predicate controlsBlock(BasicBlock controlled, boolean testIsTrue) {
|
||||
exists(IRBlock irb |
|
||||
ir.valueControls(irb, v) and
|
||||
ir.controls(irb, testIsTrue) and
|
||||
nonExcludedIRAndBasicBlock(irb, controlled) and
|
||||
not isUnreachedBlock(irb)
|
||||
)
|
||||
@@ -373,28 +249,10 @@ private predicate nonExcludedIRAndBasicBlock(IRBlock irb, BasicBlock controlled)
|
||||
*/
|
||||
cached
|
||||
class IRGuardCondition extends Instruction {
|
||||
Instruction branch;
|
||||
ConditionalBranchInstruction branch;
|
||||
|
||||
cached
|
||||
IRGuardCondition() { branch = getBranchForCondition(this) }
|
||||
|
||||
/**
|
||||
* Holds if this condition controls `controlled`, meaning that `controlled` is only
|
||||
* entered if the value of this condition is `v`.
|
||||
*
|
||||
* For details on what "controls" mean, see the QLDoc for `controls`.
|
||||
*/
|
||||
cached
|
||||
predicate valueControls(IRBlock controlled, AbstractValue v) {
|
||||
// This condition must determine the flow of control; that is, this
|
||||
// node must be a top-level condition.
|
||||
this.controlsBlock(controlled, v)
|
||||
or
|
||||
exists(IRGuardCondition ne |
|
||||
this = ne.(LogicalNotInstruction).getUnary() and
|
||||
ne.valueControls(controlled, v.getDualValue())
|
||||
)
|
||||
}
|
||||
IRGuardCondition() { branch = get_branch_for_condition(this) }
|
||||
|
||||
/**
|
||||
* Holds if this condition controls `controlled`, meaning that `controlled` is only
|
||||
@@ -424,25 +282,13 @@ class IRGuardCondition extends Instruction {
|
||||
*/
|
||||
cached
|
||||
predicate controls(IRBlock controlled, boolean testIsTrue) {
|
||||
this.valueControls(controlled, any(BooleanValue bv | bv.getValue() = testIsTrue))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the control-flow edge `(pred, succ)` may be taken only if
|
||||
* the value of this condition is `v`.
|
||||
*/
|
||||
cached
|
||||
predicate valueControlsEdge(IRBlock pred, IRBlock succ, AbstractValue v) {
|
||||
pred.getASuccessor() = succ and
|
||||
this.valueControls(pred, v)
|
||||
// This condition must determine the flow of control; that is, this
|
||||
// node must be a top-level condition.
|
||||
this.controlsBlock(controlled, testIsTrue)
|
||||
or
|
||||
succ = this.getBranchSuccessor(v) and
|
||||
(
|
||||
branch.(ConditionalBranchInstruction).getCondition() = this and
|
||||
branch.getBlock() = pred
|
||||
or
|
||||
branch.(SwitchInstruction).getExpression() = this and
|
||||
branch.getBlock() = pred
|
||||
exists(IRGuardCondition ne |
|
||||
this = ne.(LogicalNotInstruction).getUnary() and
|
||||
ne.controls(controlled, testIsTrue.booleanNot())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -451,12 +297,17 @@ class IRGuardCondition extends Instruction {
|
||||
* the value of this condition is `testIsTrue`.
|
||||
*/
|
||||
cached
|
||||
final predicate controlsEdge(IRBlock pred, IRBlock succ, boolean testIsTrue) {
|
||||
this.valueControlsEdge(pred, succ, any(BooleanValue bv | bv.getValue() = testIsTrue))
|
||||
predicate controlsEdge(IRBlock pred, IRBlock succ, boolean testIsTrue) {
|
||||
pred.getASuccessor() = succ and
|
||||
this.controls(pred, testIsTrue)
|
||||
or
|
||||
succ = this.getBranchSuccessor(testIsTrue) and
|
||||
branch.getCondition() = this and
|
||||
branch.getBlock() = pred
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the block to which `branch` jumps directly when the value of this condition is `v`.
|
||||
* Gets the block to which `branch` jumps directly when this condition is `testIsTrue`.
|
||||
*
|
||||
* This predicate is intended to help with situations in which an inference can only be made
|
||||
* based on an edge between a block with multiple successors and a block with multiple
|
||||
@@ -470,39 +321,21 @@ class IRGuardCondition extends Instruction {
|
||||
* return x;
|
||||
* ```
|
||||
*/
|
||||
private IRBlock getBranchSuccessor(AbstractValue v) {
|
||||
branch.(ConditionalBranchInstruction).getCondition() = this and
|
||||
exists(BooleanValue bv | bv = v |
|
||||
bv.getValue() = true and
|
||||
result.getFirstInstruction() = branch.(ConditionalBranchInstruction).getTrueSuccessor()
|
||||
private IRBlock getBranchSuccessor(boolean testIsTrue) {
|
||||
branch.getCondition() = this and
|
||||
(
|
||||
testIsTrue = true and
|
||||
result.getFirstInstruction() = branch.getTrueSuccessor()
|
||||
or
|
||||
bv.getValue() = false and
|
||||
result.getFirstInstruction() = branch.(ConditionalBranchInstruction).getFalseSuccessor()
|
||||
)
|
||||
or
|
||||
exists(SwitchInstruction switch, CaseEdge kind | switch = branch |
|
||||
switch.getExpression() = this and
|
||||
result.getFirstInstruction() = switch.getSuccessor(kind) and
|
||||
kind = v.(MatchValue).getCase()
|
||||
testIsTrue = false and
|
||||
result.getFirstInstruction() = branch.getFalseSuccessor()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if (determined by this guard) `left < right + k` evaluates to `isLessThan` if this expression evaluates to `testIsTrue`. */
|
||||
cached
|
||||
predicate comparesLt(Operand left, Operand right, int k, boolean isLessThan, boolean testIsTrue) {
|
||||
exists(BooleanValue value |
|
||||
compares_lt(this, left, right, k, isLessThan, value) and
|
||||
value.getValue() = testIsTrue
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if (determined by this guard) `op < k` evaluates to `isLessThan` if
|
||||
* this expression evaluates to `value`.
|
||||
*/
|
||||
cached
|
||||
predicate comparesLt(Operand op, int k, boolean isLessThan, AbstractValue value) {
|
||||
compares_lt(this, op, k, isLessThan, value)
|
||||
compares_lt(this, left, right, k, isLessThan, testIsTrue)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -511,19 +344,8 @@ class IRGuardCondition extends Instruction {
|
||||
*/
|
||||
cached
|
||||
predicate ensuresLt(Operand left, Operand right, int k, IRBlock block, boolean isLessThan) {
|
||||
exists(AbstractValue value |
|
||||
compares_lt(this, left, right, k, isLessThan, value) and this.valueControls(block, value)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if (determined by this guard) `op < k` must be `isLessThan` in `block`.
|
||||
* If `isLessThan = false` then this implies `op >= k`.
|
||||
*/
|
||||
cached
|
||||
predicate ensuresLt(Operand op, int k, IRBlock block, boolean isLessThan) {
|
||||
exists(AbstractValue value |
|
||||
compares_lt(this, op, k, isLessThan, value) and this.valueControls(block, value)
|
||||
exists(boolean testIsTrue |
|
||||
compares_lt(this, left, right, k, isLessThan, testIsTrue) and this.controls(block, testIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -535,37 +357,16 @@ class IRGuardCondition extends Instruction {
|
||||
predicate ensuresLtEdge(
|
||||
Operand left, Operand right, int k, IRBlock pred, IRBlock succ, boolean isLessThan
|
||||
) {
|
||||
exists(AbstractValue value |
|
||||
compares_lt(this, left, right, k, isLessThan, value) and
|
||||
this.valueControlsEdge(pred, succ, value)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if (determined by this guard) `op < k` must be `isLessThan` on the edge from
|
||||
* `pred` to `succ`. If `isLessThan = false` then this implies `op >= k`.
|
||||
*/
|
||||
cached
|
||||
predicate ensuresLtEdge(Operand left, int k, IRBlock pred, IRBlock succ, boolean isLessThan) {
|
||||
exists(AbstractValue value |
|
||||
compares_lt(this, left, k, isLessThan, value) and
|
||||
this.valueControlsEdge(pred, succ, value)
|
||||
exists(boolean testIsTrue |
|
||||
compares_lt(this, left, right, k, isLessThan, testIsTrue) and
|
||||
this.controlsEdge(pred, succ, testIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */
|
||||
cached
|
||||
predicate comparesEq(Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue) {
|
||||
exists(BooleanValue value |
|
||||
compares_eq(this, left, right, k, areEqual, value) and
|
||||
value.getValue() = testIsTrue
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if (determined by this guard) `op == k` evaluates to `areEqual` if this expression evaluates to `value`. */
|
||||
cached
|
||||
predicate comparesEq(Operand op, int k, boolean areEqual, AbstractValue value) {
|
||||
compares_eq(this, op, k, areEqual, value)
|
||||
compares_eq(this, left, right, k, areEqual, testIsTrue)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -574,19 +375,8 @@ class IRGuardCondition extends Instruction {
|
||||
*/
|
||||
cached
|
||||
predicate ensuresEq(Operand left, Operand right, int k, IRBlock block, boolean areEqual) {
|
||||
exists(AbstractValue value |
|
||||
compares_eq(this, left, right, k, areEqual, value) and this.valueControls(block, value)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if (determined by this guard) `op == k` must be `areEqual` in `block`.
|
||||
* If `areEqual = false` then this implies `op != k`.
|
||||
*/
|
||||
cached
|
||||
predicate ensuresEq(Operand op, int k, IRBlock block, boolean areEqual) {
|
||||
exists(AbstractValue value |
|
||||
compares_eq(this, op, k, areEqual, value) and this.valueControls(block, value)
|
||||
exists(boolean testIsTrue |
|
||||
compares_eq(this, left, right, k, areEqual, testIsTrue) and this.controls(block, testIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -598,31 +388,19 @@ class IRGuardCondition extends Instruction {
|
||||
predicate ensuresEqEdge(
|
||||
Operand left, Operand right, int k, IRBlock pred, IRBlock succ, boolean areEqual
|
||||
) {
|
||||
exists(AbstractValue value |
|
||||
compares_eq(this, left, right, k, areEqual, value) and
|
||||
this.valueControlsEdge(pred, succ, value)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if (determined by this guard) `op == k` must be `areEqual` on the edge from
|
||||
* `pred` to `succ`. If `areEqual = false` then this implies `op != k`.
|
||||
*/
|
||||
cached
|
||||
predicate ensuresEqEdge(Operand op, int k, IRBlock pred, IRBlock succ, boolean areEqual) {
|
||||
exists(AbstractValue value |
|
||||
compares_eq(this, op, k, areEqual, value) and
|
||||
this.valueControlsEdge(pred, succ, value)
|
||||
exists(boolean testIsTrue |
|
||||
compares_eq(this, left, right, k, areEqual, testIsTrue) and
|
||||
this.controlsEdge(pred, succ, testIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this condition controls `block`, meaning that `block` is only
|
||||
* entered if the value of this condition is `v`. This helper
|
||||
* entered if the value of this condition is `testIsTrue`. This helper
|
||||
* predicate does not necessarily hold for binary logical operations like
|
||||
* `&&` and `||`. See the detailed explanation on predicate `controls`.
|
||||
*/
|
||||
private predicate controlsBlock(IRBlock controlled, AbstractValue v) {
|
||||
private predicate controlsBlock(IRBlock controlled, boolean testIsTrue) {
|
||||
not isUnreachedBlock(controlled) and
|
||||
//
|
||||
// For this block to control the block `controlled` with `testIsTrue` the
|
||||
@@ -663,7 +441,7 @@ class IRGuardCondition extends Instruction {
|
||||
// that `this` strictly dominates `controlled` so that isn't necessary to check
|
||||
// directly.
|
||||
exists(IRBlock succ |
|
||||
succ = this.getBranchSuccessor(v) and
|
||||
succ = this.getBranchSuccessor(testIsTrue) and
|
||||
this.hasDominatingEdgeTo(succ) and
|
||||
succ.dominates(controlled)
|
||||
)
|
||||
@@ -698,14 +476,12 @@ class IRGuardCondition extends Instruction {
|
||||
private IRBlock getBranchBlock() { result = branch.getBlock() }
|
||||
}
|
||||
|
||||
private Instruction getBranchForCondition(Instruction guard) {
|
||||
result.(ConditionalBranchInstruction).getCondition() = guard
|
||||
private ConditionalBranchInstruction get_branch_for_condition(Instruction guard) {
|
||||
result.getCondition() = guard
|
||||
or
|
||||
exists(LogicalNotInstruction cond |
|
||||
result = getBranchForCondition(cond) and cond.getUnary() = guard
|
||||
result = get_branch_for_condition(cond) and cond.getUnary() = guard
|
||||
)
|
||||
or
|
||||
result.(SwitchInstruction).getExpression() = guard
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -714,98 +490,52 @@ private Instruction getBranchForCondition(Instruction guard) {
|
||||
* Beware making mistaken logical implications here relating `areEqual` and `testIsTrue`.
|
||||
*/
|
||||
private predicate compares_eq(
|
||||
Instruction test, Operand left, Operand right, int k, boolean areEqual, AbstractValue value
|
||||
Instruction test, Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue
|
||||
) {
|
||||
/* The simple case where the test *is* the comparison so areEqual = testIsTrue xor eq. */
|
||||
exists(AbstractValue v | simple_comparison_eq(test, left, right, k, v) |
|
||||
areEqual = true and value = v
|
||||
exists(boolean eq | simple_comparison_eq(test, left, right, k, eq) |
|
||||
areEqual = true and testIsTrue = eq
|
||||
or
|
||||
areEqual = false and value = v.getDualValue()
|
||||
areEqual = false and testIsTrue = eq.booleanNot()
|
||||
)
|
||||
or
|
||||
// I think this is handled by forwarding in controlsBlock.
|
||||
//or
|
||||
//logical_comparison_eq(test, left, right, k, areEqual, testIsTrue)
|
||||
/* a == b + k => b == a - k */
|
||||
exists(int mk | k = -mk | compares_eq(test, right, left, mk, areEqual, value))
|
||||
exists(int mk | k = -mk | compares_eq(test, right, left, mk, areEqual, testIsTrue))
|
||||
or
|
||||
complex_eq(test, left, right, k, areEqual, value)
|
||||
complex_eq(test, left, right, k, areEqual, testIsTrue)
|
||||
or
|
||||
/* (x is true => (left == right + k)) => (!x is false => (left == right + k)) */
|
||||
exists(AbstractValue dual | value = dual.getDualValue() |
|
||||
compares_eq(test.(LogicalNotInstruction).getUnary(), left, right, k, areEqual, dual)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `op == k` is `areEqual` given that `test` is equal to `value`. */
|
||||
private predicate compares_eq(
|
||||
Instruction test, Operand op, int k, boolean areEqual, AbstractValue value
|
||||
) {
|
||||
/* The simple case where the test *is* the comparison so areEqual = testIsTrue xor eq. */
|
||||
exists(AbstractValue v | simple_comparison_eq(test, op, k, v) |
|
||||
areEqual = true and value = v
|
||||
or
|
||||
areEqual = false and value = v.getDualValue()
|
||||
)
|
||||
or
|
||||
complex_eq(test, op, k, areEqual, value)
|
||||
or
|
||||
/* (x is true => (op == k)) => (!x is false => (op == k)) */
|
||||
exists(AbstractValue dual | value = dual.getDualValue() |
|
||||
compares_eq(test.(LogicalNotInstruction).getUnary(), op, k, areEqual, dual)
|
||||
)
|
||||
or
|
||||
// ((test is `areEqual` => op == const + k2) and const == `k1`) =>
|
||||
// test is `areEqual` => op == k1 + k2
|
||||
exists(int k1, int k2, ConstantInstruction const |
|
||||
compares_eq(test, op, const.getAUse(), k2, areEqual, value) and
|
||||
int_value(const) = k1 and
|
||||
k = k1 + k2
|
||||
exists(boolean isFalse | testIsTrue = isFalse.booleanNot() |
|
||||
compares_eq(test.(LogicalNotInstruction).getUnary(), left, right, k, areEqual, isFalse)
|
||||
)
|
||||
}
|
||||
|
||||
/** Rearrange various simple comparisons into `left == right + k` form. */
|
||||
private predicate simple_comparison_eq(
|
||||
CompareInstruction cmp, Operand left, Operand right, int k, AbstractValue value
|
||||
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual
|
||||
) {
|
||||
left = cmp.getLeftOperand() and
|
||||
cmp instanceof CompareEQInstruction and
|
||||
right = cmp.getRightOperand() and
|
||||
k = 0 and
|
||||
value.(BooleanValue).getValue() = true
|
||||
areEqual = true
|
||||
or
|
||||
left = cmp.getLeftOperand() and
|
||||
cmp instanceof CompareNEInstruction and
|
||||
right = cmp.getRightOperand() and
|
||||
k = 0 and
|
||||
value.(BooleanValue).getValue() = false
|
||||
}
|
||||
|
||||
/** Rearrange various simple comparisons into `op == k` form. */
|
||||
private predicate simple_comparison_eq(Instruction test, Operand op, int k, AbstractValue value) {
|
||||
exists(SwitchInstruction switch, CaseEdge case |
|
||||
test = switch.getExpression() and
|
||||
op.getDef() = test and
|
||||
case = value.(MatchValue).getCase() and
|
||||
exists(switch.getSuccessor(case)) and
|
||||
case.getValue().toInt() = k
|
||||
)
|
||||
areEqual = false
|
||||
}
|
||||
|
||||
private predicate complex_eq(
|
||||
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, AbstractValue value
|
||||
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue
|
||||
) {
|
||||
sub_eq(cmp, left, right, k, areEqual, value)
|
||||
sub_eq(cmp, left, right, k, areEqual, testIsTrue)
|
||||
or
|
||||
add_eq(cmp, left, right, k, areEqual, value)
|
||||
}
|
||||
|
||||
private predicate complex_eq(
|
||||
Instruction test, Operand op, int k, boolean areEqual, AbstractValue value
|
||||
) {
|
||||
sub_eq(test, op, k, areEqual, value)
|
||||
or
|
||||
add_eq(test, op, k, areEqual, value)
|
||||
add_eq(cmp, left, right, k, areEqual, testIsTrue)
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -815,46 +545,31 @@ private predicate complex_eq(
|
||||
|
||||
/** Holds if `left < right + k` evaluates to `isLt` given that test is `testIsTrue`. */
|
||||
private predicate compares_lt(
|
||||
Instruction test, Operand left, Operand right, int k, boolean isLt, AbstractValue value
|
||||
Instruction test, Operand left, Operand right, int k, boolean isLt, boolean testIsTrue
|
||||
) {
|
||||
/* In the simple case, the test is the comparison, so isLt = testIsTrue */
|
||||
simple_comparison_lt(test, left, right, k) and
|
||||
value.(BooleanValue).getValue() = isLt
|
||||
simple_comparison_lt(test, left, right, k) and isLt = true and testIsTrue = true
|
||||
or
|
||||
complex_lt(test, left, right, k, isLt, value)
|
||||
simple_comparison_lt(test, left, right, k) and isLt = false and testIsTrue = false
|
||||
or
|
||||
complex_lt(test, left, right, k, isLt, testIsTrue)
|
||||
or
|
||||
/* (not (left < right + k)) => (left >= right + k) */
|
||||
exists(boolean isGe | isLt = isGe.booleanNot() | compares_ge(test, left, right, k, isGe, value))
|
||||
exists(boolean isGe | isLt = isGe.booleanNot() |
|
||||
compares_ge(test, left, right, k, isGe, testIsTrue)
|
||||
)
|
||||
or
|
||||
/* (x is true => (left < right + k)) => (!x is false => (left < right + k)) */
|
||||
exists(AbstractValue dual | value = dual.getDualValue() |
|
||||
compares_lt(test.(LogicalNotInstruction).getUnary(), left, right, k, isLt, dual)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `op < k` evaluates to `isLt` given that `test` evaluates to `value`. */
|
||||
private predicate compares_lt(Instruction test, Operand op, int k, boolean isLt, AbstractValue value) {
|
||||
simple_comparison_lt(test, op, k, isLt, value)
|
||||
or
|
||||
complex_lt(test, op, k, isLt, value)
|
||||
or
|
||||
/* (x is true => (op < k)) => (!x is false => (op < k)) */
|
||||
exists(AbstractValue dual | value = dual.getDualValue() |
|
||||
compares_lt(test.(LogicalNotInstruction).getUnary(), op, k, isLt, dual)
|
||||
)
|
||||
or
|
||||
exists(int k1, int k2, ConstantInstruction const |
|
||||
compares_lt(test, op, const.getAUse(), k2, isLt, value) and
|
||||
int_value(const) = k1 and
|
||||
k = k1 + k2
|
||||
exists(boolean isFalse | testIsTrue = isFalse.booleanNot() |
|
||||
compares_lt(test.(LogicalNotInstruction).getUnary(), left, right, k, isLt, isFalse)
|
||||
)
|
||||
}
|
||||
|
||||
/** `(a < b + k) => (b > a - k) => (b >= a + (1-k))` */
|
||||
private predicate compares_ge(
|
||||
Instruction test, Operand left, Operand right, int k, boolean isGe, AbstractValue value
|
||||
Instruction test, Operand left, Operand right, int k, boolean isGe, boolean testIsTrue
|
||||
) {
|
||||
exists(int onemk | k = 1 - onemk | compares_lt(test, right, left, onemk, isGe, value))
|
||||
exists(int onemk | k = 1 - onemk | compares_lt(test, right, left, onemk, isGe, testIsTrue))
|
||||
}
|
||||
|
||||
/** Rearrange various simple comparisons into `left < right + k` form. */
|
||||
@@ -880,99 +595,55 @@ private predicate simple_comparison_lt(CompareInstruction cmp, Operand left, Ope
|
||||
k = 1
|
||||
}
|
||||
|
||||
/** Rearrange various simple comparisons into `op < k` form. */
|
||||
private predicate simple_comparison_lt(
|
||||
Instruction test, Operand op, int k, boolean isLt, AbstractValue value
|
||||
) {
|
||||
exists(SwitchInstruction switch, CaseEdge case |
|
||||
test = switch.getExpression() and
|
||||
op.getDef() = test and
|
||||
case = value.(MatchValue).getCase() and
|
||||
exists(switch.getSuccessor(case)) and
|
||||
case.getMaxValue() > case.getMinValue()
|
||||
|
|
||||
// op <= k => op < k - 1
|
||||
isLt = true and
|
||||
case.getMaxValue().toInt() = k - 1
|
||||
or
|
||||
isLt = false and
|
||||
case.getMinValue().toInt() = k
|
||||
)
|
||||
}
|
||||
|
||||
private predicate complex_lt(
|
||||
CompareInstruction cmp, Operand left, Operand right, int k, boolean isLt, AbstractValue value
|
||||
CompareInstruction cmp, Operand left, Operand right, int k, boolean isLt, boolean testIsTrue
|
||||
) {
|
||||
sub_lt(cmp, left, right, k, isLt, value)
|
||||
sub_lt(cmp, left, right, k, isLt, testIsTrue)
|
||||
or
|
||||
add_lt(cmp, left, right, k, isLt, value)
|
||||
}
|
||||
|
||||
private predicate complex_lt(
|
||||
Instruction test, Operand left, int k, boolean isLt, AbstractValue value
|
||||
) {
|
||||
sub_lt(test, left, k, isLt, value)
|
||||
or
|
||||
add_lt(test, left, k, isLt, value)
|
||||
add_lt(cmp, left, right, k, isLt, testIsTrue)
|
||||
}
|
||||
|
||||
// left - x < right + c => left < right + (c+x)
|
||||
// left < (right - x) + c => left < right + (c-x)
|
||||
private predicate sub_lt(
|
||||
CompareInstruction cmp, Operand left, Operand right, int k, boolean isLt, AbstractValue value
|
||||
CompareInstruction cmp, Operand left, Operand right, int k, boolean isLt, boolean testIsTrue
|
||||
) {
|
||||
exists(SubInstruction lhs, int c, int x |
|
||||
compares_lt(cmp, lhs.getAUse(), right, c, isLt, value) and
|
||||
compares_lt(cmp, lhs.getAUse(), right, c, isLt, testIsTrue) and
|
||||
left = lhs.getLeftOperand() and
|
||||
x = int_value(lhs.getRight()) and
|
||||
k = c + x
|
||||
)
|
||||
or
|
||||
exists(SubInstruction rhs, int c, int x |
|
||||
compares_lt(cmp, left, rhs.getAUse(), c, isLt, value) and
|
||||
compares_lt(cmp, left, rhs.getAUse(), c, isLt, testIsTrue) and
|
||||
right = rhs.getLeftOperand() and
|
||||
x = int_value(rhs.getRight()) and
|
||||
k = c - x
|
||||
)
|
||||
or
|
||||
exists(PointerSubInstruction lhs, int c, int x |
|
||||
compares_lt(cmp, lhs.getAUse(), right, c, isLt, value) and
|
||||
compares_lt(cmp, lhs.getAUse(), right, c, isLt, testIsTrue) and
|
||||
left = lhs.getLeftOperand() and
|
||||
x = int_value(lhs.getRight()) and
|
||||
k = c + x
|
||||
)
|
||||
or
|
||||
exists(PointerSubInstruction rhs, int c, int x |
|
||||
compares_lt(cmp, left, rhs.getAUse(), c, isLt, value) and
|
||||
compares_lt(cmp, left, rhs.getAUse(), c, isLt, testIsTrue) and
|
||||
right = rhs.getLeftOperand() and
|
||||
x = int_value(rhs.getRight()) and
|
||||
k = c - x
|
||||
)
|
||||
}
|
||||
|
||||
private predicate sub_lt(Instruction test, Operand left, int k, boolean isLt, AbstractValue value) {
|
||||
exists(SubInstruction lhs, int c, int x |
|
||||
compares_lt(test, lhs.getAUse(), c, isLt, value) and
|
||||
left = lhs.getLeftOperand() and
|
||||
x = int_value(lhs.getRight()) and
|
||||
k = c + x
|
||||
)
|
||||
or
|
||||
exists(PointerSubInstruction lhs, int c, int x |
|
||||
compares_lt(test, lhs.getAUse(), c, isLt, value) and
|
||||
left = lhs.getLeftOperand() and
|
||||
x = int_value(lhs.getRight()) and
|
||||
k = c + x
|
||||
)
|
||||
}
|
||||
|
||||
// left + x < right + c => left < right + (c-x)
|
||||
// left < (right + x) + c => left < right + (c+x)
|
||||
private predicate add_lt(
|
||||
CompareInstruction cmp, Operand left, Operand right, int k, boolean isLt, AbstractValue value
|
||||
CompareInstruction cmp, Operand left, Operand right, int k, boolean isLt, boolean testIsTrue
|
||||
) {
|
||||
exists(AddInstruction lhs, int c, int x |
|
||||
compares_lt(cmp, lhs.getAUse(), right, c, isLt, value) and
|
||||
compares_lt(cmp, lhs.getAUse(), right, c, isLt, testIsTrue) and
|
||||
(
|
||||
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
|
||||
or
|
||||
@@ -982,7 +653,7 @@ private predicate add_lt(
|
||||
)
|
||||
or
|
||||
exists(AddInstruction rhs, int c, int x |
|
||||
compares_lt(cmp, left, rhs.getAUse(), c, isLt, value) and
|
||||
compares_lt(cmp, left, rhs.getAUse(), c, isLt, testIsTrue) and
|
||||
(
|
||||
right = rhs.getLeftOperand() and x = int_value(rhs.getRight())
|
||||
or
|
||||
@@ -992,7 +663,7 @@ private predicate add_lt(
|
||||
)
|
||||
or
|
||||
exists(PointerAddInstruction lhs, int c, int x |
|
||||
compares_lt(cmp, lhs.getAUse(), right, c, isLt, value) and
|
||||
compares_lt(cmp, lhs.getAUse(), right, c, isLt, testIsTrue) and
|
||||
(
|
||||
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
|
||||
or
|
||||
@@ -1002,7 +673,7 @@ private predicate add_lt(
|
||||
)
|
||||
or
|
||||
exists(PointerAddInstruction rhs, int c, int x |
|
||||
compares_lt(cmp, left, rhs.getAUse(), c, isLt, value) and
|
||||
compares_lt(cmp, left, rhs.getAUse(), c, isLt, testIsTrue) and
|
||||
(
|
||||
right = rhs.getLeftOperand() and x = int_value(rhs.getRight())
|
||||
or
|
||||
@@ -1012,86 +683,47 @@ private predicate add_lt(
|
||||
)
|
||||
}
|
||||
|
||||
private predicate add_lt(Instruction test, Operand left, int k, boolean isLt, AbstractValue value) {
|
||||
exists(AddInstruction lhs, int c, int x |
|
||||
compares_lt(test, lhs.getAUse(), c, isLt, value) and
|
||||
(
|
||||
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
|
||||
or
|
||||
left = lhs.getRightOperand() and x = int_value(lhs.getLeft())
|
||||
) and
|
||||
k = c - x
|
||||
)
|
||||
or
|
||||
exists(PointerAddInstruction lhs, int c, int x |
|
||||
compares_lt(test, lhs.getAUse(), c, isLt, value) and
|
||||
(
|
||||
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
|
||||
or
|
||||
left = lhs.getRightOperand() and x = int_value(lhs.getLeft())
|
||||
) and
|
||||
k = c - x
|
||||
)
|
||||
}
|
||||
|
||||
// left - x == right + c => left == right + (c+x)
|
||||
// left == (right - x) + c => left == right + (c-x)
|
||||
private predicate sub_eq(
|
||||
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, AbstractValue value
|
||||
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue
|
||||
) {
|
||||
exists(SubInstruction lhs, int c, int x |
|
||||
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, value) and
|
||||
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, testIsTrue) and
|
||||
left = lhs.getLeftOperand() and
|
||||
x = int_value(lhs.getRight()) and
|
||||
k = c + x
|
||||
)
|
||||
or
|
||||
exists(SubInstruction rhs, int c, int x |
|
||||
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, value) and
|
||||
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, testIsTrue) and
|
||||
right = rhs.getLeftOperand() and
|
||||
x = int_value(rhs.getRight()) and
|
||||
k = c - x
|
||||
)
|
||||
or
|
||||
exists(PointerSubInstruction lhs, int c, int x |
|
||||
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, value) and
|
||||
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, testIsTrue) and
|
||||
left = lhs.getLeftOperand() and
|
||||
x = int_value(lhs.getRight()) and
|
||||
k = c + x
|
||||
)
|
||||
or
|
||||
exists(PointerSubInstruction rhs, int c, int x |
|
||||
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, value) and
|
||||
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, testIsTrue) and
|
||||
right = rhs.getLeftOperand() and
|
||||
x = int_value(rhs.getRight()) and
|
||||
k = c - x
|
||||
)
|
||||
}
|
||||
|
||||
// op - x == c => op == (c+x)
|
||||
private predicate sub_eq(Instruction test, Operand op, int k, boolean areEqual, AbstractValue value) {
|
||||
exists(SubInstruction sub, int c, int x |
|
||||
compares_eq(test, sub.getAUse(), c, areEqual, value) and
|
||||
op = sub.getLeftOperand() and
|
||||
x = int_value(sub.getRight()) and
|
||||
k = c + x
|
||||
)
|
||||
or
|
||||
exists(PointerSubInstruction sub, int c, int x |
|
||||
compares_eq(test, sub.getAUse(), c, areEqual, value) and
|
||||
op = sub.getLeftOperand() and
|
||||
x = int_value(sub.getRight()) and
|
||||
k = c + x
|
||||
)
|
||||
}
|
||||
|
||||
// left + x == right + c => left == right + (c-x)
|
||||
// left == (right + x) + c => left == right + (c+x)
|
||||
private predicate add_eq(
|
||||
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, AbstractValue value
|
||||
CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue
|
||||
) {
|
||||
exists(AddInstruction lhs, int c, int x |
|
||||
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, value) and
|
||||
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, testIsTrue) and
|
||||
(
|
||||
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
|
||||
or
|
||||
@@ -1101,7 +733,7 @@ private predicate add_eq(
|
||||
)
|
||||
or
|
||||
exists(AddInstruction rhs, int c, int x |
|
||||
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, value) and
|
||||
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, testIsTrue) and
|
||||
(
|
||||
right = rhs.getLeftOperand() and x = int_value(rhs.getRight())
|
||||
or
|
||||
@@ -1111,7 +743,7 @@ private predicate add_eq(
|
||||
)
|
||||
or
|
||||
exists(PointerAddInstruction lhs, int c, int x |
|
||||
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, value) and
|
||||
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, testIsTrue) and
|
||||
(
|
||||
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
|
||||
or
|
||||
@@ -1121,7 +753,7 @@ private predicate add_eq(
|
||||
)
|
||||
or
|
||||
exists(PointerAddInstruction rhs, int c, int x |
|
||||
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, value) and
|
||||
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, testIsTrue) and
|
||||
(
|
||||
right = rhs.getLeftOperand() and x = int_value(rhs.getRight())
|
||||
or
|
||||
@@ -1131,30 +763,5 @@ private predicate add_eq(
|
||||
)
|
||||
}
|
||||
|
||||
// left + x == right + c => left == right + (c-x)
|
||||
private predicate add_eq(
|
||||
Instruction test, Operand left, int k, boolean areEqual, AbstractValue value
|
||||
) {
|
||||
exists(AddInstruction lhs, int c, int x |
|
||||
compares_eq(test, lhs.getAUse(), c, areEqual, value) and
|
||||
(
|
||||
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
|
||||
or
|
||||
left = lhs.getRightOperand() and x = int_value(lhs.getLeft())
|
||||
) and
|
||||
k = c - x
|
||||
)
|
||||
or
|
||||
exists(PointerAddInstruction lhs, int c, int x |
|
||||
compares_eq(test, lhs.getAUse(), c, areEqual, value) and
|
||||
(
|
||||
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
|
||||
or
|
||||
left = lhs.getRightOperand() and x = int_value(lhs.getLeft())
|
||||
) and
|
||||
k = c - x
|
||||
)
|
||||
}
|
||||
|
||||
/** The int value of integer constant expression. */
|
||||
private int int_value(Instruction i) { result = i.(IntegerConstantInstruction).getValue().toInt() }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// NOTE: There are two copies of this file, and they must be kept identical:
|
||||
// - semmle/code/cpp/controlflow/SubBasicBlocks.qll
|
||||
// - semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll [now DEPRECATED]
|
||||
// - semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll
|
||||
//
|
||||
// The second one is a private copy of the `SubBasicBlocks` library for
|
||||
// internal use by the data flow library. Having an extra copy prevents
|
||||
|
||||
@@ -28,6 +28,6 @@ import cpp
|
||||
deprecated module DataFlow {
|
||||
private import semmle.code.cpp.dataflow.internal.DataFlowImplSpecific
|
||||
private import codeql.dataflow.DataFlow
|
||||
import DataFlowMake<Location, CppOldDataFlow>
|
||||
import DataFlowMake<CppOldDataFlow>
|
||||
import semmle.code.cpp.dataflow.internal.DataFlowImpl1
|
||||
}
|
||||
|
||||
@@ -29,6 +29,6 @@ deprecated module TaintTracking {
|
||||
private import semmle.code.cpp.dataflow.internal.DataFlowImplSpecific
|
||||
private import semmle.code.cpp.dataflow.internal.TaintTrackingImplSpecific
|
||||
private import codeql.dataflow.TaintTracking
|
||||
import TaintFlowMake<Location, CppOldDataFlow, CppOldTaintTracking>
|
||||
import TaintFlowMake<CppOldDataFlow, CppOldTaintTracking>
|
||||
import semmle.code.cpp.dataflow.internal.tainttracking1.TaintTrackingImpl
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*
|
||||
* Provides a local analysis for identifying where a variable address
|
||||
* is effectively taken. Array-like offsets are allowed to pass through but
|
||||
* not field-like offsets.
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*/
|
||||
|
||||
private import cpp
|
||||
private import DataFlowPrivate
|
||||
private import DataFlowUtil
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*/
|
||||
|
||||
private import semmle.code.cpp.Location
|
||||
private import DataFlowImplSpecific
|
||||
private import codeql.dataflow.internal.DataFlowImpl
|
||||
import MakeImpl<Location, CppOldDataFlow>
|
||||
import MakeImpl<CppOldDataFlow>
|
||||
|
||||
@@ -285,8 +285,6 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
|
||||
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
|
||||
|
||||
int accessPathLimit() { result = 5 }
|
||||
|
||||
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
|
||||
|
||||
predicate sourceGrouping(Node source, string sourceGroup) {
|
||||
|
||||
@@ -285,8 +285,6 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
|
||||
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
|
||||
|
||||
int accessPathLimit() { result = 5 }
|
||||
|
||||
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
|
||||
|
||||
predicate sourceGrouping(Node source, string sourceGroup) {
|
||||
|
||||
@@ -285,8 +285,6 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
|
||||
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
|
||||
|
||||
int accessPathLimit() { result = 5 }
|
||||
|
||||
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
|
||||
|
||||
predicate sourceGrouping(Node source, string sourceGroup) {
|
||||
|
||||
@@ -285,8 +285,6 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
|
||||
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
|
||||
|
||||
int accessPathLimit() { result = 5 }
|
||||
|
||||
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
|
||||
|
||||
predicate sourceGrouping(Node source, string sourceGroup) {
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*/
|
||||
|
||||
private import semmle.code.cpp.Location
|
||||
private import DataFlowImplSpecific
|
||||
private import codeql.dataflow.internal.DataFlowImplCommon
|
||||
import MakeImplCommon<Location, CppOldDataFlow>
|
||||
import MakeImplCommon<CppOldDataFlow>
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*
|
||||
* Provides consistency queries for checking invariants in the language-specific
|
||||
* data-flow classes and predicates.
|
||||
*/
|
||||
@@ -10,7 +8,7 @@ private import DataFlowImplSpecific
|
||||
private import TaintTrackingImplSpecific
|
||||
private import codeql.dataflow.internal.DataFlowImplConsistency
|
||||
|
||||
private module Input implements InputSig<Location, CppOldDataFlow> {
|
||||
private module Input implements InputSig<CppOldDataFlow> {
|
||||
predicate argHasPostUpdateExclude(Private::ArgumentNode n) {
|
||||
// Is the null pointer (or something that's not really a pointer)
|
||||
exists(n.asExpr().getValue())
|
||||
@@ -26,4 +24,4 @@ private module Input implements InputSig<Location, CppOldDataFlow> {
|
||||
}
|
||||
}
|
||||
|
||||
module Consistency = MakeConsistency<Location, CppOldDataFlow, CppOldTaintTracking, Input>;
|
||||
module Consistency = MakeConsistency<CppOldDataFlow, CppOldTaintTracking, Input>;
|
||||
|
||||
@@ -285,8 +285,6 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
|
||||
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
|
||||
|
||||
int accessPathLimit() { result = 5 }
|
||||
|
||||
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
|
||||
|
||||
predicate sourceGrouping(Node source, string sourceGroup) {
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*
|
||||
* Provides C++-specific definitions for use in the data flow library.
|
||||
*/
|
||||
|
||||
private import semmle.code.cpp.Location
|
||||
private import codeql.dataflow.DataFlow
|
||||
|
||||
module Private {
|
||||
@@ -16,7 +13,7 @@ module Public {
|
||||
import DataFlowUtil
|
||||
}
|
||||
|
||||
module CppOldDataFlow implements InputSig<Location> {
|
||||
module CppOldDataFlow implements InputSig {
|
||||
import Private
|
||||
import Public
|
||||
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*/
|
||||
|
||||
private import cpp
|
||||
private import DataFlowUtil
|
||||
private import DataFlowDispatch
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*
|
||||
* Provides C++-specific definitions for use in the data flow library.
|
||||
*/
|
||||
|
||||
@@ -105,7 +103,7 @@ class Node extends TNode {
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
deprecated predicate hasLocationInfo(
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*
|
||||
* Provides a class for handling variables in the data flow analysis.
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// NOTE: There are two copies of this file, and they must be kept identical:
|
||||
// - semmle/code/cpp/controlflow/SubBasicBlocks.qll
|
||||
// - semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll [now DEPRECATED]
|
||||
// - semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll
|
||||
//
|
||||
// The second one is a private copy of the `SubBasicBlocks` library for
|
||||
// internal use by the data flow library. Having an extra copy prevents
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*
|
||||
* Provides C++-specific definitions for use in the taint tracking library.
|
||||
*/
|
||||
|
||||
private import semmle.code.cpp.Location
|
||||
private import codeql.dataflow.TaintTracking
|
||||
private import DataFlowImplSpecific
|
||||
|
||||
module CppOldTaintTracking implements InputSig<Location, CppOldDataFlow> {
|
||||
module CppOldTaintTracking implements InputSig<CppOldDataFlow> {
|
||||
import TaintTrackingUtil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/**
|
||||
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
|
||||
*
|
||||
* Provides classes for performing local (intra-procedural) and
|
||||
* global (inter-procedural) taint-tracking analyses.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
/**
|
||||
* DEPRECATED: Use `Global` and `GlobalWithState` instead.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.dataflow.internal.TaintTrackingUtil as Public
|
||||
|
||||
module Private {
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
/**
|
||||
* DEPRECATED: Use `Global` and `GlobalWithState` instead.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.dataflow.internal.TaintTrackingUtil as Public
|
||||
|
||||
module Private {
|
||||
|
||||
@@ -28,6 +28,6 @@ import cpp
|
||||
module DataFlow {
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplSpecific
|
||||
private import codeql.dataflow.DataFlow
|
||||
import DataFlowMake<Location, CppDataFlow>
|
||||
import DataFlowMake<CppDataFlow>
|
||||
import semmle.code.cpp.ir.dataflow.internal.DataFlowImpl1
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ module TaintTracking {
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplSpecific
|
||||
private import semmle.code.cpp.ir.dataflow.internal.TaintTrackingImplSpecific
|
||||
private import codeql.dataflow.TaintTracking
|
||||
private import semmle.code.cpp.Location
|
||||
import TaintFlowMake<Location, CppDataFlow, CppTaintTracking>
|
||||
import TaintFlowMake<CppDataFlow, CppTaintTracking>
|
||||
import semmle.code.cpp.ir.dataflow.internal.tainttracking1.TaintTrackingImpl
|
||||
}
|
||||
|
||||
@@ -1322,23 +1322,3 @@ class CoYieldExpr extends UnaryOperation, @co_yield {
|
||||
|
||||
override int getPrecedence() { result = 2 }
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression representing the re-use of another expression.
|
||||
*
|
||||
* In some specific cases an expression may be referred to outside its
|
||||
* original context. A re-use expression wraps any such reference. A
|
||||
* re-use expression can for example occur as the qualifier of an implicit
|
||||
* destructor called on a temporary object, where the original use of the
|
||||
* expression is in the definition of the temporary.
|
||||
*/
|
||||
class ReuseExpr extends Expr, @reuseexpr {
|
||||
override string getAPrimaryQlClass() { result = "ReuseExpr" }
|
||||
|
||||
override string toString() { result = "reuse of " + this.getReusedExpr().toString() }
|
||||
|
||||
/**
|
||||
* Gets the expression that is being re-used.
|
||||
*/
|
||||
Expr getReusedExpr() { expr_reuse(underlyingElement(this), unresolveElement(result)) }
|
||||
}
|
||||
|
||||
@@ -24,6 +24,6 @@ import cpp
|
||||
module DataFlow {
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplSpecific
|
||||
private import codeql.dataflow.DataFlow
|
||||
import DataFlowMake<Location, CppDataFlow>
|
||||
import DataFlowMake<CppDataFlow>
|
||||
import semmle.code.cpp.ir.dataflow.internal.DataFlowImpl1
|
||||
}
|
||||
|
||||
@@ -23,6 +23,6 @@ module TaintTracking {
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplSpecific
|
||||
private import semmle.code.cpp.ir.dataflow.internal.TaintTrackingImplSpecific
|
||||
private import codeql.dataflow.TaintTracking
|
||||
import TaintFlowMake<Location, CppDataFlow, CppTaintTracking>
|
||||
import TaintFlowMake<CppDataFlow, CppTaintTracking>
|
||||
import semmle.code.cpp.ir.dataflow.internal.tainttracking1.TaintTrackingImpl
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
private import semmle.code.cpp.Location
|
||||
private import DataFlowImplSpecific
|
||||
private import codeql.dataflow.internal.DataFlowImpl
|
||||
import MakeImpl<Location, CppDataFlow>
|
||||
import MakeImpl<CppDataFlow>
|
||||
|
||||
@@ -285,8 +285,6 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
|
||||
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
|
||||
|
||||
int accessPathLimit() { result = 5 }
|
||||
|
||||
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
|
||||
|
||||
predicate sourceGrouping(Node source, string sourceGroup) {
|
||||
|
||||
@@ -285,8 +285,6 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
|
||||
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
|
||||
|
||||
int accessPathLimit() { result = 5 }
|
||||
|
||||
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
|
||||
|
||||
predicate sourceGrouping(Node source, string sourceGroup) {
|
||||
|
||||
@@ -285,8 +285,6 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
|
||||
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
|
||||
|
||||
int accessPathLimit() { result = 5 }
|
||||
|
||||
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
|
||||
|
||||
predicate sourceGrouping(Node source, string sourceGroup) {
|
||||
|
||||
@@ -285,8 +285,6 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
|
||||
int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) }
|
||||
|
||||
int accessPathLimit() { result = 5 }
|
||||
|
||||
FlowFeature getAFeature() { result = any(Configuration config).getAFeature() }
|
||||
|
||||
predicate sourceGrouping(Node source, string sourceGroup) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
private import semmle.code.cpp.Location
|
||||
private import DataFlowImplSpecific
|
||||
private import codeql.dataflow.internal.DataFlowImplCommon
|
||||
import MakeImplCommon<Location, CppDataFlow>
|
||||
import MakeImplCommon<CppDataFlow>
|
||||
|
||||
@@ -8,7 +8,7 @@ private import DataFlowImplSpecific
|
||||
private import TaintTrackingImplSpecific
|
||||
private import codeql.dataflow.internal.DataFlowImplConsistency
|
||||
|
||||
private module Input implements InputSig<Location, CppDataFlow> {
|
||||
private module Input implements InputSig<CppDataFlow> {
|
||||
predicate argHasPostUpdateExclude(Private::ArgumentNode n) {
|
||||
// The rules for whether an IR argument gets a post-update node are too
|
||||
// complex to model here.
|
||||
@@ -16,4 +16,4 @@ private module Input implements InputSig<Location, CppDataFlow> {
|
||||
}
|
||||
}
|
||||
|
||||
module Consistency = MakeConsistency<Location, CppDataFlow, CppTaintTracking, Input>;
|
||||
module Consistency = MakeConsistency<CppDataFlow, CppTaintTracking, Input>;
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*/
|
||||
|
||||
private import codeql.dataflow.DataFlow
|
||||
private import semmle.code.cpp.Location
|
||||
|
||||
module Private {
|
||||
import DataFlowPrivate
|
||||
@@ -14,7 +13,7 @@ module Public {
|
||||
import DataFlowUtil
|
||||
}
|
||||
|
||||
module CppDataFlow implements InputSig<Location> {
|
||||
module CppDataFlow implements InputSig {
|
||||
import Private
|
||||
import Public
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ private import Node0ToString
|
||||
cached
|
||||
private newtype TIRDataFlowNode =
|
||||
TNode0(Node0Impl node) { DataFlowImplCommon::forceCachingInSameStage() } or
|
||||
TGlobalLikeVariableNode(GlobalLikeVariable var, int indirectionIndex) {
|
||||
TVariableNode(Variable var, int indirectionIndex) {
|
||||
indirectionIndex =
|
||||
[getMinIndirectionsForType(var.getUnspecifiedType()) .. Ssa::getMaxIndirectionsForType(var.getUnspecifiedType())]
|
||||
} or
|
||||
@@ -396,7 +396,7 @@ class Node extends TIRDataFlowNode {
|
||||
* modeling flow in and out of global variables.
|
||||
*/
|
||||
Variable asVariable() {
|
||||
this = TGlobalLikeVariableNode(result, getMinIndirectionsForType(result.getUnspecifiedType()))
|
||||
this = TVariableNode(result, getMinIndirectionsForType(result.getUnspecifiedType()))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -406,7 +406,7 @@ class Node extends TIRDataFlowNode {
|
||||
*/
|
||||
Variable asIndirectVariable(int indirectionIndex) {
|
||||
indirectionIndex > getMinIndirectionsForType(result.getUnspecifiedType()) and
|
||||
this = TGlobalLikeVariableNode(result, indirectionIndex)
|
||||
this = TVariableNode(result, indirectionIndex)
|
||||
}
|
||||
|
||||
/** Gets an indirection of this node's underlying variable, if any. */
|
||||
@@ -448,7 +448,7 @@ class Node extends TIRDataFlowNode {
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
deprecated predicate hasLocationInfo(
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
@@ -1331,7 +1331,6 @@ private import GetConvertedResultExpression
|
||||
|
||||
/** Holds if `node` is an `OperandNode` that should map `node.asExpr()` to `e`. */
|
||||
predicate exprNodeShouldBeOperand(OperandNode node, Expr e, int n) {
|
||||
not exprNodeShouldBeIndirectOperand(_, e, n) and
|
||||
exists(Instruction def |
|
||||
unique( | | getAUse(def)) = node.getOperand() and
|
||||
e = getConvertedResultExpression(def, n)
|
||||
@@ -1348,22 +1347,6 @@ private predicate indirectExprNodeShouldBeIndirectOperand(
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `node` should be an `IndirectOperand` that maps `node.asExpr()` to `e`. */
|
||||
private predicate exprNodeShouldBeIndirectOperand(IndirectOperand node, Expr e, int n) {
|
||||
exists(ArgumentOperand operand |
|
||||
// When an argument (qualifier or positional) is a prvalue and the
|
||||
// parameter (qualifier or positional) is a (const) reference, IR
|
||||
// construction introduces a temporary `IRVariable`. The `VariableAddress`
|
||||
// instruction has the argument as its `getConvertedResultExpression`
|
||||
// result. However, the instruction actually represents the _address_ of
|
||||
// the argument. So to fix this mismatch, we have the indirection of the
|
||||
// `VariableAddressInstruction` map to the expression.
|
||||
node.hasOperandAndIndirectionIndex(operand, 1) and
|
||||
e = getConvertedResultExpression(operand.getDef(), n) and
|
||||
operand.getDef().(VariableAddressInstruction).getIRVariable() instanceof IRTempVariable
|
||||
)
|
||||
}
|
||||
|
||||
private predicate exprNodeShouldBeIndirectOutNode(IndirectArgumentOutNode node, Expr e, int n) {
|
||||
exists(CallInstruction call |
|
||||
call.getStaticCallTarget() instanceof Constructor and
|
||||
@@ -1376,7 +1359,6 @@ private predicate exprNodeShouldBeIndirectOutNode(IndirectArgumentOutNode node,
|
||||
predicate exprNodeShouldBeInstruction(Node node, Expr e, int n) {
|
||||
not exprNodeShouldBeOperand(_, e, n) and
|
||||
not exprNodeShouldBeIndirectOutNode(_, e, n) and
|
||||
not exprNodeShouldBeIndirectOperand(_, e, n) and
|
||||
e = getConvertedResultExpression(node.asInstruction(), n)
|
||||
}
|
||||
|
||||
@@ -1409,8 +1391,7 @@ abstract private class ExprNodeBase extends Node {
|
||||
private predicate exprNodeShouldBe(Expr e, int n) {
|
||||
exprNodeShouldBeInstruction(_, e, n) or
|
||||
exprNodeShouldBeOperand(_, e, n) or
|
||||
exprNodeShouldBeIndirectOutNode(_, e, n) or
|
||||
exprNodeShouldBeIndirectOperand(_, e, n)
|
||||
exprNodeShouldBeIndirectOutNode(_, e, n)
|
||||
}
|
||||
|
||||
private class InstructionExprNode extends ExprNodeBase, InstructionNode {
|
||||
@@ -1552,12 +1533,6 @@ private class IndirectArgumentOutExprNode extends ExprNodeBase, IndirectArgument
|
||||
final override Expr getConvertedExpr(int n) { exprNodeShouldBeIndirectOutNode(this, result, n) }
|
||||
}
|
||||
|
||||
private class IndirectOperandExprNode extends ExprNodeBase instanceof IndirectOperand {
|
||||
IndirectOperandExprNode() { exprNodeShouldBeIndirectOperand(this, _, _) }
|
||||
|
||||
final override Expr getConvertedExpr(int n) { exprNodeShouldBeIndirectOperand(this, result, n) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression, viewed as a node in a data flow graph.
|
||||
*/
|
||||
@@ -1776,18 +1751,15 @@ class DefinitionByReferenceNode extends IndirectArgumentOutNode {
|
||||
}
|
||||
|
||||
/**
|
||||
* A `Node` corresponding to a global (or `static` local) variable in the
|
||||
* program, as opposed to the value of that variable at some particular point.
|
||||
* This is used to model flow through global variables (and `static` local
|
||||
* variables).
|
||||
*
|
||||
* There is no `VariableNode` for non-`static` local variables.
|
||||
* A `Node` corresponding to a variable in the program, as opposed to the
|
||||
* value of that variable at some particular point. This can be used for
|
||||
* modeling flow in and out of global variables.
|
||||
*/
|
||||
class VariableNode extends Node, TGlobalLikeVariableNode {
|
||||
class VariableNode extends Node, TVariableNode {
|
||||
Variable v;
|
||||
int indirectionIndex;
|
||||
|
||||
VariableNode() { this = TGlobalLikeVariableNode(v, indirectionIndex) }
|
||||
VariableNode() { this = TVariableNode(v, indirectionIndex) }
|
||||
|
||||
/** Gets the variable corresponding to this node. */
|
||||
Variable getVariable() { result = v }
|
||||
|
||||
@@ -10,12 +10,13 @@ private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs as FIO
|
||||
private import semmle.code.cpp.ir.internal.IRCppLanguage
|
||||
private import semmle.code.cpp.ir.dataflow.internal.ModelUtil
|
||||
private import DataFlowPrivate
|
||||
private import ssa0.SsaInternals as SsaInternals0
|
||||
import SsaInternalsCommon
|
||||
|
||||
private module SourceVariables {
|
||||
cached
|
||||
private newtype TSourceVariable =
|
||||
TMkSourceVariable(BaseSourceVariable base, int ind) {
|
||||
TMkSourceVariable(SsaInternals0::SourceVariable base, int ind) {
|
||||
ind = [0 .. countIndirectionsForCppType(base.getLanguageType()) + 1]
|
||||
}
|
||||
|
||||
@@ -29,7 +30,7 @@ private module SourceVariables {
|
||||
}
|
||||
|
||||
class SourceVariable extends TSourceVariable {
|
||||
BaseSourceVariable base;
|
||||
SsaInternals0::SourceVariable base;
|
||||
int ind;
|
||||
|
||||
SourceVariable() { this = TMkSourceVariable(base, ind) }
|
||||
@@ -41,7 +42,7 @@ private module SourceVariables {
|
||||
* Gets the base source variable (i.e., the variable without any
|
||||
* indirections) of this source variable.
|
||||
*/
|
||||
BaseSourceVariable getBaseVariable() { result = base }
|
||||
SsaInternals0::SourceVariable getBaseVariable() { result = base }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = repeatStars(this.getIndirection()) + base.toString() }
|
||||
@@ -103,9 +104,17 @@ predicate hasRawIndirectInstruction(Instruction instr, int indirectionIndex) {
|
||||
|
||||
cached
|
||||
private newtype TDefOrUseImpl =
|
||||
TDefAddressImpl(BaseIRVariable v) or
|
||||
TDefImpl(BaseSourceVariableInstruction base, Operand address, int indirectionIndex) {
|
||||
isDef(_, _, address, base, _, indirectionIndex)
|
||||
isDef(_, _, address, base, _, indirectionIndex) and
|
||||
(
|
||||
// We only include the definition if the SSA pruning stage
|
||||
// concluded that the definition is live after the write.
|
||||
any(SsaInternals0::Def def).getAddressOperand() = address
|
||||
or
|
||||
// Since the pruning stage doesn't know about global variables we can't use the above check to
|
||||
// rule out dead assignments to globals.
|
||||
base.(VariableAddressInstruction).getAstVariable() instanceof GlobalLikeVariable
|
||||
)
|
||||
} or
|
||||
TUseImpl(BaseSourceVariableInstruction base, Operand operand, int indirectionIndex) {
|
||||
isUse(_, operand, base, _, indirectionIndex) and
|
||||
@@ -124,7 +133,8 @@ private newtype TDefOrUseImpl =
|
||||
TIteratorDef(
|
||||
Operand iteratorDerefAddress, BaseSourceVariableInstruction container, int indirectionIndex
|
||||
) {
|
||||
isIteratorDef(container, iteratorDerefAddress, _, _, indirectionIndex)
|
||||
isIteratorDef(container, iteratorDerefAddress, _, _, indirectionIndex) and
|
||||
any(SsaInternals0::Def def | def.isIteratorDef()).getAddressOperand() = iteratorDerefAddress
|
||||
} or
|
||||
TIteratorUse(
|
||||
Operand iteratorAddress, BaseSourceVariableInstruction container, int indirectionIndex
|
||||
@@ -257,64 +267,24 @@ private predicate sourceVariableHasBaseAndIndex(SourceVariable v, BaseSourceVari
|
||||
}
|
||||
|
||||
abstract class DefImpl extends DefOrUseImpl {
|
||||
Operand address;
|
||||
int ind;
|
||||
|
||||
bindingset[ind]
|
||||
DefImpl() { any() }
|
||||
|
||||
override int getIndirectionIndex() { result = ind }
|
||||
|
||||
override string toString() { result = "Def of " + this.getSourceVariable() }
|
||||
|
||||
abstract int getIndirection();
|
||||
|
||||
abstract Node0Impl getValue();
|
||||
|
||||
abstract predicate isCertain();
|
||||
|
||||
abstract Node0Impl getValue();
|
||||
}
|
||||
|
||||
/** An initial definition of an `IRVariable`'s address. */
|
||||
private class DefAddressImpl extends DefImpl, TDefAddressImpl {
|
||||
BaseIRVariable v;
|
||||
|
||||
DefAddressImpl() {
|
||||
this = TDefAddressImpl(v) and
|
||||
ind = 0
|
||||
}
|
||||
|
||||
final override int getIndirection() { result = 0 }
|
||||
|
||||
final override predicate isCertain() { any() }
|
||||
|
||||
final override Node0Impl getValue() { none() }
|
||||
|
||||
final override predicate hasIndexInBlock(IRBlock block, int index) {
|
||||
block = v.getIRVariable().getEnclosingIRFunction().getEntryBlock() and
|
||||
index = 0
|
||||
}
|
||||
|
||||
override Cpp::Location getLocation() { result = v.getIRVariable().getLocation() }
|
||||
|
||||
final override SourceVariable getSourceVariable() {
|
||||
result.getBaseVariable() = v and
|
||||
result.getIndirection() = 0
|
||||
}
|
||||
|
||||
final override BaseSourceVariableInstruction getBase() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An SSA definition that has an associated `Operand` representing the address
|
||||
* that is being written to.
|
||||
*/
|
||||
abstract private class OperandBasedDef extends DefImpl {
|
||||
Operand address;
|
||||
|
||||
bindingset[ind]
|
||||
OperandBasedDef() { any() }
|
||||
|
||||
Operand getAddressOperand() { result = address }
|
||||
|
||||
override int getIndirectionIndex() { result = ind }
|
||||
|
||||
override string toString() { result = "Def of " + this.getSourceVariable() }
|
||||
|
||||
override Cpp::Location getLocation() { result = this.getAddressOperand().getUse().getLocation() }
|
||||
|
||||
final override predicate hasIndexInBlock(IRBlock block, int index) {
|
||||
@@ -322,7 +292,7 @@ abstract private class OperandBasedDef extends DefImpl {
|
||||
}
|
||||
}
|
||||
|
||||
private class DirectDef extends OperandBasedDef, TDefImpl {
|
||||
private class DirectDef extends DefImpl, TDefImpl {
|
||||
BaseSourceVariableInstruction base;
|
||||
|
||||
DirectDef() { this = TDefImpl(base, address, ind) }
|
||||
@@ -336,7 +306,7 @@ private class DirectDef extends OperandBasedDef, TDefImpl {
|
||||
override predicate isCertain() { isDef(true, _, address, base, _, ind) }
|
||||
}
|
||||
|
||||
private class IteratorDef extends OperandBasedDef, TIteratorDef {
|
||||
private class IteratorDef extends DefImpl, TIteratorDef {
|
||||
BaseSourceVariableInstruction container;
|
||||
|
||||
IteratorDef() { this = TIteratorDef(address, container, ind) }
|
||||
@@ -1014,6 +984,17 @@ predicate fromPhiNode(SsaPhiNode nodeFrom, Node nodeTo) {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a write at index `i` in basic block `bb` to variable `v` that's
|
||||
* subsequently read (as determined by the SSA pruning stage).
|
||||
*/
|
||||
private predicate variableWriteCand(IRBlock bb, int i, SourceVariable v) {
|
||||
exists(SsaInternals0::Def def, SsaInternals0::SourceVariable v0 |
|
||||
def.asDefOrUse().hasIndexInBlock(bb, i, v0) and
|
||||
v0 = v.getBaseVariable()
|
||||
)
|
||||
}
|
||||
|
||||
private predicate sourceVariableIsGlobal(
|
||||
SourceVariable sv, GlobalLikeVariable global, IRFunction func, int indirectionIndex
|
||||
) {
|
||||
@@ -1037,14 +1018,16 @@ private module SsaInput implements SsaImplCommon::InputSig<Location> {
|
||||
predicate variableWrite(IRBlock bb, int i, SourceVariable v, boolean certain) {
|
||||
DataFlowImplCommon::forceCachingInSameStage() and
|
||||
(
|
||||
exists(DefImpl def | def.hasIndexInBlock(bb, i, v) |
|
||||
if def.isCertain() then certain = true else certain = false
|
||||
)
|
||||
or
|
||||
exists(GlobalDefImpl global |
|
||||
global.hasIndexInBlock(bb, i, v) and
|
||||
certain = true
|
||||
)
|
||||
variableWriteCand(bb, i, v) or
|
||||
sourceVariableIsGlobal(v, _, _, _)
|
||||
) and
|
||||
exists(DefImpl def | def.hasIndexInBlock(bb, i, v) |
|
||||
if def.isCertain() then certain = true else certain = false
|
||||
)
|
||||
or
|
||||
exists(GlobalDefImpl global |
|
||||
global.hasIndexInBlock(bb, i, v) and
|
||||
certain = true
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1219,7 +1202,7 @@ class UseOrPhi extends SsaDefOrUse {
|
||||
class Def extends DefOrUse {
|
||||
override DefImpl defOrUse;
|
||||
|
||||
Operand getAddressOperand() { result = defOrUse.(OperandBasedDef).getAddressOperand() }
|
||||
Operand getAddressOperand() { result = defOrUse.getAddressOperand() }
|
||||
|
||||
Instruction getAddress() { result = this.getAddressOperand().getDef() }
|
||||
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
|
||||
private import codeql.dataflow.TaintTracking
|
||||
private import DataFlowImplSpecific
|
||||
private import semmle.code.cpp.Location
|
||||
|
||||
module CppTaintTracking implements InputSig<Location, CppDataFlow> {
|
||||
module CppTaintTracking implements InputSig<CppDataFlow> {
|
||||
import TaintTrackingUtil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,347 @@
|
||||
/**
|
||||
* This module defines an initial SSA pruning stage that doesn't take
|
||||
* indirections into account.
|
||||
*/
|
||||
|
||||
private import codeql.ssa.Ssa as SsaImplCommon
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon
|
||||
private import semmle.code.cpp.models.interfaces.Allocation as Alloc
|
||||
private import semmle.code.cpp.models.interfaces.DataFlow as DataFlow
|
||||
private import semmle.code.cpp.ir.implementation.raw.internal.SideEffects as SideEffects
|
||||
private import semmle.code.cpp.ir.internal.IRCppLanguage
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
|
||||
private import semmle.code.cpp.ir.dataflow.internal.SsaInternalsCommon
|
||||
|
||||
private module SourceVariables {
|
||||
class SourceVariable extends BaseSourceVariable {
|
||||
/**
|
||||
* Gets the base source variable of this `SourceVariable`.
|
||||
*/
|
||||
BaseSourceVariable getBaseVariable() { result = this }
|
||||
}
|
||||
}
|
||||
|
||||
import SourceVariables
|
||||
|
||||
private newtype TDefOrUseImpl =
|
||||
TDefImpl(Operand address) { isDef(_, _, address, _, _, _) } or
|
||||
TUseImpl(Operand operand) {
|
||||
isUse(_, operand, _, _, _) and
|
||||
not isDef(true, _, operand, _, _, _)
|
||||
} or
|
||||
TIteratorDef(BaseSourceVariableInstruction container, Operand iteratorAddress) {
|
||||
isIteratorDef(container, iteratorAddress, _, _, _)
|
||||
} or
|
||||
TIteratorUse(BaseSourceVariableInstruction container, Operand iteratorAddress) {
|
||||
isIteratorUse(container, iteratorAddress, _, _)
|
||||
} or
|
||||
TFinalParameterUse(Parameter p) {
|
||||
any(Indirection indirection).getType() = p.getUnspecifiedType()
|
||||
}
|
||||
|
||||
abstract private class DefOrUseImpl extends TDefOrUseImpl {
|
||||
/** Gets a textual representation of this element. */
|
||||
abstract string toString();
|
||||
|
||||
/** Gets the block of this definition or use. */
|
||||
final IRBlock getBlock() { this.hasIndexInBlock(result, _) }
|
||||
|
||||
/** Holds if this definition or use has index `index` in block `block`. */
|
||||
abstract predicate hasIndexInBlock(IRBlock block, int index);
|
||||
|
||||
final predicate hasIndexInBlock(IRBlock block, int index, SourceVariable sv) {
|
||||
this.hasIndexInBlock(block, index) and
|
||||
sv = this.getSourceVariable()
|
||||
}
|
||||
|
||||
/** Gets the location of this element. */
|
||||
abstract Cpp::Location getLocation();
|
||||
|
||||
abstract BaseSourceVariableInstruction getBase();
|
||||
|
||||
final BaseSourceVariable getBaseSourceVariable() {
|
||||
result = this.getBase().getBaseSourceVariable()
|
||||
}
|
||||
|
||||
/** Gets the variable that is defined or used. */
|
||||
final SourceVariable getSourceVariable() {
|
||||
result.getBaseVariable() = this.getBaseSourceVariable()
|
||||
}
|
||||
|
||||
abstract predicate isCertain();
|
||||
}
|
||||
|
||||
abstract class DefImpl extends DefOrUseImpl {
|
||||
Operand address;
|
||||
|
||||
Operand getAddressOperand() { result = address }
|
||||
|
||||
abstract Node0Impl getValue();
|
||||
|
||||
override string toString() { result = address.toString() }
|
||||
|
||||
override Cpp::Location getLocation() { result = this.getAddressOperand().getLocation() }
|
||||
|
||||
final override predicate hasIndexInBlock(IRBlock block, int index) {
|
||||
this.getAddressOperand().getUse() = block.getInstruction(index)
|
||||
}
|
||||
}
|
||||
|
||||
private class DirectDef extends DefImpl, TDefImpl {
|
||||
DirectDef() { this = TDefImpl(address) }
|
||||
|
||||
override BaseSourceVariableInstruction getBase() { isDef(_, _, address, result, _, _) }
|
||||
|
||||
override Node0Impl getValue() { isDef(_, result, address, _, _, _) }
|
||||
|
||||
override predicate isCertain() { isDef(true, _, address, _, _, _) }
|
||||
}
|
||||
|
||||
private class IteratorDef extends DefImpl, TIteratorDef {
|
||||
BaseSourceVariableInstruction container;
|
||||
|
||||
IteratorDef() { this = TIteratorDef(container, address) }
|
||||
|
||||
override BaseSourceVariableInstruction getBase() { result = container }
|
||||
|
||||
override Node0Impl getValue() { isIteratorDef(_, address, result, _, _) }
|
||||
|
||||
override predicate isCertain() { none() }
|
||||
}
|
||||
|
||||
abstract class UseImpl extends DefOrUseImpl { }
|
||||
|
||||
abstract private class OperandBasedUse extends UseImpl {
|
||||
Operand operand;
|
||||
|
||||
override string toString() { result = operand.toString() }
|
||||
|
||||
final override predicate hasIndexInBlock(IRBlock block, int index) {
|
||||
// Ideally, this would just be implemented as:
|
||||
// ```
|
||||
// operand.getUse() = block.getInstruction(index)
|
||||
// ```
|
||||
// but because the IR generated for a snippet such as
|
||||
// ```
|
||||
// int x = *p++;
|
||||
// ```
|
||||
// looks like
|
||||
// ```
|
||||
// r1(glval<int>) = VariableAddress[x] :
|
||||
// r2(glval<int *>) = VariableAddress[p] :
|
||||
// r3(int *) = Load[p] : &:r2, m1
|
||||
// r4(int) = Constant[1] :
|
||||
// r5(int *) = PointerAdd[4] : r3, r4
|
||||
// m3(int *) = Store[p] : &:r2, r5
|
||||
// r6(int *) = CopyValue : r3
|
||||
// r7(int) = Load[?] : &:r6, ~m2
|
||||
// m2(int) = Store[x] : &:r1, r7
|
||||
// ```
|
||||
// we need to ensure that the `r3` operand of the `CopyValue` instruction isn't seen as a fresh use
|
||||
// of `p` that happens after the increment. So if the base instruction of this use comes from a
|
||||
// post-fix crement operation we set the index of the SSA use that wraps the `r3` operand at the
|
||||
// `CopyValue` instruction to be the same index as the `r3` operand at the `PointerAdd` instruction.
|
||||
// This ensures that the SSA library doesn't create flow from the `PointerAdd` to `r6`.
|
||||
exists(BaseSourceVariableInstruction base | base = this.getBase() |
|
||||
if base.getAst() = any(Cpp::PostfixCrementOperation c).getOperand()
|
||||
then
|
||||
exists(Operand op |
|
||||
op =
|
||||
min(Operand cand, int i |
|
||||
isUse(_, cand, base, _, _) and
|
||||
block.getInstruction(i) = cand.getUse()
|
||||
|
|
||||
cand order by i
|
||||
) and
|
||||
block.getInstruction(index) = op.getUse()
|
||||
)
|
||||
else operand.getUse() = block.getInstruction(index)
|
||||
)
|
||||
}
|
||||
|
||||
final override Cpp::Location getLocation() { result = operand.getLocation() }
|
||||
}
|
||||
|
||||
private class DirectUse extends OperandBasedUse, TUseImpl {
|
||||
DirectUse() { this = TUseImpl(operand) }
|
||||
|
||||
override BaseSourceVariableInstruction getBase() { isUse(_, operand, result, _, _) }
|
||||
|
||||
override predicate isCertain() { isUse(true, operand, _, _, _) }
|
||||
}
|
||||
|
||||
private class IteratorUse extends OperandBasedUse, TIteratorUse {
|
||||
BaseSourceVariableInstruction container;
|
||||
|
||||
IteratorUse() { this = TIteratorUse(container, operand) }
|
||||
|
||||
override BaseSourceVariableInstruction getBase() { result = container }
|
||||
|
||||
override predicate isCertain() { none() }
|
||||
}
|
||||
|
||||
private class FinalParameterUse extends UseImpl, TFinalParameterUse {
|
||||
Parameter p;
|
||||
|
||||
FinalParameterUse() { this = TFinalParameterUse(p) }
|
||||
|
||||
override string toString() { result = p.toString() }
|
||||
|
||||
final override predicate hasIndexInBlock(IRBlock block, int index) {
|
||||
// Ideally, this should always be a `ReturnInstruction`, but if
|
||||
// someone forgets to write a `return` statement in a function
|
||||
// with a non-void return type we generate an `UnreachedInstruction`.
|
||||
// In this case we still want to generate flow out of such functions
|
||||
// if they write to a parameter. So we pick the index of the
|
||||
// `UnreachedInstruction` as the index of this use.
|
||||
// Note that a function may have both a `ReturnInstruction` and an
|
||||
// `UnreachedInstruction`. If that's the case this predicate will
|
||||
// return multiple results. I don't think this is detrimental to
|
||||
// performance, however.
|
||||
exists(Instruction return |
|
||||
return instanceof ReturnInstruction or
|
||||
return instanceof UnreachedInstruction
|
||||
|
|
||||
block.getInstruction(index) = return and
|
||||
return.getEnclosingFunction() = p.getFunction()
|
||||
)
|
||||
}
|
||||
|
||||
final override Cpp::Location getLocation() {
|
||||
// Parameters can have multiple locations. When there's a unique location we use
|
||||
// that one, but if multiple locations exist we default to an unknown location.
|
||||
result = unique( | | p.getLocation())
|
||||
or
|
||||
not exists(unique( | | p.getLocation())) and
|
||||
result instanceof UnknownDefaultLocation
|
||||
}
|
||||
|
||||
override BaseSourceVariableInstruction getBase() {
|
||||
exists(InitializeParameterInstruction init |
|
||||
init.getParameter() = p and
|
||||
// This is always a `VariableAddressInstruction`
|
||||
result = init.getAnOperand().getDef()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isCertain() { any() }
|
||||
}
|
||||
|
||||
private module SsaInput implements SsaImplCommon::InputSig<Location> {
|
||||
import InputSigCommon
|
||||
import SourceVariables
|
||||
|
||||
/**
|
||||
* Holds if the `i`'th write in block `bb` writes to the variable `v`.
|
||||
* `certain` is `true` if the write is guaranteed to overwrite the entire variable.
|
||||
*/
|
||||
predicate variableWrite(IRBlock bb, int i, SourceVariable v, boolean certain) {
|
||||
DataFlowImplCommon::forceCachingInSameStage() and
|
||||
exists(DefImpl def | def.hasIndexInBlock(bb, i, v) |
|
||||
if def.isCertain() then certain = true else certain = false
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the `i`'th read in block `bb` reads to the variable `v`.
|
||||
* `certain` is `true` if the read is guaranteed.
|
||||
*/
|
||||
predicate variableRead(IRBlock bb, int i, SourceVariable v, boolean certain) {
|
||||
exists(UseImpl use | use.hasIndexInBlock(bb, i, v) |
|
||||
if use.isCertain() then certain = true else certain = false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TSsaDefOrUse =
|
||||
TDefOrUse(DefOrUseImpl defOrUse) {
|
||||
defOrUse instanceof UseImpl
|
||||
or
|
||||
// If `defOrUse` is a definition we only include it if the
|
||||
// SSA library concludes that it's live after the write.
|
||||
exists(DefinitionExt def, SourceVariable sv, IRBlock bb, int i |
|
||||
def.definesAt(sv, bb, i, _) and
|
||||
defOrUse.(DefImpl).hasIndexInBlock(bb, i, sv)
|
||||
)
|
||||
} or
|
||||
TPhi(PhiNode phi)
|
||||
|
||||
abstract private class SsaDefOrUse extends TSsaDefOrUse {
|
||||
string toString() { result = "SsaDefOrUse" }
|
||||
|
||||
DefOrUseImpl asDefOrUse() { none() }
|
||||
|
||||
PhiNode asPhi() { none() }
|
||||
|
||||
abstract Location getLocation();
|
||||
}
|
||||
|
||||
class DefOrUse extends TDefOrUse, SsaDefOrUse {
|
||||
DefOrUseImpl defOrUse;
|
||||
|
||||
DefOrUse() { this = TDefOrUse(defOrUse) }
|
||||
|
||||
final override DefOrUseImpl asDefOrUse() { result = defOrUse }
|
||||
|
||||
final override Location getLocation() { result = defOrUse.getLocation() }
|
||||
|
||||
final SourceVariable getSourceVariable() { result = defOrUse.getSourceVariable() }
|
||||
}
|
||||
|
||||
class Phi extends TPhi, SsaDefOrUse {
|
||||
PhiNode phi;
|
||||
|
||||
Phi() { this = TPhi(phi) }
|
||||
|
||||
final override PhiNode asPhi() { result = phi }
|
||||
|
||||
final override Location getLocation() { result = phi.getBasicBlock().getLocation() }
|
||||
}
|
||||
|
||||
class UseOrPhi extends SsaDefOrUse {
|
||||
UseOrPhi() {
|
||||
this.asDefOrUse() instanceof UseImpl
|
||||
or
|
||||
this instanceof Phi
|
||||
}
|
||||
|
||||
final override Location getLocation() {
|
||||
result = this.asDefOrUse().getLocation() or result = this.(Phi).getLocation()
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
result = this.asDefOrUse().toString()
|
||||
or
|
||||
this instanceof Phi and
|
||||
result = "Phi"
|
||||
}
|
||||
}
|
||||
|
||||
class Def extends DefOrUse {
|
||||
override DefImpl defOrUse;
|
||||
|
||||
Operand getAddressOperand() { result = defOrUse.getAddressOperand() }
|
||||
|
||||
Instruction getAddress() { result = this.getAddressOperand().getDef() }
|
||||
|
||||
Node0Impl getValue() { result = defOrUse.getValue() }
|
||||
|
||||
override string toString() { result = this.asDefOrUse().toString() }
|
||||
|
||||
BaseSourceVariableInstruction getBase() { result = defOrUse.getBase() }
|
||||
|
||||
predicate isIteratorDef() { defOrUse instanceof IteratorDef }
|
||||
}
|
||||
|
||||
private module SsaImpl = SsaImplCommon::Make<Location, SsaInput>;
|
||||
|
||||
class PhiNode extends SsaImpl::DefinitionExt {
|
||||
PhiNode() {
|
||||
this instanceof SsaImpl::PhiNode or
|
||||
this instanceof SsaImpl::PhiReadNode
|
||||
}
|
||||
}
|
||||
|
||||
class DefinitionExt = SsaImpl::DefinitionExt;
|
||||
@@ -90,15 +90,6 @@ class CaseEdge extends EdgeKind, TCaseEdge {
|
||||
* Gets the largest value of the switch expression for which control will flow along this edge.
|
||||
*/
|
||||
final string getMaxValue() { result = maxValue }
|
||||
|
||||
/**
|
||||
* Gets the unique value of the switch expression for which control will
|
||||
* flow along this edge, if any.
|
||||
*/
|
||||
final string getValue() {
|
||||
minValue = maxValue and
|
||||
result = minValue
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,12 +38,6 @@ private int getBinaryInstructionValue(BinaryInstruction instr) {
|
||||
or
|
||||
instr instanceof DivInstruction and result = div(left, right)
|
||||
or
|
||||
instr instanceof BitOrInstruction and result = bitOr(left, right)
|
||||
or
|
||||
instr instanceof BitAndInstruction and result = bitAnd(left, right)
|
||||
or
|
||||
instr instanceof BitXorInstruction and result = bitXor(left, right)
|
||||
or
|
||||
instr instanceof CompareEQInstruction and result = compareEQ(left, right)
|
||||
or
|
||||
instr instanceof CompareNEInstruction and result = compareNE(left, right)
|
||||
|
||||
@@ -38,12 +38,6 @@ private int getBinaryInstructionValue(BinaryInstruction instr) {
|
||||
or
|
||||
instr instanceof DivInstruction and result = div(left, right)
|
||||
or
|
||||
instr instanceof BitOrInstruction and result = bitOr(left, right)
|
||||
or
|
||||
instr instanceof BitAndInstruction and result = bitAnd(left, right)
|
||||
or
|
||||
instr instanceof BitXorInstruction and result = bitXor(left, right)
|
||||
or
|
||||
instr instanceof CompareEQInstruction and result = compareEQ(left, right)
|
||||
or
|
||||
instr instanceof CompareNEInstruction and result = compareNE(left, right)
|
||||
|
||||
@@ -11,7 +11,6 @@ private import InstructionTag
|
||||
private import TranslatedCondition
|
||||
private import TranslatedElement
|
||||
private import TranslatedExpr
|
||||
private import TranslatedCall
|
||||
private import TranslatedStmt
|
||||
private import TranslatedFunction
|
||||
private import TranslatedGlobalVar
|
||||
|
||||
@@ -85,14 +85,10 @@ newtype TInstructionTag =
|
||||
// The next three cases handle generation of branching for __except handling.
|
||||
TryExceptCompareNegativeOneBranch() or
|
||||
TryExceptCompareZeroBranch() or
|
||||
TryExceptCompareOneBranch() or
|
||||
ImplicitDestructorTag(int index) {
|
||||
exists(Expr e | exists(e.getImplicitDestructorCall(index))) or
|
||||
exists(Stmt s | exists(s.getImplicitDestructorCall(index)))
|
||||
}
|
||||
TryExceptCompareOneBranch()
|
||||
|
||||
class InstructionTag extends TInstructionTag {
|
||||
final string toString() { result = getInstructionTagId(this) }
|
||||
final string toString() { result = "Tag" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -259,8 +255,4 @@ string getInstructionTagId(TInstructionTag tag) {
|
||||
tag = TryExceptCompareZeroBranch() and result = "TryExceptCompareZeroBranch"
|
||||
or
|
||||
tag = TryExceptCompareOneBranch() and result = "TryExceptCompareOneBranch"
|
||||
or
|
||||
exists(int index |
|
||||
tag = ImplicitDestructorTag(index) and result = "ImplicitDestructor(" + index + ")"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ private CallInstruction getTranslatedCallInstruction(Call call) {
|
||||
* of a higher-level constructor (e.g. the allocator call in a `NewExpr`).
|
||||
*/
|
||||
abstract class TranslatedCall extends TranslatedExpr {
|
||||
final override TranslatedElement getChildInternal(int id) {
|
||||
final override TranslatedElement getChild(int id) {
|
||||
// We choose the child's id in the order of evaluation.
|
||||
// The qualifier is evaluated before the call target, because the value of
|
||||
// the call target may depend on the value of the qualifier for virtual
|
||||
@@ -47,19 +47,13 @@ abstract class TranslatedCall extends TranslatedExpr {
|
||||
else result = this.getFirstCallTargetInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getSideEffects().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getSideEffects() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = CallTag() and
|
||||
opcode instanceof Opcode::Call and
|
||||
resultType = getTypeForPRValue(this.getCallResultType())
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getQualifier() and
|
||||
result = this.getFirstCallTargetInstruction(kind)
|
||||
or
|
||||
@@ -93,7 +87,7 @@ abstract class TranslatedCall extends TranslatedExpr {
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = CallTag() and
|
||||
result = this.getSideEffects().getFirstInstruction(kind)
|
||||
}
|
||||
@@ -231,7 +225,7 @@ abstract class TranslatedSideEffects extends TranslatedElement {
|
||||
)
|
||||
}
|
||||
|
||||
final override Instruction getChildSuccessorInternal(TranslatedElement te, EdgeKind kind) {
|
||||
final override Instruction getChildSuccessor(TranslatedElement te, EdgeKind kind) {
|
||||
exists(int i |
|
||||
this.getChild(i) = te and
|
||||
if exists(this.getChild(i + 1))
|
||||
@@ -240,10 +234,6 @@ abstract class TranslatedSideEffects extends TranslatedElement {
|
||||
)
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() {
|
||||
result = this.getChild(max(int i | exists(this.getChild(i))))
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
|
||||
none()
|
||||
}
|
||||
@@ -256,18 +246,7 @@ abstract class TranslatedSideEffects extends TranslatedElement {
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
if exists(this.getAChild())
|
||||
then result = this.getChild(max(int i | exists(this.getChild(i)))).getALastInstruction()
|
||||
else
|
||||
// If there are no side effects, the "last" instruction should be the parent call's last
|
||||
// instruction, so that implicit destructors can be inserted in the right place.
|
||||
result = this.getParent().getInstruction(CallTag())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
/** Gets the primary instruction to be associated with each side effect instruction. */
|
||||
abstract Instruction getPrimaryInstruction();
|
||||
@@ -294,8 +273,8 @@ abstract class TranslatedDirectCall extends TranslatedCall {
|
||||
resultType = getFunctionGLValueType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
result = TranslatedCall.super.getInstructionSuccessorInternal(tag, kind)
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
result = TranslatedCall.super.getInstructionSuccessor(tag, kind)
|
||||
or
|
||||
tag = CallTargetTag() and
|
||||
result = this.getFirstArgumentOrCallInstruction(kind)
|
||||
@@ -388,16 +367,6 @@ class TranslatedStructorCall extends TranslatedFunctionCall {
|
||||
context = this.getParent() and
|
||||
result = context.getReceiver()
|
||||
)
|
||||
or
|
||||
exists(Stmt parent |
|
||||
expr = parent.getAnImplicitDestructorCall() and
|
||||
result = getTranslatedExpr(expr.getQualifier().getFullyConverted()).getResult()
|
||||
)
|
||||
or
|
||||
exists(Expr parent |
|
||||
expr = parent.getAnImplicitDestructorCall() and
|
||||
result = getTranslatedExpr(expr.getQualifier().getFullyConverted()).getResult()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate hasQualifier() { any() }
|
||||
@@ -447,25 +416,19 @@ private int initializeAllocationGroup() { result = 3 }
|
||||
abstract class TranslatedSideEffect extends TranslatedElement {
|
||||
final override TranslatedElement getChild(int n) { none() }
|
||||
|
||||
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
|
||||
final override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getInstruction(OnlyInstructionTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
|
||||
tag = OnlyInstructionTag() and
|
||||
this.sideEffectInstruction(opcode, type)
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
result = this.getParent().getChildSuccessor(this, kind) and
|
||||
tag = OnlyInstructionTag()
|
||||
}
|
||||
|
||||
@@ -50,29 +50,19 @@ abstract class TranslatedFlexibleCondition extends TranslatedCondition, Conditio
|
||||
{
|
||||
TranslatedFlexibleCondition() { this = TTranslatedFlexibleCondition(expr) }
|
||||
|
||||
final override predicate handlesDestructorsExplicitly() { none() } // TODO: this needs to be revisted when we get unnamed destructors
|
||||
|
||||
final override TranslatedElement getChild(int id) { id = 0 and result = this.getOperand() }
|
||||
|
||||
final override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getOperand().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
final override Instruction getALastInstructionInternal() {
|
||||
result = this.getOperand().getALastInstruction()
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
|
||||
abstract TranslatedCondition getOperand();
|
||||
}
|
||||
@@ -98,16 +88,12 @@ class TranslatedParenthesisCondition extends TranslatedFlexibleCondition {
|
||||
abstract class TranslatedNativeCondition extends TranslatedCondition, TTranslatedNativeCondition {
|
||||
TranslatedNativeCondition() { this = TTranslatedNativeCondition(expr) }
|
||||
|
||||
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
}
|
||||
|
||||
abstract class TranslatedBinaryLogicalOperation extends TranslatedNativeCondition, ConditionContext {
|
||||
override BinaryLogicalOperation expr;
|
||||
|
||||
final override predicate handlesDestructorsExplicitly() { none() } // TODO: this needs to be revisted when we get unnamed destructors
|
||||
|
||||
final override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getLeftOperand()
|
||||
or
|
||||
@@ -118,19 +104,11 @@ abstract class TranslatedBinaryLogicalOperation extends TranslatedNativeConditio
|
||||
result = this.getLeftOperand().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
final override Instruction getALastInstructionInternal() {
|
||||
result = this.getLeftOperand().getALastInstruction()
|
||||
or
|
||||
result = this.getRightOperand().getALastInstruction()
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
final TranslatedCondition getLeftOperand() {
|
||||
result = getTranslatedCondition(expr.getLeftOperand().getFullyConverted())
|
||||
@@ -184,25 +162,19 @@ class TranslatedValueCondition extends TranslatedCondition, TTranslatedValueCond
|
||||
result = this.getValueExpr().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(ValueConditionConditionalBranchTag())
|
||||
}
|
||||
|
||||
final override predicate handlesDestructorsExplicitly() { none() } // TODO: this needs to be revisted when we get unnamed destructors
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = ValueConditionConditionalBranchTag() and
|
||||
opcode instanceof Opcode::ConditionalBranch and
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getValueExpr() and
|
||||
result = this.getInstruction(ValueConditionConditionalBranchTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = ValueConditionConditionalBranchTag() and
|
||||
(
|
||||
kind instanceof TrueEdge and
|
||||
|
||||
@@ -60,10 +60,6 @@ abstract class TranslatedLocalVariableDeclaration extends TranslatedVariableInit
|
||||
*/
|
||||
abstract LocalVariable getVariable();
|
||||
|
||||
final override TranslatedElement getChild(int id) {
|
||||
result = TranslatedVariableInitialization.super.getChildInternal(id)
|
||||
}
|
||||
|
||||
final override Type getTargetType() { result = getVariableType(this.getVariable()) }
|
||||
|
||||
final override TranslatedInitialization getInitialization() {
|
||||
@@ -156,13 +152,7 @@ class TranslatedStaticLocalVariableDeclarationEntry extends TranslatedDeclaratio
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
final override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(DynamicInitializationConditionalBranchTag())
|
||||
or
|
||||
result = this.getInstruction(DynamicInitializationFlagStoreTag())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = DynamicInitializationFlagAddressTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = this.getInstruction(DynamicInitializationFlagLoadTag())
|
||||
@@ -188,7 +178,7 @@ class TranslatedStaticLocalVariableDeclarationEntry extends TranslatedDeclaratio
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and
|
||||
result = this.getInstruction(DynamicInitializationFlagConstantTag()) and
|
||||
kind instanceof GotoEdge
|
||||
|
||||
@@ -20,14 +20,10 @@ private import SideEffects
|
||||
* they were explicit nodes in the expression tree, rather than as implicit
|
||||
* nodes as in the regular AST representation.
|
||||
*/
|
||||
Element getRealParent(Expr expr) {
|
||||
private Element getRealParent(Expr expr) {
|
||||
result = expr.getParentWithConversions()
|
||||
or
|
||||
result.(Destructor).getADestruction() = expr
|
||||
or
|
||||
result.(Expr).getAnImplicitDestructorCall() = expr
|
||||
or
|
||||
result.(Stmt).getAnImplicitDestructorCall() = expr
|
||||
}
|
||||
|
||||
IRUserVariable getIRUserVariable(Declaration decl, Variable var) {
|
||||
@@ -40,43 +36,12 @@ IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) {
|
||||
result.getTag() = tag
|
||||
}
|
||||
|
||||
/** Gets an operand of `op`. */
|
||||
private Expr getAnOperand(Operation op) { result = op.getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the number of nested operands of `op`. For example,
|
||||
* `getNumberOfNestedBinaryOperands((1 + 2) + 3))` is `3`.
|
||||
*/
|
||||
private int getNumberOfNestedBinaryOperands(Operation op) { result = count(getAnOperand*(op)) }
|
||||
|
||||
/**
|
||||
* Holds if `op` should not be translated to a `ConstantInstruction` as part of
|
||||
* IR generation, even if the value of `op` is constant.
|
||||
*/
|
||||
private predicate ignoreConstantValue(Operation op) {
|
||||
op instanceof BitwiseAndExpr
|
||||
or
|
||||
op instanceof BitwiseOrExpr
|
||||
or
|
||||
op instanceof BitwiseXorExpr
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `expr` is a constant of a type that can be replaced directly with
|
||||
* its value in the IR. This does not include address constants as we have no
|
||||
* means to express those as QL values.
|
||||
*/
|
||||
predicate isIRConstant(Expr expr) {
|
||||
exists(expr.getValue()) and
|
||||
// We avoid constant folding certain operations since it's often useful to
|
||||
// mark one of those as a source in dataflow, and if the operation is
|
||||
// constant folded it's not possible to mark its operands as a source (or
|
||||
// sink).
|
||||
// But to avoid creating an outrageous amount of IR from very large
|
||||
// constant expressions we fall back to constant folding if the operation
|
||||
// has more than 50 operands (i.e., 1 + 2 + 3 + 4 + ... + 50)
|
||||
if ignoreConstantValue(expr) then getNumberOfNestedBinaryOperands(expr) > 50 else any()
|
||||
}
|
||||
predicate isIRConstant(Expr expr) { exists(expr.getValue()) }
|
||||
|
||||
// Pulled out for performance. See
|
||||
// https://github.com/github/codeql-coreql-team/issues/1044.
|
||||
@@ -127,14 +92,6 @@ private predicate ignoreExprAndDescendants(Expr expr) {
|
||||
exists(BuiltInVarArgsStart vaStartExpr |
|
||||
vaStartExpr.getLastNamedParameter().getFullyConverted() = expr
|
||||
)
|
||||
or
|
||||
// suppress destructors of temporary variables until proper support is added for them.
|
||||
exists(Expr parent | parent.getAnImplicitDestructorCall() = expr)
|
||||
or
|
||||
exists(Stmt parent |
|
||||
parent.getAnImplicitDestructorCall() = expr and
|
||||
expr.(DestructorCall).getQualifier() instanceof ReuseExpr
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,6 +105,12 @@ private predicate ignoreExprOnly(Expr expr) {
|
||||
newExpr.getAllocatorCall() = expr
|
||||
)
|
||||
or
|
||||
exists(DeleteOrDeleteArrayExpr deleteExpr |
|
||||
// Ignore the destructor call as we don't model it yet. Don't ignore
|
||||
// its arguments, though, as they are the arguments to the deallocator.
|
||||
deleteExpr.getDestructorCall() = expr
|
||||
)
|
||||
or
|
||||
// The extractor deliberately emits an `ErrorExpr` as the first argument to
|
||||
// the allocator call, if any, of a `NewOrNewArrayExpr`. That `ErrorExpr`
|
||||
// should not be translated.
|
||||
@@ -155,11 +118,6 @@ private predicate ignoreExprOnly(Expr expr) {
|
||||
or
|
||||
not translateFunction(getEnclosingFunction(expr)) and
|
||||
not Raw::varHasIRFunc(getEnclosingVariable(expr))
|
||||
or
|
||||
exists(DeleteOrDeleteArrayExpr deleteExpr |
|
||||
// Ignore the destructor call, because the duplicated qualifier breaks control flow.
|
||||
deleteExpr.getDestructorCall() = expr
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -650,27 +608,16 @@ newtype TTranslatedElement =
|
||||
TTranslatedInitialization(Expr expr) {
|
||||
not ignoreExpr(expr) and
|
||||
(
|
||||
exists(Initializer init | init.getExpr().getFullyConverted() = expr)
|
||||
or
|
||||
exists(ClassAggregateLiteral initList | initList.getAFieldExpr(_).getFullyConverted() = expr)
|
||||
or
|
||||
exists(Initializer init | init.getExpr().getFullyConverted() = expr) or
|
||||
exists(ClassAggregateLiteral initList | initList.getAFieldExpr(_).getFullyConverted() = expr) or
|
||||
exists(ArrayOrVectorAggregateLiteral initList |
|
||||
initList.getAnElementExpr(_).getFullyConverted() = expr
|
||||
)
|
||||
or
|
||||
exists(ReturnStmt returnStmt |
|
||||
returnStmt.getExpr().getFullyConverted() = expr and
|
||||
hasReturnValue(returnStmt.getEnclosingFunction())
|
||||
)
|
||||
or
|
||||
exists(ConstructorFieldInit fieldInit | fieldInit.getExpr().getFullyConverted() = expr)
|
||||
or
|
||||
exists(NewExpr newExpr | newExpr.getInitializer().getFullyConverted() = expr)
|
||||
or
|
||||
exists(ThrowExpr throw | throw.getExpr().getFullyConverted() = expr)
|
||||
or
|
||||
exists(TemporaryObjectExpr temp | temp.getExpr() = expr)
|
||||
or
|
||||
) or
|
||||
exists(ReturnStmt returnStmt | returnStmt.getExpr().getFullyConverted() = expr) or
|
||||
exists(ConstructorFieldInit fieldInit | fieldInit.getExpr().getFullyConverted() = expr) or
|
||||
exists(NewExpr newExpr | newExpr.getInitializer().getFullyConverted() = expr) or
|
||||
exists(ThrowExpr throw | throw.getExpr().getFullyConverted() = expr) or
|
||||
exists(TemporaryObjectExpr temp | temp.getExpr() = expr) or
|
||||
exists(LambdaExpression lambda | lambda.getInitializer().getFullyConverted() = expr)
|
||||
)
|
||||
} or
|
||||
@@ -783,13 +730,9 @@ newtype TTranslatedElement =
|
||||
// The declaration/initialization part of a `ConditionDeclExpr`
|
||||
TTranslatedConditionDecl(ConditionDeclExpr expr) { not ignoreExpr(expr) } or
|
||||
// The side effects of a `Call`
|
||||
TTranslatedCallSideEffects(CallOrAllocationExpr expr) {
|
||||
not ignoreExpr(expr) and
|
||||
not ignoreSideEffects(expr)
|
||||
} or
|
||||
TTranslatedCallSideEffects(CallOrAllocationExpr expr) { not ignoreSideEffects(expr) } or
|
||||
// The non-argument-specific side effect of a `Call`
|
||||
TTranslatedCallSideEffect(Expr expr, SideEffectOpcode opcode) {
|
||||
not ignoreExpr(expr) and
|
||||
not ignoreSideEffects(expr) and
|
||||
opcode = getCallSideEffectOpcode(expr)
|
||||
} or
|
||||
@@ -807,8 +750,9 @@ newtype TTranslatedElement =
|
||||
// Constructor calls lack a qualifier (`this`) expression, so we need to handle the side effects
|
||||
// on `*this` without an `Expr`.
|
||||
TTranslatedStructorQualifierSideEffect(Call call, SideEffectOpcode opcode) {
|
||||
not ignoreExpr(call) and
|
||||
not ignoreSideEffects(call) and
|
||||
// Don't bother with destructor calls for now, since we won't see very many of them in the IR
|
||||
// until we start injecting implicit destructor calls.
|
||||
call instanceof ConstructorCall and
|
||||
opcode = getASideEffectOpcode(call, -1)
|
||||
} or
|
||||
@@ -922,23 +866,6 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
1 + sum(TranslatedElement child | child = this.getChildByRank(_) | child.getDescendantCount())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this element has implicit destructor calls that should follow it.
|
||||
*/
|
||||
predicate hasAnImplicitDestructorCall() { none() }
|
||||
|
||||
/**
|
||||
* Gets the child index of the first destructor call that should be executed after this `TranslatedElement`
|
||||
*/
|
||||
int getFirstDestructorCallIndex() { none() }
|
||||
|
||||
/**
|
||||
* Holds if this `TranslatedElement` includes any destructor calls that must be performed after
|
||||
* it in its `getChildSuccessorInternal`, `getInstructionSuccessorInternal`, and
|
||||
* `getALastInstructionInternal` relations, rather than needing them inserted.
|
||||
*/
|
||||
predicate handlesDestructorsExplicitly() { none() }
|
||||
|
||||
private int getUniqueId() {
|
||||
if not exists(this.getParent())
|
||||
then result = 0
|
||||
@@ -974,81 +901,15 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
/**
|
||||
* Gets the successor instruction of the instruction that was generated by
|
||||
* this element for tag `tag`. The successor edge kind is specified by `kind`.
|
||||
* This predicate does not usually include destructors, which are inserted as
|
||||
* part of `getInstructionSuccessor` unless `handlesDestructorsExplicitly`
|
||||
* holds.
|
||||
*/
|
||||
abstract Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind);
|
||||
|
||||
/**
|
||||
* Gets the successor instruction of the instruction that was generated by
|
||||
* this element for tag `tag`. The successor edge kind is specified by `kind`.
|
||||
*/
|
||||
final Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
if
|
||||
this.hasAnImplicitDestructorCall() and
|
||||
this.getInstruction(tag) = this.getALastInstructionInternal() and
|
||||
not this.handlesDestructorsExplicitly()
|
||||
then
|
||||
result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind) and
|
||||
kind instanceof GotoEdge
|
||||
else result = this.getInstructionSuccessorInternal(tag, kind)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an instruction within this `TranslatedElement` (including its transitive children) which
|
||||
* will be followed by an instruction outside the `TranslatedElement`.
|
||||
*/
|
||||
final Instruction getALastInstruction() {
|
||||
if this.hasAnImplicitDestructorCall() and not this.handlesDestructorsExplicitly()
|
||||
then result = this.getChild(max(int n | exists(this.getChild(n)))).getALastInstruction() // last destructor
|
||||
else result = this.getALastInstructionInternal()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an instruction within this `TranslatedElement` (including its transitive children) which
|
||||
* will be followed by an instruction outside the `TranslatedElement`.
|
||||
* This predicate does not usually include destructors, which are inserted as
|
||||
* part of `getALastInstruction` unless `handlesDestructorsExplicitly` holds.
|
||||
*/
|
||||
abstract Instruction getALastInstructionInternal();
|
||||
|
||||
TranslatedElement getLastChild() { none() }
|
||||
|
||||
/**
|
||||
* Gets the successor instruction to which control should flow after the
|
||||
* child element specified by `child` has finished execution. The successor
|
||||
* edge kind is specified by `kind`.
|
||||
* This predicate does not usually include destructors, which are inserted as
|
||||
* part of `getChildSuccessor` unless `handlesDestructorsExplicitly` holds.
|
||||
*/
|
||||
Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
|
||||
abstract Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind);
|
||||
|
||||
/**
|
||||
* Gets the successor instruction to which control should flow after the
|
||||
* child element specified by `child` has finished execution. The successor
|
||||
* edge kind is specified by `kind`.
|
||||
*/
|
||||
final Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
(
|
||||
if
|
||||
// this is the last child and we need to handle destructors for it
|
||||
this.hasAnImplicitDestructorCall() and
|
||||
not this.handlesDestructorsExplicitly() and
|
||||
child = this.getLastChild()
|
||||
then result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind)
|
||||
else result = this.getChildSuccessorInternal(child, kind)
|
||||
)
|
||||
or
|
||||
not this.handlesDestructorsExplicitly() and
|
||||
exists(int id |
|
||||
id >= this.getFirstDestructorCallIndex() and
|
||||
child = this.getChild(id) and
|
||||
if id = max(int n | exists(this.getChild(n)))
|
||||
then result = this.getParent().getChildSuccessor(this, kind)
|
||||
else result = this.getChild(id + 1).getFirstInstruction(kind)
|
||||
)
|
||||
}
|
||||
abstract Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind);
|
||||
|
||||
/**
|
||||
* Gets the instruction to which control should flow if an exception is thrown
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -114,11 +114,7 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(ExitFunctionTag())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
tag = EnterFunctionTag() and
|
||||
@@ -154,7 +150,7 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
|
||||
)
|
||||
}
|
||||
|
||||
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int paramIndex | child = this.getParameter(paramIndex) |
|
||||
if
|
||||
exists(func.getParameter(paramIndex + 1)) or
|
||||
@@ -383,13 +379,7 @@ abstract class TranslatedParameter extends TranslatedElement {
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
if this.hasIndirection()
|
||||
then result = this.getInstruction(InitializerIndirectStoreTag())
|
||||
else result = this.getInstruction(InitializerStoreTag())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
tag = InitializerVariableAddressTag() and
|
||||
result = this.getInstruction(InitializerStoreTag())
|
||||
@@ -407,9 +397,7 @@ abstract class TranslatedParameter extends TranslatedElement {
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = InitializerVariableAddressTag() and
|
||||
@@ -623,23 +611,15 @@ class TranslatedConstructorInitList extends TranslatedElement, InitializationCon
|
||||
else result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getLastChild().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() {
|
||||
result = this.getChild(max(int id | exists(this.getChild(id))))
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Function getFunction() { result = func }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int id |
|
||||
child = this.getChild(id) and
|
||||
if exists(this.getChild(id + 1))
|
||||
@@ -698,23 +678,15 @@ class TranslatedDestructorDestructionList extends TranslatedElement,
|
||||
else result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getChild(max(int id | exists(this.getChild(id)))).getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() {
|
||||
result = this.getChild(max(int id | exists(this.getChild(id))))
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Function getFunction() { result = func }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int id |
|
||||
child = this.getChild(id) and
|
||||
if exists(this.getChild(id + 1))
|
||||
@@ -756,20 +728,7 @@ class TranslatedReadEffects extends TranslatedElement, TTranslatedReadEffects {
|
||||
else result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
if exists(this.getAChild())
|
||||
then
|
||||
result =
|
||||
max(TranslatedElement child, int id | child = this.getChild(id) | child order by id)
|
||||
.getFirstInstruction(any(GotoEdge goto))
|
||||
else result = this.getParent().getChildSuccessor(this, any(GotoEdge goto))
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() {
|
||||
result = this.getChild(max(int id | exists(this.getChild(id))))
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int id | child = this.getChild(id) |
|
||||
if exists(TranslatedReadEffect child2, int id2 | id2 > id and child2 = this.getChild(id2))
|
||||
then
|
||||
@@ -787,7 +746,7 @@ class TranslatedReadEffects extends TranslatedElement, TTranslatedReadEffects {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
}
|
||||
|
||||
private TranslatedThisReadEffect getTranslatedThisReadEffect(Function func) {
|
||||
@@ -801,9 +760,9 @@ private TranslatedParameterReadEffect getTranslatedParameterReadEffect(Parameter
|
||||
abstract class TranslatedReadEffect extends TranslatedElement {
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
@@ -813,10 +772,6 @@ abstract class TranslatedReadEffect extends TranslatedElement {
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
opcode instanceof Opcode::ReturnIndirection and
|
||||
tag = OnlyInstructionTag() and
|
||||
|
||||
@@ -27,10 +27,6 @@ class TranslatedStaticStorageDurationVarInit extends TranslatedRootElement,
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(ExitFunctionTag())
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int n) {
|
||||
n = 1 and
|
||||
result = getTranslatedInitialization(var.getInitializer().getExpr().getFullyConverted())
|
||||
@@ -62,7 +58,7 @@ class TranslatedStaticStorageDurationVarInit extends TranslatedRootElement,
|
||||
type = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
tag = EnterFunctionTag() and
|
||||
@@ -85,7 +81,7 @@ class TranslatedStaticStorageDurationVarInit extends TranslatedRootElement,
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getChild(1) and
|
||||
result = this.getInstruction(ReturnTag()) and
|
||||
kind instanceof GotoEdge
|
||||
|
||||
@@ -35,19 +35,13 @@ abstract class InitializationContext extends TranslatedElement {
|
||||
* declarations, `return` statements, and `throw` expressions.
|
||||
*/
|
||||
abstract class TranslatedVariableInitialization extends TranslatedElement, InitializationContext {
|
||||
TranslatedElement getChildInternal(int id) { id = 0 and result = this.getInitialization() }
|
||||
final override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() }
|
||||
|
||||
final override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getInstruction(InitializerVariableAddressTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInitialization().getALastInstruction()
|
||||
or
|
||||
not exists(this.getInitialization()) and result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = InitializerVariableAddressTag() and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
@@ -59,7 +53,7 @@ abstract class TranslatedVariableInitialization extends TranslatedElement, Initi
|
||||
resultType = getTypeForPRValue(this.getTargetType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
(
|
||||
tag = InitializerVariableAddressTag() and
|
||||
if this.hasUninitializedInstruction()
|
||||
@@ -77,7 +71,7 @@ abstract class TranslatedVariableInitialization extends TranslatedElement, Initi
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and
|
||||
result = this.getInitializationSuccessor(kind)
|
||||
}
|
||||
@@ -183,11 +177,7 @@ abstract class TranslatedListInitialization extends TranslatedInitialization, In
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getChild(max(int i | exists(this.getChild(i)))).getALastInstruction()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int index |
|
||||
child = this.getChild(index) and
|
||||
if exists(this.getChild(index + 1))
|
||||
@@ -200,9 +190,7 @@ abstract class TranslatedListInitialization extends TranslatedInitialization, In
|
||||
none()
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getTargetAddress() { result = this.getContext().getTargetAddress() }
|
||||
|
||||
@@ -272,22 +260,18 @@ class TranslatedSimpleDirectInitialization extends TranslatedDirectInitializatio
|
||||
not expr instanceof StringLiteral
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(InitializerStoreTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = InitializerStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getTypeForPRValue(this.getContext().getTargetType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = InitializerStoreTag() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitializer() and
|
||||
result = this.getInstruction(InitializerStoreTag()) and
|
||||
kind instanceof GotoEdge
|
||||
@@ -312,12 +296,6 @@ class TranslatedSimpleDirectInitialization extends TranslatedDirectInitializatio
|
||||
class TranslatedStringLiteralInitialization extends TranslatedDirectInitialization {
|
||||
override StringLiteral expr;
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
if this.zeroInitRange(_, _)
|
||||
then result = this.getInstruction(ZeroPadStringStoreTag())
|
||||
else result = this.getInstruction(InitializerStoreTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
// Load the string literal to make it a prvalue of type `char[len]`
|
||||
tag = InitializerLoadStringTag() and
|
||||
@@ -359,7 +337,7 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
tag = InitializerLoadStringTag() and
|
||||
result = this.getInstruction(InitializerStoreTag())
|
||||
@@ -389,7 +367,7 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitializer() and
|
||||
result = this.getInstruction(InitializerLoadStringTag()) and
|
||||
kind instanceof GotoEdge
|
||||
@@ -479,22 +457,16 @@ class TranslatedConstructorInitialization extends TranslatedDirectInitialization
|
||||
{
|
||||
override ConstructorCall expr;
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInitializer().getALastInstruction()
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitializer() and result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getInitializer() }
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
none()
|
||||
}
|
||||
@@ -586,29 +558,23 @@ class TranslatedExplicitFieldInitialization extends TranslatedFieldInitializatio
|
||||
this = TTranslatedExplicitFieldInitialization(ast, field, expr, position)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInitialization().getALastInstruction()
|
||||
}
|
||||
|
||||
override Instruction getTargetAddress() {
|
||||
result = this.getInstruction(this.getFieldAddressTag())
|
||||
}
|
||||
|
||||
override Type getTargetType() { result = field.getUnspecifiedType() }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = this.getFieldAddressTag() and
|
||||
result = this.getInitialization().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() }
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getInitialization() }
|
||||
|
||||
private TranslatedInitialization getInitialization() {
|
||||
result = getTranslatedInitialization(expr)
|
||||
}
|
||||
@@ -629,10 +595,6 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization,
|
||||
{
|
||||
TranslatedFieldValueInitialization() { this = TTranslatedFieldValueInitialization(ast, field) }
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(this.getFieldDefaultValueStoreTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
TranslatedFieldInitialization.super.hasInstruction(opcode, tag, resultType)
|
||||
or
|
||||
@@ -645,7 +607,7 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization,
|
||||
resultType = getTypeForPRValue(field.getUnspecifiedType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
tag = this.getFieldAddressTag() and
|
||||
@@ -677,7 +639,7 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization,
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
@@ -727,7 +689,7 @@ abstract class TranslatedElementInitialization extends TranslatedElement {
|
||||
resultType = getTypeForGLValue(this.getElementType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = this.getElementIndexTag() and
|
||||
result = this.getInstruction(this.getElementAddressTag()) and
|
||||
kind instanceof GotoEdge
|
||||
@@ -781,24 +743,20 @@ class TranslatedExplicitElementInitialization extends TranslatedElementInitializ
|
||||
this = TTranslatedExplicitElementInitialization(initList, elementIndex, position)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInitialization().getALastInstruction()
|
||||
}
|
||||
|
||||
override Instruction getTargetAddress() {
|
||||
result = this.getInstruction(this.getElementAddressTag())
|
||||
}
|
||||
|
||||
override Type getTargetType() { result = this.getElementType() }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
result = TranslatedElementInitialization.super.getInstructionSuccessorInternal(tag, kind)
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
result = TranslatedElementInitialization.super.getInstructionSuccessor(tag, kind)
|
||||
or
|
||||
tag = this.getElementAddressTag() and
|
||||
result = this.getInitialization().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
@@ -830,10 +788,6 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
this = TTranslatedElementValueInitialization(initList, elementIndex, elementCount)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(this.getElementDefaultValueStoreTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
TranslatedElementInitialization.super.hasInstruction(opcode, tag, resultType)
|
||||
or
|
||||
@@ -846,8 +800,8 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
resultType = this.getDefaultValueType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
result = TranslatedElementInitialization.super.getInstructionSuccessorInternal(tag, kind)
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
result = TranslatedElementInitialization.super.getInstructionSuccessor(tag, kind)
|
||||
or
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
@@ -882,7 +836,7 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
@@ -922,13 +876,11 @@ abstract class TranslatedStructorCallFromStructor extends TranslatedElement, Str
|
||||
|
||||
final override Function getFunction() { result = getEnclosingFunction(call) }
|
||||
|
||||
final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
final override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getStructorCall() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getStructorCall() }
|
||||
|
||||
final TranslatedExpr getStructorCall() { result = getTranslatedExpr(call) }
|
||||
}
|
||||
|
||||
@@ -942,17 +894,13 @@ abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStru
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getStructorCall().getALastInstruction()
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode instanceof Opcode::ConvertToNonVirtualBase and
|
||||
resultType = getTypeForGLValue(call.getTarget().getDeclaringType())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = this.getStructorCall().getFirstInstruction(kind)
|
||||
}
|
||||
@@ -999,17 +947,11 @@ class TranslatedConstructorDelegationInit extends TranslatedConstructorCallFromC
|
||||
result = this.getStructorCall().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getStructorCall().getALastInstruction()
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
final override Instruction getReceiver() {
|
||||
result = getTranslatedFunction(this.getFunction()).getInitializeThisInstruction()
|
||||
@@ -1067,8 +1009,6 @@ class TranslatedConstructorBareInit extends TranslatedElement, TTranslatedConstr
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() { none() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
@@ -1077,9 +1017,9 @@ class TranslatedConstructorBareInit extends TranslatedElement, TTranslatedConstr
|
||||
|
||||
override Declaration getFunction() { result = this.getParent().getFunction() }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
}
|
||||
|
||||
TranslatedConstructorBareInit getTranslatedConstructorBareInit(ConstructorInit init) {
|
||||
|
||||
@@ -138,7 +138,7 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
|
||||
result = "1"
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
// Generate -1 -> Compare condition
|
||||
tag = TryExceptGenerateNegativeOne() and
|
||||
kind instanceof GotoEdge and
|
||||
@@ -202,7 +202,7 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
child = this.getTranslatedCondition() and
|
||||
result = this.getInstruction(TryExceptGenerateNegativeOne())
|
||||
@@ -211,14 +211,6 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getTranslatedHandler() }
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getTranslatedHandler().getALastInstruction()
|
||||
or
|
||||
result = this.getInstruction(UnwindTag())
|
||||
}
|
||||
|
||||
private TranslatedExpr getTranslatedCondition() {
|
||||
result = getTranslatedExpr(tryExcept.getCondition())
|
||||
}
|
||||
@@ -243,41 +235,6 @@ abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt {
|
||||
|
||||
TranslatedStmt() { this = TTranslatedStmt(stmt) }
|
||||
|
||||
abstract TranslatedElement getChildInternal(int id);
|
||||
|
||||
final override TranslatedElement getChild(int id) {
|
||||
result = this.getChildInternal(id)
|
||||
or
|
||||
exists(int destructorIndex, int tempDestructorCount |
|
||||
result.(TranslatedExpr).getExpr() = stmt.getImplicitDestructorCall(destructorIndex) and
|
||||
id = this.getFirstDestructorCallIndex() + destructorIndex - tempDestructorCount and
|
||||
// suppress destructors of temporary variables until proper support is added for them.
|
||||
tempDestructorCount =
|
||||
count(DestructorCall call, int tempIndex |
|
||||
stmt.getImplicitDestructorCall(tempIndex) = call and
|
||||
tempIndex < destructorIndex and
|
||||
call.getQualifier() instanceof ReuseExpr
|
||||
|
|
||||
call
|
||||
) and
|
||||
not stmt.getImplicitDestructorCall(destructorIndex).getQualifier() instanceof ReuseExpr
|
||||
)
|
||||
}
|
||||
|
||||
final override int getFirstDestructorCallIndex() {
|
||||
result = max(int childId | exists(this.getChildInternal(childId))) + 1
|
||||
or
|
||||
not exists(this.getChildInternal(_)) and result = 0
|
||||
}
|
||||
|
||||
final override predicate hasAnImplicitDestructorCall() {
|
||||
exists(stmt.getAnImplicitDestructorCall()) and
|
||||
// suppress destructors of temporary variables until proper support is added for them.
|
||||
exists(Expr expr | stmt.getAnImplicitDestructorCall().getQualifier() = expr |
|
||||
not expr instanceof ReuseExpr
|
||||
)
|
||||
}
|
||||
|
||||
final override string toString() { result = stmt.toString() }
|
||||
|
||||
final override Locatable getAst() { result = stmt }
|
||||
@@ -295,29 +252,25 @@ class TranslatedEmptyStmt extends TranslatedStmt {
|
||||
stmt instanceof SwitchCase
|
||||
}
|
||||
|
||||
override TranslatedElement getChildInternal(int id) { none() }
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getInstruction(OnlyInstructionTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode instanceof Opcode::NoOp and
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -328,7 +281,7 @@ class TranslatedEmptyStmt extends TranslatedStmt {
|
||||
class TranslatedDeclStmt extends TranslatedStmt {
|
||||
override DeclStmt stmt;
|
||||
|
||||
override TranslatedElement getChildInternal(int id) { result = this.getDeclarationEntry(id) }
|
||||
override TranslatedElement getChild(int id) { result = this.getDeclarationEntry(id) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
@@ -341,12 +294,6 @@ class TranslatedDeclStmt extends TranslatedStmt {
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getChild(this.getChildCount() - 1).getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getChild(this.getChildCount() - 1) }
|
||||
|
||||
private int getChildCount() { result = count(this.getDeclarationEntry(_)) }
|
||||
|
||||
IRDeclarationEntry getIRDeclarationEntry(int index) {
|
||||
@@ -371,9 +318,9 @@ class TranslatedDeclStmt extends TranslatedStmt {
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int index |
|
||||
child = this.getDeclarationEntry(index) and
|
||||
if index = (this.getChildCount() - 1)
|
||||
@@ -388,7 +335,7 @@ class TranslatedExprStmt extends TranslatedStmt {
|
||||
|
||||
TranslatedExpr getExpr() { result = getTranslatedExpr(stmt.getExpr().getFullyConverted()) }
|
||||
|
||||
override TranslatedElement getChildInternal(int id) { id = 0 and result = this.getExpr() }
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = this.getExpr() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
@@ -398,15 +345,9 @@ class TranslatedExprStmt extends TranslatedStmt {
|
||||
result = this.getExpr().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getExpr().getALastInstruction()
|
||||
}
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getExpr() }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getExpr() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
@@ -418,21 +359,6 @@ abstract class TranslatedReturnStmt extends TranslatedStmt {
|
||||
final TranslatedFunction getEnclosingFunction() {
|
||||
result = getTranslatedFunction(stmt.getEnclosingFunction())
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int id |
|
||||
child = this.getChild(id) and
|
||||
id >= this.getFirstDestructorCallIndex() and
|
||||
(
|
||||
result = this.getChild(id + 1).getFirstInstruction(kind)
|
||||
or
|
||||
not exists(this.getChild(id + 1)) and
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
final override predicate handlesDestructorsExplicitly() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -442,19 +368,7 @@ class TranslatedReturnValueStmt extends TranslatedReturnStmt, TranslatedVariable
|
||||
TranslatedReturnValueStmt() { stmt.hasExpr() and hasReturnValue(stmt.getEnclosingFunction()) }
|
||||
|
||||
final override Instruction getInitializationSuccessor(EdgeKind kind) {
|
||||
if this.hasAnImplicitDestructorCall()
|
||||
then result = this.getChild(1).getFirstInstruction(kind)
|
||||
else result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
result = TranslatedVariableInitialization.super.getChildSuccessorInternal(child, kind)
|
||||
or
|
||||
result = TranslatedReturnStmt.super.getChildSuccessorInternal(child, kind)
|
||||
}
|
||||
|
||||
final override TranslatedElement getChildInternal(int id) {
|
||||
result = TranslatedVariableInitialization.super.getChildInternal(id)
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
}
|
||||
|
||||
final override Type getTargetType() { result = this.getEnclosingFunction().getReturnType() }
|
||||
@@ -476,7 +390,7 @@ class TranslatedReturnVoidExpressionStmt extends TranslatedReturnStmt {
|
||||
stmt.hasExpr() and not hasReturnValue(stmt.getEnclosingFunction())
|
||||
}
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and
|
||||
result = this.getExpr()
|
||||
}
|
||||
@@ -485,31 +399,21 @@ class TranslatedReturnVoidExpressionStmt extends TranslatedReturnStmt {
|
||||
result = this.getExpr().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
if this.hasAnImplicitDestructorCall()
|
||||
then result = this.getChild(max(int id | exists(this.getChild(id)))).getALastInstruction()
|
||||
else result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode instanceof Opcode::NoOp and
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
if this.hasAnImplicitDestructorCall()
|
||||
then result = this.getChild(1).getFirstInstruction(kind)
|
||||
else result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getExpr() and
|
||||
result = this.getInstruction(OnlyInstructionTag()) and
|
||||
kind instanceof GotoEdge
|
||||
or
|
||||
result = TranslatedReturnStmt.super.getChildSuccessorInternal(child, kind)
|
||||
}
|
||||
|
||||
private TranslatedExpr getExpr() { result = getTranslatedExpr(stmt.getExpr()) }
|
||||
@@ -524,43 +428,25 @@ class TranslatedReturnVoidStmt extends TranslatedReturnStmt {
|
||||
not stmt.hasExpr() and not hasReturnValue(stmt.getEnclosingFunction())
|
||||
}
|
||||
|
||||
override TranslatedElement getChildInternal(int id) { none() }
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getInstruction(OnlyInstructionTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
if this.hasAnImplicitDestructorCall()
|
||||
then result = this.getChild(max(int id | exists(this.getChild(id)))).getALastInstruction()
|
||||
else result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode instanceof Opcode::NoOp and
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
if this.hasAnImplicitDestructorCall()
|
||||
then result = this.getChild(0).getFirstInstruction(kind)
|
||||
else result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int id |
|
||||
this.getChild(id) = child and
|
||||
(
|
||||
result = this.getChild(id + 1).getFirstInstruction(kind)
|
||||
or
|
||||
not exists(this.getChild(id + 1)) and
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
)
|
||||
)
|
||||
}
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -578,16 +464,6 @@ class TranslatedNoValueReturnStmt extends TranslatedReturnStmt, TranslatedVariab
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction(kind)
|
||||
}
|
||||
|
||||
final override TranslatedElement getChildInternal(int id) {
|
||||
result = TranslatedVariableInitialization.super.getChildInternal(id)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
result = TranslatedVariableInitialization.super.getChildSuccessorInternal(child, kind)
|
||||
or
|
||||
result = TranslatedReturnStmt.super.getChildSuccessorInternal(child, kind)
|
||||
}
|
||||
|
||||
final override Type getTargetType() { result = this.getEnclosingFunction().getReturnType() }
|
||||
|
||||
final override TranslatedInitialization getInitialization() { none() }
|
||||
@@ -642,7 +518,7 @@ private class TryOrMicrosoftTryStmt extends Stmt {
|
||||
class TranslatedTryStmt extends TranslatedStmt {
|
||||
override TryOrMicrosoftTryStmt stmt;
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getBody()
|
||||
or
|
||||
result = this.getHandler(id - 1)
|
||||
@@ -655,23 +531,13 @@ class TranslatedTryStmt extends TranslatedStmt {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getBody().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getLastChild().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() {
|
||||
if exists(this.getFinally())
|
||||
then result = this.getFinally()
|
||||
else result = [this.getBody(), this.getHandler(_)]
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
// All non-finally children go to the successor of the `try` if
|
||||
// there is no finally block, but if there is a finally block
|
||||
// then we go to that one.
|
||||
@@ -715,7 +581,7 @@ class TranslatedTryStmt extends TranslatedStmt {
|
||||
class TranslatedBlock extends TranslatedStmt {
|
||||
override BlockStmt stmt;
|
||||
|
||||
override TranslatedElement getChildInternal(int id) { result = this.getStmt(id) }
|
||||
override TranslatedElement getChild(int id) { result = this.getStmt(id) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
this.isEmpty() and
|
||||
@@ -730,26 +596,18 @@ class TranslatedBlock extends TranslatedStmt {
|
||||
else result = this.getStmt(0).getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
if this.isEmpty()
|
||||
then result = this.getInstruction(OnlyInstructionTag())
|
||||
else result = this.getStmt(this.getStmtCount() - 1).getFirstInstruction(any(GotoEdge goto))
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getStmt(this.getStmtCount() - 1) }
|
||||
|
||||
private predicate isEmpty() { not exists(stmt.getStmt(0)) }
|
||||
|
||||
private TranslatedStmt getStmt(int index) { result = getTranslatedStmt(stmt.getStmt(index)) }
|
||||
|
||||
private int getStmtCount() { result = stmt.getNumStmt() }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int index |
|
||||
child = this.getStmt(index) and
|
||||
if index = (this.getStmtCount() - 1)
|
||||
@@ -765,20 +623,14 @@ class TranslatedBlock extends TranslatedStmt {
|
||||
abstract class TranslatedHandler extends TranslatedStmt {
|
||||
override Handler stmt;
|
||||
|
||||
override TranslatedElement getChildInternal(int id) { id = 1 and result = this.getBlock() }
|
||||
override TranslatedElement getChild(int id) { id = 1 and result = this.getBlock() }
|
||||
|
||||
override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getInstruction(CatchTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getBlock().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getBlock() }
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getBlock() and result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
@@ -804,20 +656,20 @@ class TranslatedCatchByTypeHandler extends TranslatedHandler {
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
result = super.getChildInternal(id)
|
||||
override TranslatedElement getChild(int id) {
|
||||
result = super.getChild(id)
|
||||
or
|
||||
id = 0 and result = this.getParameter()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
result = super.getChildSuccessorInternal(child, kind)
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
result = super.getChildSuccessor(child, kind)
|
||||
or
|
||||
child = this.getParameter() and
|
||||
result = this.getBlock().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = CatchTag() and
|
||||
(
|
||||
kind instanceof GotoEdge and
|
||||
@@ -850,7 +702,7 @@ class TranslatedCatchAnyHandler extends TranslatedHandler {
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = CatchTag() and
|
||||
result = this.getBlock().getFirstInstruction(kind)
|
||||
}
|
||||
@@ -865,13 +717,7 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
|
||||
else result = this.getFirstConditionInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getElse().getALastInstruction() or result = this.getThen().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getElse() or result = this.getThen() }
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getInitialization()
|
||||
or
|
||||
id = 1 and result = this.getCondition()
|
||||
@@ -901,7 +747,7 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
|
||||
|
||||
private predicate hasElse() { exists(stmt.getElse()) }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildTrueSuccessor(TranslatedCondition child, EdgeKind kind) {
|
||||
child = this.getCondition() and
|
||||
@@ -915,7 +761,7 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
|
||||
else result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and
|
||||
result = this.getFirstConditionInstruction(kind)
|
||||
or
|
||||
@@ -937,7 +783,7 @@ class TranslatedConstExprIfStmt extends TranslatedStmt, ConditionContext {
|
||||
else result = this.getFirstConditionInstruction(kind)
|
||||
}
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getInitialization()
|
||||
or
|
||||
id = 1 and result = this.getCondition()
|
||||
@@ -967,7 +813,7 @@ class TranslatedConstExprIfStmt extends TranslatedStmt, ConditionContext {
|
||||
|
||||
private predicate hasElse() { exists(stmt.getElse()) }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildTrueSuccessor(TranslatedCondition child, EdgeKind kind) {
|
||||
child = this.getCondition() and
|
||||
@@ -981,7 +827,7 @@ class TranslatedConstExprIfStmt extends TranslatedStmt, ConditionContext {
|
||||
else result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and
|
||||
result = this.getFirstConditionInstruction(kind)
|
||||
or
|
||||
@@ -992,23 +838,11 @@ class TranslatedConstExprIfStmt extends TranslatedStmt, ConditionContext {
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getThen().getALastInstruction()
|
||||
or
|
||||
result = this.getElse().getALastInstruction()
|
||||
}
|
||||
}
|
||||
|
||||
abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
|
||||
override Loop stmt;
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getCondition().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getCondition() }
|
||||
|
||||
final TranslatedCondition getCondition() {
|
||||
result = getTranslatedCondition(stmt.getCondition().getFullyConverted())
|
||||
}
|
||||
@@ -1023,7 +857,7 @@ abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
|
||||
|
||||
final predicate hasCondition() { exists(stmt.getCondition()) }
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getCondition()
|
||||
or
|
||||
id = 1 and result = this.getBody()
|
||||
@@ -1033,15 +867,13 @@ abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
|
||||
none()
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
none()
|
||||
}
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
final override Instruction getChildTrueSuccessor(TranslatedCondition child, EdgeKind kind) {
|
||||
child = this.getCondition() and result = this.getBody().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
|
||||
final override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
|
||||
child = this.getCondition() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
@@ -1050,36 +882,13 @@ abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
|
||||
class TranslatedWhileStmt extends TranslatedLoop {
|
||||
TranslatedWhileStmt() { stmt instanceof WhileStmt }
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
id = 0 and result = this.getCondition()
|
||||
or
|
||||
id = 1 and result = this.getBody()
|
||||
or
|
||||
exists(int n |
|
||||
result.getAst() = stmt.getImplicitDestructorCall(n) and
|
||||
id = 2 + n
|
||||
)
|
||||
}
|
||||
|
||||
override predicate handlesDestructorsExplicitly() { any() }
|
||||
|
||||
final override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
|
||||
child = this.getCondition() and
|
||||
if this.hasAnImplicitDestructorCall()
|
||||
then result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind)
|
||||
else result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getFirstConditionInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getBody() and
|
||||
result = this.getFirstConditionInstruction(kind)
|
||||
or
|
||||
child = this.getChild(this.getFirstDestructorCallIndex()) and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1090,7 +899,7 @@ class TranslatedDoStmt extends TranslatedLoop {
|
||||
result = this.getBody().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getBody() and
|
||||
result = this.getFirstConditionInstruction(kind)
|
||||
}
|
||||
@@ -1099,16 +908,7 @@ class TranslatedDoStmt extends TranslatedLoop {
|
||||
class TranslatedForStmt extends TranslatedLoop {
|
||||
override ForStmt stmt;
|
||||
|
||||
override predicate handlesDestructorsExplicitly() { any() }
|
||||
|
||||
final override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
|
||||
child = this.getCondition() and
|
||||
if this.hasAnImplicitDestructorCall()
|
||||
then result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind)
|
||||
else result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getInitialization()
|
||||
or
|
||||
id = 1 and result = this.getCondition()
|
||||
@@ -1116,11 +916,6 @@ class TranslatedForStmt extends TranslatedLoop {
|
||||
id = 2 and result = this.getUpdate()
|
||||
or
|
||||
id = 3 and result = this.getBody()
|
||||
or
|
||||
exists(int n |
|
||||
result.getAst() = stmt.getImplicitDestructorCall(n) and
|
||||
id = 4 + n
|
||||
)
|
||||
}
|
||||
|
||||
private TranslatedStmt getInitialization() {
|
||||
@@ -1139,7 +934,7 @@ class TranslatedForStmt extends TranslatedLoop {
|
||||
else result = this.getFirstConditionInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and
|
||||
result = this.getFirstConditionInstruction(kind)
|
||||
or
|
||||
@@ -1151,19 +946,6 @@ class TranslatedForStmt extends TranslatedLoop {
|
||||
)
|
||||
or
|
||||
child = this.getUpdate() and result = this.getFirstConditionInstruction(kind)
|
||||
or
|
||||
exists(int destructorId |
|
||||
destructorId >= this.getFirstDestructorCallIndex() and
|
||||
child = this.getChild(destructorId) and
|
||||
result = this.getChild(destructorId + 1).getFirstInstruction(kind)
|
||||
)
|
||||
or
|
||||
exists(int lastDestructorIndex |
|
||||
lastDestructorIndex =
|
||||
max(int n | exists(this.getChild(n)) and n >= this.getFirstDestructorCallIndex()) and
|
||||
child = this.getChild(lastDestructorIndex) and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1177,7 +959,7 @@ class TranslatedForStmt extends TranslatedLoop {
|
||||
class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
|
||||
override RangeBasedForStmt stmt;
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getInitialization()
|
||||
or
|
||||
id = 1 and result = this.getRangeVariableDeclStmt()
|
||||
@@ -1206,13 +988,7 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
|
||||
else result = this.getFirstRangeVariableDeclStmtInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getCondition().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getCondition() }
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and
|
||||
result = this.getFirstRangeVariableDeclStmtInstruction(kind)
|
||||
or
|
||||
@@ -1236,7 +1012,7 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildTrueSuccessor(TranslatedCondition child, EdgeKind kind) {
|
||||
child = this.getCondition() and
|
||||
@@ -1294,11 +1070,7 @@ class TranslatedJumpStmt extends TranslatedStmt {
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override TranslatedElement getChildInternal(int id) { none() }
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
@@ -1306,12 +1078,12 @@ class TranslatedJumpStmt extends TranslatedStmt {
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = getTranslatedStmt(stmt.getTarget()).getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
}
|
||||
|
||||
private EdgeKind getCaseEdge(SwitchCase switchCase) {
|
||||
@@ -1342,13 +1114,7 @@ class TranslatedSwitchStmt extends TranslatedStmt {
|
||||
else result = this.getFirstExprInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getBody().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getBody() }
|
||||
|
||||
override TranslatedElement getChildInternal(int id) {
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getInitialization()
|
||||
or
|
||||
id = 1 and result = this.getExpr()
|
||||
@@ -1374,7 +1140,7 @@ class TranslatedSwitchStmt extends TranslatedStmt {
|
||||
result = this.getExpr().getResult()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = SwitchBranchTag() and
|
||||
exists(SwitchCase switchCase |
|
||||
switchCase = stmt.getASwitchCase() and
|
||||
@@ -1388,7 +1154,7 @@ class TranslatedSwitchStmt extends TranslatedStmt {
|
||||
result = this.getParent().getChildSuccessor(this, any(GotoEdge edge))
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getInitialization() and
|
||||
result = this.getFirstExprInstruction(kind)
|
||||
or
|
||||
@@ -1403,7 +1169,7 @@ class TranslatedSwitchStmt extends TranslatedStmt {
|
||||
class TranslatedAsmStmt extends TranslatedStmt {
|
||||
override AsmStmt stmt;
|
||||
|
||||
override TranslatedExpr getChildInternal(int id) {
|
||||
override TranslatedExpr getChild(int id) {
|
||||
result = getTranslatedExpr(stmt.getChild(id).(Expr).getFullyConverted())
|
||||
}
|
||||
|
||||
@@ -1415,8 +1181,6 @@ class TranslatedAsmStmt extends TranslatedStmt {
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() { result = this.getInstruction(AsmTag()) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = AsmTag() and
|
||||
opcode instanceof Opcode::InlineAsm and
|
||||
@@ -1427,7 +1191,7 @@ class TranslatedAsmStmt extends TranslatedStmt {
|
||||
exists(int index |
|
||||
tag = AsmTag() and
|
||||
operandTag = asmOperand(index) and
|
||||
result = this.getChildInternal(index).getResult()
|
||||
result = this.getChild(index).getResult()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1439,12 +1203,12 @@ class TranslatedAsmStmt extends TranslatedStmt {
|
||||
result = getUnknownType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = AsmTag() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
exists(int index |
|
||||
child = this.getChild(index) and
|
||||
if exists(this.getChild(index + 1))
|
||||
@@ -1459,7 +1223,7 @@ class TranslatedAsmStmt extends TranslatedStmt {
|
||||
class TranslatedVlaDimensionStmt extends TranslatedStmt {
|
||||
override VlaDimensionStmt stmt;
|
||||
|
||||
override TranslatedExpr getChildInternal(int id) {
|
||||
override TranslatedExpr getChild(int id) {
|
||||
id = 0 and
|
||||
result = getTranslatedExpr(stmt.getDimensionExpr().getFullyConverted())
|
||||
}
|
||||
@@ -1468,19 +1232,13 @@ class TranslatedVlaDimensionStmt extends TranslatedStmt {
|
||||
result = this.getChild(0).getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getChild(0).getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getChild(0) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getChild(0) and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
@@ -1489,17 +1247,13 @@ class TranslatedVlaDimensionStmt extends TranslatedStmt {
|
||||
class TranslatedVlaDeclarationStmt extends TranslatedStmt {
|
||||
override VlaDeclStmt stmt;
|
||||
|
||||
override TranslatedExpr getChildInternal(int id) { none() }
|
||||
override TranslatedExpr getChild(int id) { none() }
|
||||
|
||||
override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getInstruction(OnlyInstructionTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
// TODO: This needs a new kind of instruction that represents initialization of a VLA.
|
||||
// For now we just emit a `NoOp` instruction so that the CFG isn't incomplete.
|
||||
@@ -1508,10 +1262,10 @@ class TranslatedVlaDeclarationStmt extends TranslatedStmt {
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
|
||||
override Instruction getChildSuccessor(TranslatedElement child, EdgeKind kind) { none() }
|
||||
}
|
||||
|
||||
@@ -38,12 +38,6 @@ private int getBinaryInstructionValue(BinaryInstruction instr) {
|
||||
or
|
||||
instr instanceof DivInstruction and result = div(left, right)
|
||||
or
|
||||
instr instanceof BitOrInstruction and result = bitOr(left, right)
|
||||
or
|
||||
instr instanceof BitAndInstruction and result = bitAnd(left, right)
|
||||
or
|
||||
instr instanceof BitXorInstruction and result = bitXor(left, right)
|
||||
or
|
||||
instr instanceof CompareEQInstruction and result = compareEQ(left, right)
|
||||
or
|
||||
instr instanceof CompareNEInstruction and result = compareNE(left, right)
|
||||
|
||||
@@ -11,7 +11,7 @@ private int getTypeSizeWorkaround(Type type) {
|
||||
exists(Type unspecifiedType |
|
||||
unspecifiedType = type.getUnspecifiedType() and
|
||||
(
|
||||
(unspecifiedType instanceof FunctionReferenceType or unspecifiedType instanceof RoutineType) and
|
||||
unspecifiedType instanceof FunctionReferenceType and
|
||||
result = getPointerSize()
|
||||
or
|
||||
exists(PointerToMemberType ptmType |
|
||||
@@ -176,7 +176,7 @@ private IRType getIRTypeForPRValue(Type type) {
|
||||
isPointerIshType(unspecifiedType) and
|
||||
result.(IRAddressType).getByteSize() = getTypeSize(unspecifiedType)
|
||||
or
|
||||
(unspecifiedType instanceof FunctionPointerIshType or unspecifiedType instanceof RoutineType) and
|
||||
unspecifiedType instanceof FunctionPointerIshType and
|
||||
result.(IRFunctionAddressType).getByteSize() = getTypeSize(type)
|
||||
or
|
||||
unspecifiedType instanceof VoidType and result instanceof IRVoidType
|
||||
|
||||
@@ -89,18 +89,6 @@ int compareLE(int a, int b) { if a <= b then result = 1 else result = 0 }
|
||||
bindingset[a, b]
|
||||
int compareGE(int a, int b) { if a >= b then result = 1 else result = 0 }
|
||||
|
||||
/** Returns `a | b`. */
|
||||
bindingset[a, b]
|
||||
int bitOr(int a, int b) { result = a.bitOr(b) }
|
||||
|
||||
/** Returns `a & b`. */
|
||||
bindingset[a, b]
|
||||
int bitAnd(int a, int b) { result = a.bitAnd(b) }
|
||||
|
||||
/** Returns `a ^ b`. */
|
||||
bindingset[a, b]
|
||||
int bitXor(int a, int b) { result = a.bitXor(b) }
|
||||
|
||||
/**
|
||||
* Returns `-a`. If the negation would overflow, there is no result.
|
||||
*/
|
||||
|
||||
@@ -36,9 +36,7 @@ private class MallocAllocationFunction extends AllocationFunction {
|
||||
"CRYPTO_malloc", // CRYPTO_malloc(size_t num, const char *file, int line)
|
||||
"CRYPTO_zalloc", // CRYPTO_zalloc(size_t num, const char *file, int line)
|
||||
"CRYPTO_secure_malloc", // CRYPTO_secure_malloc(size_t num, const char *file, int line)
|
||||
"CRYPTO_secure_zalloc", // CRYPTO_secure_zalloc(size_t num, const char *file, int line)
|
||||
"g_malloc", // g_malloc (n_bytes);
|
||||
"g_try_malloc" // g_try_malloc(n_bytes);
|
||||
"CRYPTO_secure_zalloc" // CRYPTO_secure_zalloc(size_t num, const char *file, int line)
|
||||
]) and
|
||||
sizeArg = 0
|
||||
or
|
||||
@@ -141,9 +139,7 @@ private class ReallocAllocationFunction extends AllocationFunction, TaintFunctio
|
||||
// --- Windows COM allocation
|
||||
"CoTaskMemRealloc", // CoTaskMemRealloc(ptr, size)
|
||||
// --- OpenSSL memory allocation
|
||||
"CRYPTO_realloc", // CRYPTO_realloc(void *addr, size_t num, const char *file, int line)
|
||||
"g_realloc", // g_realloc(mem, n_bytes);
|
||||
"g_try_realloc" // g_try_realloc(mem, n_bytes);
|
||||
"CRYPTO_realloc" // CRYPTO_realloc(void *addr, size_t num, const char *file, int line)
|
||||
]) and
|
||||
sizeArg = 1 and
|
||||
reallocArg = 0
|
||||
|
||||
@@ -20,10 +20,8 @@ private class StandardDeallocationFunction extends DeallocationFunction {
|
||||
freedArg = 0
|
||||
or
|
||||
this.hasGlobalName([
|
||||
// --- OpenSSL memory deallocation
|
||||
"CRYPTO_free", "CRYPTO_secure_free",
|
||||
// --- glib memory deallocation
|
||||
"g_free"
|
||||
// --- OpenSSL memory allocation
|
||||
"CRYPTO_free", "CRYPTO_secure_free"
|
||||
]) and
|
||||
freedArg = 0
|
||||
or
|
||||
|
||||
@@ -9,8 +9,6 @@ import cpp
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
import semmle.code.cpp.models.interfaces.DataFlow
|
||||
import semmle.code.cpp.models.interfaces.Iterator
|
||||
import semmle.code.cpp.models.interfaces.Alias
|
||||
import semmle.code.cpp.models.interfaces.SideEffect
|
||||
|
||||
/**
|
||||
* An instantiation of the `std::iterator_traits` template.
|
||||
@@ -440,7 +438,7 @@ private class IteratorAssignmentMemberOperatorModel extends IteratorAssignmentMe
|
||||
* A `begin` or `end` member function, or a related member function, that
|
||||
* returns an iterator.
|
||||
*/
|
||||
class BeginOrEndFunction extends MemberFunction {
|
||||
private class BeginOrEndFunction extends MemberFunction, TaintFunction, GetIteratorFunction {
|
||||
BeginOrEndFunction() {
|
||||
this.hasName([
|
||||
"begin", "cbegin", "rbegin", "crbegin", "end", "cend", "rend", "crend", "before_begin",
|
||||
@@ -448,11 +446,7 @@ class BeginOrEndFunction extends MemberFunction {
|
||||
]) and
|
||||
this.getType().getUnspecifiedType() instanceof Iterator
|
||||
}
|
||||
}
|
||||
|
||||
private class BeginOrEndFunctionModels extends BeginOrEndFunction, TaintFunction,
|
||||
GetIteratorFunction, AliasFunction, SideEffectFunction
|
||||
{
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
input.isQualifierObject() and
|
||||
output.isReturnValue()
|
||||
@@ -462,22 +456,6 @@ private class BeginOrEndFunctionModels extends BeginOrEndFunction, TaintFunction
|
||||
input.isQualifierObject() and
|
||||
output.isReturnValue()
|
||||
}
|
||||
|
||||
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||
|
||||
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||
|
||||
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||
|
||||
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||
|
||||
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||
none()
|
||||
}
|
||||
|
||||
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||
i = -1 and buffer = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -168,57 +168,3 @@ private class SmartPtrSetterFunction extends MemberFunction, AliasFunction, Side
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A destructor assocaited with a smart pointer. */
|
||||
private class SmartPtrDestructor extends Destructor, SideEffectFunction, AliasFunction {
|
||||
SmartPtr declaringType;
|
||||
|
||||
SmartPtrDestructor() {
|
||||
declaringType = this.getDeclaringType() and not this.isFromUninstantiatedTemplate(_)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the destructor associated with the base type of this smart pointer.
|
||||
*/
|
||||
private Destructor getBaseTypeDestructor() {
|
||||
result.getDeclaringType() = declaringType.getBaseType()
|
||||
}
|
||||
|
||||
override predicate hasOnlySpecificReadSideEffects() {
|
||||
this.getBaseTypeDestructor().(SideEffectFunction).hasOnlySpecificReadSideEffects()
|
||||
or
|
||||
// If there's no declared destructor for the base type then it won't have
|
||||
// any strange read side effects.
|
||||
not exists(this.getBaseTypeDestructor())
|
||||
}
|
||||
|
||||
override predicate hasOnlySpecificWriteSideEffects() {
|
||||
this.getBaseTypeDestructor().(SideEffectFunction).hasOnlySpecificWriteSideEffects()
|
||||
or
|
||||
// If there's no declared destructor for the base type then it won't have
|
||||
// any strange write side effects.
|
||||
not exists(this.getBaseTypeDestructor())
|
||||
}
|
||||
|
||||
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||
i = -1 and buffer = false
|
||||
}
|
||||
|
||||
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||
i = -1 and buffer = false and mustWrite = true
|
||||
}
|
||||
|
||||
override predicate parameterNeverEscapes(int index) {
|
||||
this.getBaseTypeDestructor().(AliasFunction).parameterNeverEscapes(index)
|
||||
or
|
||||
// If there's no declared destructor for the base type then it won't cause
|
||||
// anything to escape.
|
||||
not exists(this.getBaseTypeDestructor()) and
|
||||
index = -1
|
||||
}
|
||||
|
||||
override predicate parameterEscapesOnlyViaReturn(int index) {
|
||||
// A destructor call does not have a return value
|
||||
none()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,15 +253,13 @@ private class StdSequenceContainerAssign extends TaintFunction {
|
||||
/**
|
||||
* The standard container functions `at` and `operator[]`.
|
||||
*/
|
||||
class StdSequenceContainerAt extends MemberFunction {
|
||||
private class StdSequenceContainerAt extends TaintFunction {
|
||||
StdSequenceContainerAt() {
|
||||
this.getClassAndName(["at", "operator[]"]) instanceof Array or
|
||||
this.getClassAndName(["at", "operator[]"]) instanceof Deque or
|
||||
this.getClassAndName(["at", "operator[]"]) instanceof Vector
|
||||
}
|
||||
}
|
||||
|
||||
private class StdSequenceContainerAtModel extends StdSequenceContainerAt, TaintFunction {
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from qualifier to referenced return value
|
||||
input.isQualifierObject() and
|
||||
|
||||
@@ -129,11 +129,9 @@ private class StdMapMerge extends TaintFunction {
|
||||
/**
|
||||
* The standard map functions `at` and `operator[]`.
|
||||
*/
|
||||
class StdMapAt extends MemberFunction {
|
||||
private class StdMapAt extends TaintFunction {
|
||||
StdMapAt() { this.getClassAndName(["at", "operator[]"]) instanceof MapOrUnorderedMap }
|
||||
}
|
||||
|
||||
private class StdMapAtModels extends StdMapAt, TaintFunction {
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from qualifier to referenced return value
|
||||
input.isQualifierObject() and
|
||||
|
||||
@@ -1513,11 +1513,6 @@ exprs(
|
||||
int location: @location_expr ref
|
||||
);
|
||||
|
||||
expr_reuse(
|
||||
int reuse: @expr ref,
|
||||
int original: @expr ref
|
||||
)
|
||||
|
||||
/*
|
||||
case @value.category of
|
||||
1 = prval
|
||||
@@ -1746,7 +1741,6 @@ case @expr.kind of
|
||||
| 360 = @isunsigned
|
||||
| 361 = @isvoid
|
||||
| 362 = @isvolatile
|
||||
| 363 = @reuseexpr
|
||||
;
|
||||
|
||||
@var_args_expr = @vastartexpr
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
||||
description: Introduce re-use expressions
|
||||
compatibility: backwards
|
||||
@@ -1,14 +1,3 @@
|
||||
## 0.9.7
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.9.6
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The "non-constant format string" query (`cpp/non-constant-format`) has been converted to a `path-problem` query.
|
||||
* The new C/C++ dataflow and taint-tracking libraries (`semmle.code.cpp.dataflow.new.DataFlow` and `semmle.code.cpp.dataflow.new.TaintTracking`) now implicitly assume that dataflow and taint modelled via `DataFlowFunction` and `TaintFunction` always fully overwrite their buffers and thus act as flow barriers. As a result, many dataflow and taint-tracking queries now produce fewer false positives. To remove this assumption and go back to the previous behavior for a given model, one can override the new `isPartialWrite` predicate.
|
||||
|
||||
## 0.9.5
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @name Missing return-value check for a 'scanf'-like function
|
||||
* @description Failing to check that a call to 'scanf' actually writes to an
|
||||
* output variable can lead to unexpected behavior at reading time.
|
||||
* @kind path-problem
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 7.5
|
||||
* @precision medium
|
||||
@@ -18,9 +18,16 @@ import semmle.code.cpp.commons.Scanf
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
import semmle.code.cpp.dataflow.new.DataFlow::DataFlow
|
||||
import semmle.code.cpp.ir.IR
|
||||
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
import semmle.code.cpp.ir.ValueNumbering
|
||||
import ScanfChecks
|
||||
import ScanfToUseFlow::PathGraph
|
||||
|
||||
/** Holds if `n` reaches an argument to a call to a `scanf`-like function. */
|
||||
pragma[nomagic]
|
||||
predicate revFlow0(Node n) {
|
||||
isSink(_, _, n, _)
|
||||
or
|
||||
exists(Node succ | revFlow0(succ) | localFlowStep(n, succ))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` represents an uninitialized stack-allocated variable, or a
|
||||
@@ -31,45 +38,30 @@ predicate isUninitialized(Node n) {
|
||||
n.asIndirectExpr(1) instanceof AllocationExpr
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate fwdFlow0(Node n) {
|
||||
revFlow0(n) and
|
||||
(
|
||||
isUninitialized(n)
|
||||
or
|
||||
exists(Node prev |
|
||||
fwdFlow0(prev) and
|
||||
localFlowStep(prev, n)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
predicate isSink(ScanfFunctionCall call, int index, Node n, Expr input) {
|
||||
input = call.getOutputArgument(index) and
|
||||
n.asIndirectExpr() = input
|
||||
}
|
||||
|
||||
/**
|
||||
* A configuration to track a uninitialized data flowing to a `scanf`-like
|
||||
* output parameter position.
|
||||
*
|
||||
* This is meant to be a simple flow to rule out cases like:
|
||||
* ```
|
||||
* int x = 0;
|
||||
* scanf(..., &x);
|
||||
* use(x);
|
||||
* ```
|
||||
* since `x` is already initialized it's not a security concern that `x` is
|
||||
* used without checking the return value of `scanf`.
|
||||
*
|
||||
* Since this flow is meant to be simple, we disable field flow and require the
|
||||
* source and the sink to be in the same callable.
|
||||
*/
|
||||
module UninitializedToScanfConfig implements ConfigSig {
|
||||
predicate isSource(Node source) { isUninitialized(source) }
|
||||
|
||||
predicate isSink(Node sink) { isSink(_, _, sink, _) }
|
||||
|
||||
FlowFeature getAFeature() { result instanceof FeatureEqualSourceSinkCallContext }
|
||||
|
||||
int accessPathLimit() { result = 0 }
|
||||
}
|
||||
|
||||
module UninitializedToScanfFlow = Global<UninitializedToScanfConfig>;
|
||||
|
||||
/**
|
||||
* Holds if `call` is a `scanf`-like call and `output` is the `index`'th
|
||||
* argument that has not been previously initialized.
|
||||
*/
|
||||
predicate isRelevantScanfCall(ScanfFunctionCall call, int index, Expr output) {
|
||||
exists(Node n | UninitializedToScanfFlow::flowTo(n) and isSink(call, index, n, output)) and
|
||||
exists(Node n | fwdFlow0(n) and isSink(call, index, n, output)) and
|
||||
// Exclude results from incorrectky checked scanf query
|
||||
not incorrectlyCheckedScanf(call)
|
||||
}
|
||||
@@ -85,6 +77,31 @@ predicate isSource(ScanfFunctionCall call, int index, Node n, Expr output) {
|
||||
n.asDefiningArgument() = output
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` is reachable from an output argument of a relevant call to
|
||||
* a `scanf`-like function.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate fwdFlow(Node n) {
|
||||
isSource(_, _, n, _)
|
||||
or
|
||||
exists(Node prev |
|
||||
fwdFlow(prev) and
|
||||
localFlowStep(prev, n) and
|
||||
not isSanitizerOut(prev)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `n` should not have outgoing flow. */
|
||||
predicate isSanitizerOut(Node n) {
|
||||
// We disable flow out of sinks to reduce result duplication
|
||||
isSink(n, _)
|
||||
or
|
||||
// If the node is being passed to a function it may be
|
||||
// modified, and thus it's safe to later read the value.
|
||||
exists(n.asIndirectArgument())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` is a node such that `n.asExpr() = e` and `e` is not an
|
||||
* argument of a deallocation expression.
|
||||
@@ -95,37 +112,40 @@ predicate isSink(Node n, Expr e) {
|
||||
}
|
||||
|
||||
/**
|
||||
* A configuration to track flow from the output argument of a call to a
|
||||
* `scanf`-like function, and to a use of the defined variable.
|
||||
* Holds if `n` is part of a path from a call to a `scanf`-like function
|
||||
* to a use of the written variable.
|
||||
*/
|
||||
module ScanfToUseConfig implements ConfigSig {
|
||||
predicate isSource(Node source) { isSource(_, _, source, _) }
|
||||
|
||||
predicate isSink(Node sink) { isSink(sink, _) }
|
||||
|
||||
predicate isBarrierOut(Node n) {
|
||||
// We disable flow out of sinks to reduce result duplication
|
||||
pragma[nomagic]
|
||||
predicate revFlow(Node n) {
|
||||
fwdFlow(n) and
|
||||
(
|
||||
isSink(n, _)
|
||||
or
|
||||
// If the node is being passed to a function it may be
|
||||
// modified, and thus it's safe to later read the value.
|
||||
exists(n.asIndirectArgument())
|
||||
}
|
||||
exists(Node succ |
|
||||
revFlow(succ) and
|
||||
localFlowStep(n, succ) and
|
||||
not isSanitizerOut(n)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
module ScanfToUseFlow = Global<ScanfToUseConfig>;
|
||||
/** A local flow step, restricted to relevant dataflow nodes. */
|
||||
private predicate step(Node n1, Node n2) {
|
||||
revFlow(n1) and
|
||||
revFlow(n2) and
|
||||
localFlowStep(n1, n2)
|
||||
}
|
||||
|
||||
predicate hasFlow(Node n1, Node n2) = fastTC(step/2)(n1, n2)
|
||||
|
||||
/**
|
||||
* Holds if `source` is the `index`'th argument to the `scanf`-like call `call`, and `sink` is
|
||||
* a dataflow node that represents the expression `e`.
|
||||
*/
|
||||
predicate flowPath(
|
||||
ScanfToUseFlow::PathNode source, ScanfFunctionCall call, int index, ScanfToUseFlow::PathNode sink,
|
||||
Expr e
|
||||
) {
|
||||
isSource(call, index, source.getNode(), _) and
|
||||
ScanfToUseFlow::flowPath(source, sink) and
|
||||
isSink(sink.getNode(), e)
|
||||
predicate hasFlow(Node source, ScanfFunctionCall call, int index, Node sink, Expr e) {
|
||||
isSource(call, index, source, _) and
|
||||
hasFlow(source, sink) and
|
||||
isSink(sink, e)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -147,33 +167,39 @@ int getMinimumGuardConstant(ScanfFunctionCall call, int index) {
|
||||
* Holds the access to `e` isn't guarded by a check that ensures that `call` returned
|
||||
* at least `minGuard`.
|
||||
*/
|
||||
predicate hasNonGuardedAccess(
|
||||
ScanfToUseFlow::PathNode source, ScanfFunctionCall call, ScanfToUseFlow::PathNode sink, Expr e,
|
||||
int minGuard
|
||||
) {
|
||||
predicate hasNonGuardedAccess(ScanfFunctionCall call, Expr e, int minGuard) {
|
||||
exists(int index |
|
||||
flowPath(source, call, index, sink, e) and
|
||||
hasFlow(_, call, index, _, e) and
|
||||
minGuard = getMinimumGuardConstant(call, index)
|
||||
|
|
||||
not exists(GuardCondition guard |
|
||||
// call == k and k >= minGuard so call >= minGuard
|
||||
guard
|
||||
.ensuresEq(globalValueNumber(call).getAnExpr(), any(int k | minGuard <= k),
|
||||
e.getBasicBlock(), true)
|
||||
not exists(int value |
|
||||
e.getBasicBlock() = blockGuardedBy(value, "==", call) and minGuard <= value
|
||||
or
|
||||
// call >= k and k >= minGuard so call >= minGuard
|
||||
guard
|
||||
.ensuresLt(globalValueNumber(call).getAnExpr(), any(int k | minGuard <= k),
|
||||
e.getBasicBlock(), false)
|
||||
e.getBasicBlock() = blockGuardedBy(value, "<", call) and minGuard - 1 <= value
|
||||
or
|
||||
e.getBasicBlock() = blockGuardedBy(value, "<=", call) and minGuard <= value
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
from
|
||||
ScanfToUseFlow::PathNode source, ScanfToUseFlow::PathNode sink, ScanfFunctionCall call, Expr e,
|
||||
int minGuard
|
||||
where hasNonGuardedAccess(source, call, sink, e, minGuard)
|
||||
select e, source, sink,
|
||||
/** Returns a block guarded by the assertion of `value op call` */
|
||||
BasicBlock blockGuardedBy(int value, string op, ScanfFunctionCall call) {
|
||||
exists(GuardCondition g, Expr left, Expr right |
|
||||
right = g.getAChild() and
|
||||
value = left.getValue().toInt() and
|
||||
localExprFlow(call, right)
|
||||
|
|
||||
g.ensuresEq(left, right, 0, result, true) and op = "=="
|
||||
or
|
||||
g.ensuresLt(left, right, 0, result, true) and op = "<"
|
||||
or
|
||||
g.ensuresLt(left, right, 1, result, true) and op = "<="
|
||||
)
|
||||
}
|
||||
|
||||
from ScanfFunctionCall call, Expr e, int minGuard
|
||||
where hasNonGuardedAccess(call, e, minGuard)
|
||||
select e,
|
||||
"This variable is read, but may not have been written. " +
|
||||
"It should be guarded by a check that the $@ returns at least " + minGuard + ".", call,
|
||||
call.toString()
|
||||
|
||||
@@ -3,11 +3,15 @@ private import semmle.code.cpp.commons.Scanf
|
||||
private import semmle.code.cpp.controlflow.IRGuards
|
||||
private import semmle.code.cpp.ir.ValueNumbering
|
||||
|
||||
private ConstantInstruction getZeroInstruction() { result.getValue() = "0" }
|
||||
|
||||
private Operand zero() { result.getDef() = getZeroInstruction() }
|
||||
|
||||
private predicate exprInBooleanContext(Expr e) {
|
||||
exists(IRGuardCondition gc |
|
||||
exists(Instruction i |
|
||||
i.getUnconvertedResultExpression() = e and
|
||||
gc.comparesEq(valueNumber(i).getAUse(), 0, _, _)
|
||||
gc.comparesEq(valueNumber(i).getAUse(), zero(), 0, _, _)
|
||||
)
|
||||
or
|
||||
gc.getUnconvertedResultExpression() = e
|
||||
@@ -32,6 +36,10 @@ private string getEofValue() {
|
||||
)
|
||||
}
|
||||
|
||||
private ConstantInstruction getEofInstruction() { result.getValue() = getEofValue() }
|
||||
|
||||
private Operand eof() { result.getDef() = getEofInstruction() }
|
||||
|
||||
/**
|
||||
* Holds if the value of `call` has been checked to not equal `EOF`.
|
||||
*/
|
||||
@@ -39,10 +47,10 @@ private predicate checkedForEof(ScanfFunctionCall call) {
|
||||
exists(IRGuardCondition gc |
|
||||
exists(Instruction i | i.getUnconvertedResultExpression() = call |
|
||||
// call == EOF
|
||||
gc.comparesEq(valueNumber(i).getAUse(), getEofValue().toInt(), _, _)
|
||||
gc.comparesEq(valueNumber(i).getAUse(), eof(), 0, _, _)
|
||||
or
|
||||
// call < 0 (EOF is guaranteed to be negative)
|
||||
gc.comparesLt(valueNumber(i).getAUse(), 0, true, _)
|
||||
gc.comparesLt(valueNumber(i).getAUse(), zero(), 0, true, _)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* type `const char*` it is still considered non-constant if the value is not coming from a string
|
||||
* literal. For example, for a parameter with type `const char*` of an exported function that is
|
||||
* used as a format string, there is no way to ensure the originating value was a string literal.
|
||||
* @kind path-problem
|
||||
* @kind problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 9.3
|
||||
* @precision high
|
||||
@@ -26,7 +26,6 @@ import semmle.code.cpp.ir.dataflow.internal.ModelUtil
|
||||
import semmle.code.cpp.models.interfaces.DataFlow
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
import semmle.code.cpp.ir.IR
|
||||
import NonConstFlow::PathGraph
|
||||
|
||||
class UncalledFunction extends Function {
|
||||
UncalledFunction() {
|
||||
@@ -37,37 +36,6 @@ class UncalledFunction extends Function {
|
||||
}
|
||||
}
|
||||
|
||||
/** The `unsigned short` type. */
|
||||
class UnsignedShort extends ShortType {
|
||||
UnsignedShort() { this.isUnsigned() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `t` cannot refer to a string. That is, it's a built-in
|
||||
* or arithmetic type that is not a "`char` like" type.
|
||||
*/
|
||||
predicate cannotContainString(Type t) {
|
||||
exists(Type unspecified |
|
||||
unspecified = t.getUnspecifiedType() and
|
||||
not unspecified instanceof UnknownType and
|
||||
not unspecified instanceof CharType and
|
||||
not unspecified instanceof WideCharType and
|
||||
not unspecified instanceof Char8Type and
|
||||
not unspecified instanceof Char16Type and
|
||||
not unspecified instanceof Char32Type and
|
||||
// C often defines `wchar_t` as `unsigned short`
|
||||
not unspecified instanceof UnsignedShort
|
||||
|
|
||||
unspecified instanceof ArithmeticType or
|
||||
unspecified instanceof BuiltInType
|
||||
)
|
||||
}
|
||||
|
||||
predicate dataFlowOrTaintFlowFunction(Function func, FunctionOutput output) {
|
||||
func.(DataFlowFunction).hasDataFlow(_, output) or
|
||||
func.(TaintFunction).hasTaintFlow(_, output)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` is a non-constant source of data flow for non-const format string detection.
|
||||
* This is defined as either:
|
||||
@@ -100,12 +68,7 @@ predicate isNonConst(DataFlow::Node node) {
|
||||
// Parameters of uncalled functions that aren't const
|
||||
exists(UncalledFunction f, Parameter p |
|
||||
f.getAParameter() = p and
|
||||
// We pick the indirection of the parameter since this query is focused
|
||||
// on strings.
|
||||
p = node.asParameter(1) and
|
||||
// Ignore main's argv parameter as it is already considered a `FlowSource`
|
||||
// not ignoring it will result in path redundancies
|
||||
(f.getName() = "main" implies p != f.getParameter(1))
|
||||
p = node.asParameter()
|
||||
)
|
||||
or
|
||||
// Consider as an input any out arg of a function or a function's return where the function is not:
|
||||
@@ -115,27 +78,30 @@ predicate isNonConst(DataFlow::Node node) {
|
||||
// are considered as possible non-const sources
|
||||
// The function's output must also not be const to be considered a non-const source
|
||||
exists(Function func, CallInstruction call |
|
||||
not func.hasDefinition() and
|
||||
func = call.getStaticCallTarget()
|
||||
|
|
||||
// Case 1: It's a known dataflow or taintflow function with flow to the return value
|
||||
call.getUnconvertedResultExpression() = node.asIndirectExpr() and
|
||||
not exists(FunctionOutput output |
|
||||
dataFlowOrTaintFlowFunction(func, output) and
|
||||
output.isReturnValueDeref(_) and
|
||||
node = callOutput(call, output)
|
||||
// NOTE: could use `Call` getAnArgument() instead of `CallInstruction` but requires two
|
||||
// variables representing the same call in ordoer to use `callOutput` below.
|
||||
exists(Expr arg |
|
||||
call.getPositionalArgumentOperand(_).getDef().getUnconvertedResultExpression() = arg and
|
||||
arg = node.asDefiningArgument()
|
||||
)
|
||||
or
|
||||
// Case 2: It's a known dataflow or taintflow function with flow to an output parameter
|
||||
exists(int i |
|
||||
call.getPositionalArgumentOperand(i).getDef().getUnconvertedResultExpression() =
|
||||
node.asDefiningArgument() and
|
||||
not exists(FunctionOutput output |
|
||||
dataFlowOrTaintFlowFunction(func, output) and
|
||||
output.isParameterDeref(i, _) and
|
||||
node = callOutput(call, output)
|
||||
)
|
||||
call.getUnconvertedResultExpression() = node.asIndirectExpr()
|
||||
|
|
||||
func = call.getStaticCallTarget() and
|
||||
not exists(FunctionOutput output |
|
||||
// NOTE: we must include dataflow and taintflow. e.g., including only dataflow we will find sprintf
|
||||
// variant function's output are now possible non-const sources
|
||||
pragma[only_bind_out](func).(DataFlowFunction).hasDataFlow(_, output) or
|
||||
pragma[only_bind_out](func).(TaintFunction).hasTaintFlow(_, output)
|
||||
|
|
||||
node = callOutput(call, output)
|
||||
)
|
||||
) and
|
||||
not exists(Call c |
|
||||
c.getTarget().hasDefinition() and
|
||||
if node instanceof DataFlow::DefinitionByReferenceNode
|
||||
then c.getAnArgument() = node.asDefiningArgument()
|
||||
else c = [node.asExpr(), node.asIndirectExpr()]
|
||||
)
|
||||
}
|
||||
|
||||
@@ -144,41 +110,28 @@ predicate isNonConst(DataFlow::Node node) {
|
||||
* `FormattingFunctionCall`.
|
||||
*/
|
||||
predicate isSinkImpl(DataFlow::Node sink, Expr formatString) {
|
||||
sink.asIndirectExpr() = formatString and
|
||||
[sink.asExpr(), sink.asIndirectExpr()] = formatString and
|
||||
exists(FormattingFunctionCall fc | formatString = fc.getArgument(fc.getFormatParameterIndex()))
|
||||
}
|
||||
|
||||
module NonConstFlowConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(Type t |
|
||||
isNonConst(source) and
|
||||
t = source.getType() and
|
||||
not cannotContainString(t)
|
||||
)
|
||||
}
|
||||
predicate isSource(DataFlow::Node source) { isNonConst(source) }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _) }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
// Ignore tracing non-const through array indices
|
||||
exists(ArrayExpr a | a.getArrayOffset() = node.asIndirectExpr())
|
||||
or
|
||||
exists(Type t |
|
||||
t = node.getType() and
|
||||
cannotContainString(t)
|
||||
)
|
||||
exists(ArrayExpr a | a.getArrayOffset() = node.asExpr())
|
||||
}
|
||||
}
|
||||
|
||||
module NonConstFlow = TaintTracking::Global<NonConstFlowConfig>;
|
||||
|
||||
from
|
||||
FormattingFunctionCall call, Expr formatString, NonConstFlow::PathNode sink,
|
||||
NonConstFlow::PathNode source
|
||||
from FormattingFunctionCall call, Expr formatString, DataFlow::Node sink
|
||||
where
|
||||
isSinkImpl(sink.getNode(), formatString) and
|
||||
call.getArgument(call.getFormatParameterIndex()) = formatString and
|
||||
NonConstFlow::flowPath(source, sink)
|
||||
select sink.getNode(), source, sink,
|
||||
"The format string argument to $@ has a source which cannot be " +
|
||||
"verified to originate from a string literal.", call, call.getTarget().getName()
|
||||
NonConstFlow::flowTo(sink) and
|
||||
isSinkImpl(sink, formatString)
|
||||
select formatString,
|
||||
"The format string argument to " + call.getTarget().getName() +
|
||||
" should be constant to prevent security issues and other potential errors."
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @name Potentially uninitialized local variable
|
||||
* @description Reading from a local variable that has not been assigned to
|
||||
* will typically yield garbage.
|
||||
* @kind path-problem
|
||||
* @kind problem
|
||||
* @id cpp/uninitialized-local
|
||||
* @problem.severity warning
|
||||
* @security-severity 7.8
|
||||
@@ -15,7 +15,6 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.ir.IR
|
||||
import semmle.code.cpp.ir.dataflow.MustFlow
|
||||
import PathGraph
|
||||
|
||||
/**
|
||||
* Auxiliary predicate: Types that don't require initialization
|
||||
@@ -90,4 +89,4 @@ where
|
||||
conf.hasFlowPath(source, sink) and
|
||||
isSinkImpl(sink.getInstruction(), va) and
|
||||
v = va.getTarget()
|
||||
select va, source, sink, "The variable $@ may not be initialized at this access.", v, v.getName()
|
||||
select va, "The variable $@ may not be initialized at this access.", v, v.getName()
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
/**
|
||||
* @name boost::asio TLS settings misconfiguration
|
||||
* @name Boost_asio TLS Settings Misconfiguration
|
||||
* @description Using the TLS or SSLv23 protocol from the boost::asio library, but not disabling deprecated protocols, or disabling minimum-recommended protocols.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @precision medium
|
||||
* @security-severity 7.5
|
||||
* @id cpp/boost/tls-settings-misconfiguration
|
||||
* @tags security
|
||||
@@ -13,41 +12,34 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.security.boostorg.asio.protocols
|
||||
|
||||
predicate isSourceImpl(DataFlow::Node source, ConstructorCall cc) {
|
||||
exists(BoostorgAsio::SslContextClass c | c.getAContructorCall() = cc and cc = source.asExpr())
|
||||
}
|
||||
|
||||
predicate isSinkImpl(DataFlow::Node sink, FunctionCall fcSetOptions) {
|
||||
exists(BoostorgAsio::SslSetOptionsFunction f |
|
||||
f.getACallToThisFunction() = fcSetOptions and
|
||||
fcSetOptions.getQualifier() = sink.asIndirectExpr()
|
||||
)
|
||||
}
|
||||
|
||||
module ExistsAnyFlowConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { isSourceImpl(source, _) }
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(BoostorgAsio::SslContextClass c | c.getAContructorCall() = source.asExpr())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _) }
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(BoostorgAsio::SslSetOptionsFunction f, FunctionCall fcSetOptions |
|
||||
f.getACallToThisFunction() = fcSetOptions and
|
||||
fcSetOptions.getQualifier() = sink.asExpr()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module ExistsAnyFlow = DataFlow::Global<ExistsAnyFlowConfig>;
|
||||
|
||||
bindingset[flag]
|
||||
predicate isOptionSet(ConstructorCall cc, int flag, FunctionCall fcSetOptions) {
|
||||
exists(
|
||||
VariableAccess contextSetOptions, BoostorgAsio::SslSetOptionsFunction f, DataFlow::Node source,
|
||||
DataFlow::Node sink
|
||||
|
|
||||
isSourceImpl(source, cc) and
|
||||
isSinkImpl(sink, fcSetOptions) and
|
||||
ExistsAnyFlow::flow(source, sink) and
|
||||
f.getACallToThisFunction() = fcSetOptions and
|
||||
contextSetOptions = fcSetOptions.getQualifier() and
|
||||
forex(Expr optionArgument |
|
||||
optionArgument = fcSetOptions.getArgument(0) and
|
||||
BoostorgAsio::SslOptionFlow::flowTo(DataFlow::exprNode(optionArgument))
|
||||
|
|
||||
optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag
|
||||
exists(VariableAccess contextSetOptions |
|
||||
ExistsAnyFlow::flow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and
|
||||
exists(BoostorgAsio::SslSetOptionsFunction f | f.getACallToThisFunction() = fcSetOptions |
|
||||
contextSetOptions = fcSetOptions.getQualifier() and
|
||||
forall(Expr optionArgument, Expr optionArgumentSource |
|
||||
optionArgument = fcSetOptions.getArgument(0) and
|
||||
BoostorgAsio::SslOptionFlow::flow(DataFlow::exprNode(optionArgumentSource),
|
||||
DataFlow::exprNode(optionArgument))
|
||||
|
|
||||
optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
/**
|
||||
* @name boost::asio use of deprecated hardcoded protocol
|
||||
* @name boost::asio Use of deprecated hardcoded Protocol
|
||||
* @description Using a deprecated hard-coded protocol using the boost::asio library.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @precision medium
|
||||
* @security-severity 7.5
|
||||
* @id cpp/boost/use-of-deprecated-hardcoded-security-protocol
|
||||
* @tags security
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Certain casts in C and C++ place no restrictions on the target type. For
|
||||
example, C style casts such as <code>(MyClass*)p</code> allows the programmer
|
||||
to cast any pointer <code>p</code> to an expression of type <code>MyClass*</code>.
|
||||
If the runtime type of <code>p</code> turns out to be a type that's incompatible
|
||||
with <code>MyClass</code>, this results in undefined behavior.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
If possible, use <code>dynamic_cast</code> to safely cast between polymorphic types.
|
||||
If <code>dynamic_cast</code> is not an option, use <code>static_cast</code> to restrict
|
||||
the kinds of conversions that the compiler is allowed to perform. If C++ style casts is
|
||||
not an option, carefully check that all casts are safe.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
Consider the following class hierachy where we define a base class <code>Shape</code> and two
|
||||
derived classes <code>Circle</code> and <code>Square</code> that are mutually incompatible:
|
||||
</p>
|
||||
<sample src="TypeConfusionCommon.cpp"/>
|
||||
|
||||
<p>
|
||||
The following code demonstrates a type confusion vulnerability where the programmer
|
||||
assumes that the runtime type of <code>p</code> is always a <code>Square</code>.
|
||||
However, if <code>p</code> is a <code>Circle</code>, the cast will result in undefined behavior.
|
||||
</p>
|
||||
<sample src="TypeConfusionBad.cpp"/>
|
||||
|
||||
<p>
|
||||
The following code fixes the vulnerability by using <code>dynamic_cast</code> to
|
||||
safely cast between polymorphic types. If the cast fails, <code>dynamic_cast</code>
|
||||
returns a null pointer, which can be checked for and handled appropriately.
|
||||
</p>
|
||||
<sample src="TypeConfusionGood.cpp"/>
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
Microsoft Learn: <a href="https://learn.microsoft.com/en-us/cpp/cpp/type-conversions-and-type-safety-modern-cpp">Type conversions and type safety</a>.
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user