Compare commits

..

5 Commits

Author SHA1 Message Date
Cornelius Riemenschneider
8fba481a04 shorter paths 2024-02-26 00:32:46 +01:00
Cornelius Riemenschneider
9433201b58 add bzlmod 2024-02-25 23:51:00 +01:00
Cornelius Riemenschneider
c097397c32 Address review, start accomodating bzlmod. 2024-02-22 22:02:14 +01:00
Cornelius Riemenschneider
3d5d1bc59e Fix windows CI build.
As we're now checking out the `codeql` repo in a sub-path,
we need to enable long paths on Windows.
2024-02-22 21:25:59 +01:00
Cornelius Riemenschneider
007fc89543 Ruby: Start building the language pack using bazel.
This PR introduces a bazel and `rules_rust`-based build system
for the ruby extractor and language pack.
This replacese the existing, `cargo` and `cross`-based build system.

For local development, nothing changes, and the existing `cargo`-based
build still keeps working as-is.

We no longer need to use `cross` to compile our Linux binaries,
as we now can link against our hermetic C++ toolchain, which ships
with an old enough glibc, so that we don't run into symbol version issues
when deploying the binaries to older systems.
Besides the one change in dependency (explained in detail in `Cargo.toml`
and in https://github.com/github/codeql/pull/15595), nothing ought to
change in how we build the extractor.
2024-02-22 21:25:59 +01:00
2163 changed files with 147023 additions and 287281 deletions

View File

@@ -1 +1 @@
7.1.0
6.5.0

2
.github/labeler.yml vendored
View File

@@ -20,7 +20,7 @@ JS:
Kotlin:
- java/kotlin-extractor/**/*
- java/ql/test-kotlin*/**/*
- java/ql/test/kotlin/**/*
Python:
- python/**/*

View File

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

View File

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

@@ -39,9 +39,6 @@
# local bazel options
/local.bazelrc
# generated cmake directory
/.bazel-cmake
# CLion project files
/.clwb

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,5 @@
using System;
using Semmle.Autobuild.Shared;
using Semmle.Util;
namespace Semmle.Autobuild.Cpp
{

View File

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

View File

@@ -1,4 +0,0 @@
description: Introduce re-use expressions
compatibility: partial
expr_reuse.rel: delete
exprs.rel: run exprs.qlo

View File

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

View File

@@ -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("//", "/")
}

View File

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

View File

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

View File

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

View File

@@ -1,5 +0,0 @@
## 0.12.7
### Minor Analysis Improvements
* Added destructors for named objects to the intermediate representation.

View File

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

View File

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

View File

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

View File

@@ -60,6 +60,4 @@ Element exprEnclosingElement(Expr e) {
)
else result = de.getDeclaration()
)
or
result.(Stmt).getAnImplicitDestructorCall() = e
}

View File

@@ -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 + ")"

View File

@@ -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() }

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,3 @@
/**
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
*/
private import cpp
private import DataFlowPrivate
private import DataFlowUtil

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,3 @@
/**
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
*/
private import cpp
private import DataFlowUtil
private import DataFlowDispatch

View File

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

View File

@@ -1,6 +1,4 @@
/**
* DEPRECATED: Use `semmle.code.cpp.dataflow.new.DataFlow` instead.
*
* Provides a class for handling variables in the data flow analysis.
*/

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,3 @@
/**
* DEPRECATED: Use `Global` and `GlobalWithState` instead.
*/
import semmle.code.cpp.dataflow.internal.TaintTrackingUtil as Public
module Private {

View File

@@ -1,7 +1,3 @@
/**
* DEPRECATED: Use `Global` and `GlobalWithState` instead.
*/
import semmle.code.cpp.dataflow.internal.TaintTrackingUtil as Public
module Private {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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() }

View File

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

View File

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

View File

@@ -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
}
}
/**

View File

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

View File

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

View File

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

View File

@@ -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 + ")"
)
}

View File

@@ -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()
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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() }
}

View File

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

View File

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

View File

@@ -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.
*/

View File

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

View File

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

View File

@@ -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
}
}
/**

View File

@@ -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()
}
}

View File

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

View File

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

View File

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

View File

@@ -1,2 +0,0 @@
description: Introduce re-use expressions
compatibility: backwards

View File

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

View File

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

View File

@@ -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, _)
)
)
}

View File

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

View File

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

View File

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

View File

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

View File

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