mirror of
https://github.com/github/codeql.git
synced 2026-03-06 15:49:08 +01:00
Merge branch 'main' into alexdenisov+redsun82/tuple-mangling
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"extensions": [
|
||||
"rust-lang.rust",
|
||||
"rust-lang.rust-analyzer",
|
||||
"bungcip.better-toml",
|
||||
"github.vscode-codeql",
|
||||
"hbenl.vscode-test-explorer",
|
||||
|
||||
6
.github/workflows/check-change-note.yml
vendored
6
.github/workflows/check-change-note.yml
vendored
@@ -27,9 +27,9 @@ jobs:
|
||||
run: |
|
||||
gh api 'repos/${{github.repository}}/pulls/${{github.event.number}}/files' --paginate --jq 'any(.[].filename ; test("/change-notes/.*[.]md$"))' |
|
||||
grep true -c
|
||||
- name: Fail if the change note filename doesn't match the expected format. The file name must be of the form 'YYYY-MM-DD.md' or 'YYYY-MM-DD-{title}.md', where '{title}' is arbitrary text.
|
||||
- name: Fail if the change note filename doesn't match the expected format. The file name must be of the form 'YYYY-MM-DD.md', 'YYYY-MM-DD-{title}.md', where '{title}' is arbitrary text, or released/x.y.z.md for released change-notes
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
gh api 'repos/${{github.repository}}/pulls/${{github.event.number}}/files' --paginate --jq '[.[].filename | select(test("/change-notes/.*[.]md$"))] | all(test("/change-notes/[0-9]{4}-[0-9]{2}-[0-9]{2}.*[.]md$"))' |
|
||||
grep true -c
|
||||
gh api 'repos/${{github.repository}}/pulls/${{github.event.number}}/files' --paginate --jq '[.[].filename | select(test("/change-notes/.*[.]md$"))] | all(test("/change-notes/[0-9]{4}-[0-9]{2}-[0-9]{2}.*[.]md$") or test("/change-notes/released/[0-9]*[.][0-9]*[.][0-9]*[.]md$"))' |
|
||||
grep true -c
|
||||
|
||||
2
.github/workflows/ql-for-ql-build.yml
vendored
2
.github/workflows/ql-for-ql-build.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
||||
path: |
|
||||
ql/extractor-pack/
|
||||
ql/target/release/buramu
|
||||
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-extractor-${{ hashFiles('ql/**/Cargo.lock') }}-${{ hashFiles('ql/**/*.rs') }}
|
||||
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-extractor-${{ hashFiles('ql/**/Cargo.lock') }}-${{ hashFiles('shared/tree-sitter-extractor') }}-${{ hashFiles('ql/**/*.rs') }}
|
||||
- name: Cache cargo
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
uses: actions/cache@v3
|
||||
|
||||
2
.github/workflows/ruby-build.yml
vendored
2
.github/workflows/ruby-build.yml
vendored
@@ -61,7 +61,7 @@ jobs:
|
||||
ruby/extractor/target/release/codeql-extractor-ruby
|
||||
ruby/extractor/target/release/codeql-extractor-ruby.exe
|
||||
ruby/extractor/ql/lib/codeql/ruby/ast/internal/TreeSitter.qll
|
||||
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-ruby-extractor-${{ hashFiles('ruby/extractor/rust-toolchain.toml', 'ruby/extractor/Cargo.lock') }}--${{ hashFiles('ruby/extractor/**/*.rs') }}
|
||||
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-ruby-extractor-${{ hashFiles('ruby/extractor/rust-toolchain.toml', 'ruby/extractor/Cargo.lock') }}-${{ hashFiles('shared/tree-sitter-extractor') }}-${{ hashFiles('ruby/extractor/**/*.rs') }}
|
||||
- uses: actions/cache@v3
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
with:
|
||||
|
||||
2
.github/workflows/sync-files.yml
vendored
2
.github/workflows/sync-files.yml
vendored
@@ -17,4 +17,6 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Check synchronized files
|
||||
run: python config/sync-files.py
|
||||
- name: Check dbscheme fragments
|
||||
run: python config/sync-dbscheme-fragments.py
|
||||
|
||||
|
||||
46
.github/workflows/tree-sitter-extractor-test.yml
vendored
Normal file
46
.github/workflows/tree-sitter-extractor-test.yml
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
name: Test tree-sitter-extractor
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "shared/tree-sitter-extractor/**"
|
||||
- .github/workflows/tree-sitter-extractor-test.yml
|
||||
branches:
|
||||
- main
|
||||
- "rc/*"
|
||||
pull_request:
|
||||
paths:
|
||||
- "shared/tree-sitter-extractor/**"
|
||||
- .github/workflows/tree-sitter-extractor-test.yml
|
||||
branches:
|
||||
- main
|
||||
- "rc/*"
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: shared/tree-sitter-extractor
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Check formatting
|
||||
run: cargo fmt --all -- --check
|
||||
- name: Run tests
|
||||
run: cargo test --verbose
|
||||
fmt:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Check formatting
|
||||
run: cargo fmt --check
|
||||
clippy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Run clippy
|
||||
run: cargo clippy -- --no-deps -D warnings -A clippy::new_without_default -A clippy::too_many_arguments
|
||||
18
.vscode/tasks.json
vendored
18
.vscode/tasks.json
vendored
@@ -22,6 +22,22 @@
|
||||
"command": "${config:python.pythonPath}",
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Accept .expected changes from CI",
|
||||
"type": "process",
|
||||
// Non-Windows OS will usually have Python 3 already installed at /usr/bin/python3.
|
||||
"command": "python3",
|
||||
"args": [
|
||||
"misc/scripts/accept-expected-changes-from-ci.py"
|
||||
],
|
||||
"group": "build",
|
||||
"windows": {
|
||||
// On Windows, use whatever Python interpreter is configured for this workspace. The default is
|
||||
// just `python`, so if Python is already on the path, this will find it.
|
||||
"command": "${config:python.pythonPath}",
|
||||
},
|
||||
"problemMatcher": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,3 +40,6 @@ WORKSPACE.bazel @github/codeql-ci-reviewers
|
||||
/.github/workflows/ql-for-ql-* @github/codeql-ql-for-ql-reviewers
|
||||
/.github/workflows/ruby-* @github/codeql-ruby
|
||||
/.github/workflows/swift.yml @github/codeql-swift
|
||||
|
||||
# Misc
|
||||
/misc/scripts/accept-expected-changes-from-ci.py @RasmusWL
|
||||
|
||||
33
config/dbscheme-fragments.json
Normal file
33
config/dbscheme-fragments.json
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"files": [
|
||||
"javascript/ql/lib/semmlecode.javascript.dbscheme",
|
||||
"python/ql/lib/semmlecode.python.dbscheme",
|
||||
"ruby/ql/lib/ruby.dbscheme",
|
||||
"ql/ql/src/ql.dbscheme"
|
||||
],
|
||||
"fragments": [
|
||||
"/*- External data -*/",
|
||||
"/*- Files and folders -*/",
|
||||
"/*- Diagnostic messages -*/",
|
||||
"/*- Diagnostic messages: severity -*/",
|
||||
"/*- Source location prefix -*/",
|
||||
"/*- Lines of code -*/",
|
||||
"/*- Configuration files with key value pairs -*/",
|
||||
"/*- YAML -*/",
|
||||
"/*- XML Files -*/",
|
||||
"/*- XML: sourceline -*/",
|
||||
"/*- DEPRECATED: External defects and metrics -*/",
|
||||
"/*- DEPRECATED: Snapshot date -*/",
|
||||
"/*- DEPRECATED: Duplicate code -*/",
|
||||
"/*- DEPRECATED: Version control data -*/",
|
||||
"/*- JavaScript-specific part -*/",
|
||||
"/*- Ruby dbscheme -*/",
|
||||
"/*- Erb dbscheme -*/",
|
||||
"/*- QL dbscheme -*/",
|
||||
"/*- Dbscheme dbscheme -*/",
|
||||
"/*- Yaml dbscheme -*/",
|
||||
"/*- Blame dbscheme -*/",
|
||||
"/*- JSON dbscheme -*/",
|
||||
"/*- Python dbscheme -*/"
|
||||
]
|
||||
}
|
||||
@@ -47,7 +47,6 @@
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplForRegExp.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl1.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll",
|
||||
|
||||
86
config/sync-dbscheme-fragments.py
Executable file
86
config/sync-dbscheme-fragments.py
Executable file
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
|
||||
|
||||
def make_groups(blocks):
|
||||
groups = {}
|
||||
for block in blocks:
|
||||
groups.setdefault("".join(block["lines"]), []).append(block)
|
||||
return list(groups.values())
|
||||
|
||||
|
||||
def validate_fragments(fragments):
|
||||
ok = True
|
||||
for header, blocks in fragments.items():
|
||||
groups = make_groups(blocks)
|
||||
if len(groups) > 1:
|
||||
ok = False
|
||||
print("Warning: dbscheme fragments with header '{}' are different for {}".format(header, ["{}:{}:{}".format(
|
||||
group[0]["file"], group[0]["start"], group[0]["end"]) for group in groups]))
|
||||
return ok
|
||||
|
||||
|
||||
def main():
|
||||
script_path = os.path.realpath(__file__)
|
||||
script_dir = os.path.dirname(script_path)
|
||||
parser = argparse.ArgumentParser(
|
||||
prog=os.path.basename(script_path),
|
||||
description='Sync dbscheme fragments across files.'
|
||||
)
|
||||
parser.add_argument('files', metavar='dbscheme_file', type=pathlib.Path, nargs='*', default=[],
|
||||
help='dbscheme files to check')
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(os.path.join(script_dir, "dbscheme-fragments.json"), "r") as f:
|
||||
config = json.load(f)
|
||||
|
||||
fragment_headers = set(config["fragments"])
|
||||
fragments = {}
|
||||
ok = True
|
||||
for file in args.files + config["files"]:
|
||||
with open(os.path.join(os.path.dirname(script_dir), file), "r") as dbscheme:
|
||||
header = None
|
||||
line_number = 1
|
||||
block = {"file": file, "start": line_number,
|
||||
"end": None, "lines": []}
|
||||
|
||||
def end_block():
|
||||
block["end"] = line_number - 1
|
||||
if len(block["lines"]) > 0:
|
||||
if header is None:
|
||||
if re.match(r'(?m)\A(\s|//.*$|/\*(\**[^\*])*\*+/)*\Z', "".join(block["lines"])):
|
||||
# Ignore comments at the beginning of the file
|
||||
pass
|
||||
else:
|
||||
ok = False
|
||||
print("Warning: dbscheme fragment without header: {}:{}:{}".format(
|
||||
block["file"], block["start"], block["end"]))
|
||||
else:
|
||||
fragments.setdefault(header, []).append(block)
|
||||
for line in dbscheme:
|
||||
m = re.match(r"^\/\*-.*-\*\/$", line)
|
||||
if m:
|
||||
end_block()
|
||||
header = line.strip()
|
||||
if header not in fragment_headers:
|
||||
ok = False
|
||||
print("Warning: unknown header for dbscheme fragment: '{}': {}:{}".format(
|
||||
header, file, line_number))
|
||||
block = {"file": file, "start": line_number,
|
||||
"end": None, "lines": []}
|
||||
block["lines"].append(line)
|
||||
line_number += 1
|
||||
block["lines"].append('\n')
|
||||
line_number += 1
|
||||
end_block()
|
||||
if not ok or not validate_fragments(fragments):
|
||||
exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,3 +1,7 @@
|
||||
## 0.7.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.7.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* A new predicate `BarrierGuard::getAnIndirectBarrierNode` has been added to the new dataflow library (`semmle.code.cpp.dataflow.new.DataFlow`) to mark indirect expressions as barrier nodes using the `BarrierGuard` API.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The new dataflow (`semmle.code.cpp.dataflow.new.DataFlow`) and taint-tracking libraries (`semmle.code.cpp.dataflow.new.TaintTracking`) now support tracking flow through static local variables.
|
||||
4
cpp/ql/lib/change-notes/2023-05-02-ir-noreturn-calls.md
Normal file
4
cpp/ql/lib/change-notes/2023-05-02-ir-noreturn-calls.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: majorAnalysis
|
||||
---
|
||||
* In the intermediate representation, handling of control flow after non-returning calls has been improved. This should remove false positives in queries that use the intermedite representation or libraries based on it, including the new data flow library.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Added an AST-based interface (`semmle.code.cpp.rangeanalysis.new.RangeAnalysis`) for the relative range analysis library.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The `StdNamespace` class now also includes all inline namespaces that are children of `std` namespace.
|
||||
3
cpp/ql/lib/change-notes/released/0.7.1.md
Normal file
3
cpp/ql/lib/change-notes/released/0.7.1.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.7.1
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.7.0
|
||||
lastReleaseVersion: 0.7.1
|
||||
|
||||
@@ -238,7 +238,7 @@ class NoReason extends Reason, TNoReason {
|
||||
class CondReason extends Reason, TCondReason {
|
||||
IRGuardCondition getCond() { this = TCondReason(result) }
|
||||
|
||||
override string toString() { result = getCond().toString() }
|
||||
override string toString() { result = this.getCond().toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -260,14 +260,14 @@ private predicate typeBound(IRIntegerType typ, int lowerbound, int upperbound) {
|
||||
private class NarrowingCastInstruction extends ConvertInstruction {
|
||||
NarrowingCastInstruction() {
|
||||
not this instanceof SafeCastInstruction and
|
||||
typeBound(getResultIRType(), _, _)
|
||||
typeBound(this.getResultIRType(), _, _)
|
||||
}
|
||||
|
||||
/** Gets the lower bound of the resulting type. */
|
||||
int getLowerBound() { typeBound(getResultIRType(), result, _) }
|
||||
int getLowerBound() { typeBound(this.getResultIRType(), result, _) }
|
||||
|
||||
/** Gets the upper bound of the resulting type. */
|
||||
int getUpperBound() { typeBound(getResultIRType(), _, result) }
|
||||
int getUpperBound() { typeBound(this.getResultIRType(), _, result) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -109,8 +109,8 @@ private predicate safeCast(IRIntegerType fromtyp, IRIntegerType totyp) {
|
||||
*/
|
||||
class PtrToPtrCastInstruction extends ConvertInstruction {
|
||||
PtrToPtrCastInstruction() {
|
||||
getResultIRType() instanceof IRAddressType and
|
||||
getUnary().getResultIRType() instanceof IRAddressType
|
||||
this.getResultIRType() instanceof IRAddressType and
|
||||
this.getUnary().getResultIRType() instanceof IRAddressType
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ class PtrToPtrCastInstruction extends ConvertInstruction {
|
||||
* that cannot overflow or underflow.
|
||||
*/
|
||||
class SafeIntCastInstruction extends ConvertInstruction {
|
||||
SafeIntCastInstruction() { safeCast(getUnary().getResultIRType(), getResultIRType()) }
|
||||
SafeIntCastInstruction() { safeCast(this.getUnary().getResultIRType(), this.getResultIRType()) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -50,8 +50,8 @@ private class ConstantBitwiseAndExprRange extends SimpleRangeAnalysisExpr {
|
||||
// If an operand can have negative values, the lower bound is unconstrained.
|
||||
// Otherwise, the lower bound is zero.
|
||||
exists(float lLower, float rLower |
|
||||
lLower = getFullyConvertedLowerBounds(getLeftOperand()) and
|
||||
rLower = getFullyConvertedLowerBounds(getRightOperand()) and
|
||||
lLower = getFullyConvertedLowerBounds(this.getLeftOperand()) and
|
||||
rLower = getFullyConvertedLowerBounds(this.getRightOperand()) and
|
||||
(
|
||||
(lLower < 0 or rLower < 0) and
|
||||
result = exprMinVal(this)
|
||||
@@ -68,10 +68,10 @@ private class ConstantBitwiseAndExprRange extends SimpleRangeAnalysisExpr {
|
||||
// If an operand can have negative values, the upper bound is unconstrained.
|
||||
// Otherwise, the upper bound is the minimum of the upper bounds of the operands
|
||||
exists(float lLower, float lUpper, float rLower, float rUpper |
|
||||
lLower = getFullyConvertedLowerBounds(getLeftOperand()) and
|
||||
lUpper = getFullyConvertedUpperBounds(getLeftOperand()) and
|
||||
rLower = getFullyConvertedLowerBounds(getRightOperand()) and
|
||||
rUpper = getFullyConvertedUpperBounds(getRightOperand()) and
|
||||
lLower = getFullyConvertedLowerBounds(this.getLeftOperand()) and
|
||||
lUpper = getFullyConvertedUpperBounds(this.getLeftOperand()) and
|
||||
rLower = getFullyConvertedLowerBounds(this.getRightOperand()) and
|
||||
rUpper = getFullyConvertedUpperBounds(this.getRightOperand()) and
|
||||
(
|
||||
(lLower < 0 or rLower < 0) and
|
||||
result = exprMaxVal(this)
|
||||
@@ -85,6 +85,6 @@ private class ConstantBitwiseAndExprRange extends SimpleRangeAnalysisExpr {
|
||||
}
|
||||
|
||||
override predicate dependsOnChild(Expr child) {
|
||||
child = getLeftOperand() or child = getRightOperand()
|
||||
child = this.getLeftOperand() or child = this.getRightOperand()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ class ConstantRShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||
* We don't handle the case where `a` and `b` are both non-constant values.
|
||||
*/
|
||||
ConstantRShiftExprRange() {
|
||||
getUnspecifiedType() instanceof IntegralType and
|
||||
this.getUnspecifiedType() instanceof IntegralType and
|
||||
exists(Expr l, Expr r |
|
||||
l = this.(RShiftExpr).getLeftOperand() and
|
||||
r = this.(RShiftExpr).getRightOperand()
|
||||
@@ -84,10 +84,10 @@ class ConstantRShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||
|
||||
override float getLowerBounds() {
|
||||
exists(int lLower, int lUpper, int rLower, int rUpper |
|
||||
lLower = getFullyConvertedLowerBounds(getLeftOperand()) and
|
||||
lUpper = getFullyConvertedUpperBounds(getLeftOperand()) and
|
||||
rLower = getFullyConvertedLowerBounds(getRightOperand()) and
|
||||
rUpper = getFullyConvertedUpperBounds(getRightOperand()) and
|
||||
lLower = getFullyConvertedLowerBounds(this.getLeftOperand()) and
|
||||
lUpper = getFullyConvertedUpperBounds(this.getLeftOperand()) and
|
||||
rLower = getFullyConvertedLowerBounds(this.getRightOperand()) and
|
||||
rUpper = getFullyConvertedUpperBounds(this.getRightOperand()) and
|
||||
lLower <= lUpper and
|
||||
rLower <= rUpper
|
||||
|
|
||||
@@ -95,8 +95,8 @@ class ConstantRShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||
lLower < 0
|
||||
or
|
||||
not (
|
||||
isValidShiftExprShift(rLower, getLeftOperand()) and
|
||||
isValidShiftExprShift(rUpper, getLeftOperand())
|
||||
isValidShiftExprShift(rLower, this.getLeftOperand()) and
|
||||
isValidShiftExprShift(rUpper, this.getLeftOperand())
|
||||
)
|
||||
then
|
||||
// We don't want to deal with shifting negative numbers at the moment,
|
||||
@@ -111,10 +111,10 @@ class ConstantRShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||
|
||||
override float getUpperBounds() {
|
||||
exists(int lLower, int lUpper, int rLower, int rUpper |
|
||||
lLower = getFullyConvertedLowerBounds(getLeftOperand()) and
|
||||
lUpper = getFullyConvertedUpperBounds(getLeftOperand()) and
|
||||
rLower = getFullyConvertedLowerBounds(getRightOperand()) and
|
||||
rUpper = getFullyConvertedUpperBounds(getRightOperand()) and
|
||||
lLower = getFullyConvertedLowerBounds(this.getLeftOperand()) and
|
||||
lUpper = getFullyConvertedUpperBounds(this.getLeftOperand()) and
|
||||
rLower = getFullyConvertedLowerBounds(this.getRightOperand()) and
|
||||
rUpper = getFullyConvertedUpperBounds(this.getRightOperand()) and
|
||||
lLower <= lUpper and
|
||||
rLower <= rUpper
|
||||
|
|
||||
@@ -122,8 +122,8 @@ class ConstantRShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||
lLower < 0
|
||||
or
|
||||
not (
|
||||
isValidShiftExprShift(rLower, getLeftOperand()) and
|
||||
isValidShiftExprShift(rUpper, getLeftOperand())
|
||||
isValidShiftExprShift(rLower, this.getLeftOperand()) and
|
||||
isValidShiftExprShift(rUpper, this.getLeftOperand())
|
||||
)
|
||||
then
|
||||
// We don't want to deal with shifting negative numbers at the moment,
|
||||
@@ -137,7 +137,7 @@ class ConstantRShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||
}
|
||||
|
||||
override predicate dependsOnChild(Expr child) {
|
||||
child = getLeftOperand() or child = getRightOperand()
|
||||
child = this.getLeftOperand() or child = this.getRightOperand()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ class ConstantLShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||
* We don't handle the case where `a` and `b` are both non-constant values.
|
||||
*/
|
||||
ConstantLShiftExprRange() {
|
||||
getUnspecifiedType() instanceof IntegralType and
|
||||
this.getUnspecifiedType() instanceof IntegralType and
|
||||
exists(Expr l, Expr r |
|
||||
l = this.(LShiftExpr).getLeftOperand() and
|
||||
r = this.(LShiftExpr).getRightOperand()
|
||||
@@ -197,10 +197,10 @@ class ConstantLShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||
|
||||
override float getLowerBounds() {
|
||||
exists(int lLower, int lUpper, int rLower, int rUpper |
|
||||
lLower = getFullyConvertedLowerBounds(getLeftOperand()) and
|
||||
lUpper = getFullyConvertedUpperBounds(getLeftOperand()) and
|
||||
rLower = getFullyConvertedLowerBounds(getRightOperand()) and
|
||||
rUpper = getFullyConvertedUpperBounds(getRightOperand()) and
|
||||
lLower = getFullyConvertedLowerBounds(this.getLeftOperand()) and
|
||||
lUpper = getFullyConvertedUpperBounds(this.getLeftOperand()) and
|
||||
rLower = getFullyConvertedLowerBounds(this.getRightOperand()) and
|
||||
rUpper = getFullyConvertedUpperBounds(this.getRightOperand()) and
|
||||
lLower <= lUpper and
|
||||
rLower <= rUpper
|
||||
|
|
||||
@@ -208,8 +208,8 @@ class ConstantLShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||
lLower < 0
|
||||
or
|
||||
not (
|
||||
isValidShiftExprShift(rLower, getLeftOperand()) and
|
||||
isValidShiftExprShift(rUpper, getLeftOperand())
|
||||
isValidShiftExprShift(rLower, this.getLeftOperand()) and
|
||||
isValidShiftExprShift(rUpper, this.getLeftOperand())
|
||||
)
|
||||
then
|
||||
// We don't want to deal with shifting negative numbers at the moment,
|
||||
@@ -228,10 +228,10 @@ class ConstantLShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||
|
||||
override float getUpperBounds() {
|
||||
exists(int lLower, int lUpper, int rLower, int rUpper |
|
||||
lLower = getFullyConvertedLowerBounds(getLeftOperand()) and
|
||||
lUpper = getFullyConvertedUpperBounds(getLeftOperand()) and
|
||||
rLower = getFullyConvertedLowerBounds(getRightOperand()) and
|
||||
rUpper = getFullyConvertedUpperBounds(getRightOperand()) and
|
||||
lLower = getFullyConvertedLowerBounds(this.getLeftOperand()) and
|
||||
lUpper = getFullyConvertedUpperBounds(this.getLeftOperand()) and
|
||||
rLower = getFullyConvertedLowerBounds(this.getRightOperand()) and
|
||||
rUpper = getFullyConvertedUpperBounds(this.getRightOperand()) and
|
||||
lLower <= lUpper and
|
||||
rLower <= rUpper
|
||||
|
|
||||
@@ -239,8 +239,8 @@ class ConstantLShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||
lLower < 0
|
||||
or
|
||||
not (
|
||||
isValidShiftExprShift(rLower, getLeftOperand()) and
|
||||
isValidShiftExprShift(rUpper, getLeftOperand())
|
||||
isValidShiftExprShift(rLower, this.getLeftOperand()) and
|
||||
isValidShiftExprShift(rUpper, this.getLeftOperand())
|
||||
)
|
||||
then
|
||||
// We don't want to deal with shifting negative numbers at the moment,
|
||||
@@ -258,6 +258,6 @@ class ConstantLShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||
}
|
||||
|
||||
override predicate dependsOnChild(Expr child) {
|
||||
child = getLeftOperand() or child = getRightOperand()
|
||||
child = this.getLeftOperand() or child = this.getRightOperand()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,20 +83,23 @@ private class ExprRangeNode extends DataFlow::ExprNode {
|
||||
private string getCallBounds(Call e) {
|
||||
result =
|
||||
getExprBoundAsString(e) + "(" +
|
||||
concat(Expr arg, int i | arg = e.getArgument(i) | getIntegralBounds(arg) order by i, ",") +
|
||||
")"
|
||||
concat(Expr arg, int i |
|
||||
arg = e.getArgument(i)
|
||||
|
|
||||
this.getIntegralBounds(arg), "," order by i
|
||||
) + ")"
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
exists(Expr e | e = getExpr() |
|
||||
exists(Expr e | e = this.getExpr() |
|
||||
if hasIntegralOrReferenceIntegralType(e)
|
||||
then
|
||||
result = super.toString() + ": " + getOperationBounds(e)
|
||||
result = super.toString() + ": " + this.getOperationBounds(e)
|
||||
or
|
||||
result = super.toString() + ": " + getCallBounds(e)
|
||||
result = super.toString() + ": " + this.getCallBounds(e)
|
||||
or
|
||||
not exists(getOperationBounds(e)) and
|
||||
not exists(getCallBounds(e)) and
|
||||
not exists(this.getOperationBounds(e)) and
|
||||
not exists(this.getCallBounds(e)) and
|
||||
result = super.toString() + ": " + getExprBoundAsString(e)
|
||||
else result = super.toString()
|
||||
)
|
||||
@@ -108,8 +111,8 @@ private class ExprRangeNode extends DataFlow::ExprNode {
|
||||
*/
|
||||
private class ReferenceArgumentRangeNode extends DataFlow::DefinitionByReferenceNode {
|
||||
override string toString() {
|
||||
if hasIntegralOrReferenceIntegralType(asDefiningArgument())
|
||||
then result = super.toString() + ": " + getExprBoundAsString(getArgument())
|
||||
if hasIntegralOrReferenceIntegralType(this.asDefiningArgument())
|
||||
then result = super.toString() + ": " + getExprBoundAsString(this.getArgument())
|
||||
else result = super.toString()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,12 @@ private import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysi
|
||||
*/
|
||||
class StrlenLiteralRangeExpr extends SimpleRangeAnalysisExpr, FunctionCall {
|
||||
StrlenLiteralRangeExpr() {
|
||||
getTarget().hasGlobalOrStdName("strlen") and getArgument(0).isConstant()
|
||||
this.getTarget().hasGlobalOrStdName("strlen") and this.getArgument(0).isConstant()
|
||||
}
|
||||
|
||||
override int getLowerBounds() { result = getArgument(0).getValue().length() }
|
||||
override int getLowerBounds() { result = this.getArgument(0).getValue().length() }
|
||||
|
||||
override int getUpperBounds() { result = getArgument(0).getValue().length() }
|
||||
override int getUpperBounds() { result = this.getArgument(0).getValue().length() }
|
||||
|
||||
override predicate dependsOnChild(Expr e) { none() }
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisExpr
|
||||
private class SelfSub extends SimpleRangeAnalysisExpr, SubExpr {
|
||||
SelfSub() {
|
||||
// Match `x - x` but not `myInt - (unsigned char)myInt`.
|
||||
getLeftOperand().getExplicitlyConverted().(VariableAccess).getTarget() =
|
||||
getRightOperand().getExplicitlyConverted().(VariableAccess).getTarget()
|
||||
this.getLeftOperand().getExplicitlyConverted().(VariableAccess).getTarget() =
|
||||
this.getRightOperand().getExplicitlyConverted().(VariableAccess).getTarget()
|
||||
}
|
||||
|
||||
override float getLowerBounds() { result = 0 }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.7.1-dev
|
||||
version: 0.7.2-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
@@ -9,3 +9,4 @@ dependencies:
|
||||
codeql/ssa: ${workspace}
|
||||
codeql/tutorial: ${workspace}
|
||||
codeql/util: ${workspace}
|
||||
warnOnImplicitThis: true
|
||||
|
||||
@@ -42,7 +42,7 @@ class Compilation extends @compilation {
|
||||
}
|
||||
|
||||
/** Gets a file compiled during this invocation. */
|
||||
File getAFileCompiled() { result = getFileCompiled(_) }
|
||||
File getAFileCompiled() { result = this.getFileCompiled(_) }
|
||||
|
||||
/** Gets the `i`th file compiled during this invocation */
|
||||
File getFileCompiled(int i) { compilation_compiling_files(this, i, unresolveElement(result)) }
|
||||
@@ -74,7 +74,7 @@ class Compilation extends @compilation {
|
||||
/**
|
||||
* Gets an argument passed to the extractor on this invocation.
|
||||
*/
|
||||
string getAnArgument() { result = getArgument(_) }
|
||||
string getAnArgument() { result = this.getArgument(_) }
|
||||
|
||||
/**
|
||||
* Gets the `i`th argument passed to the extractor on this invocation.
|
||||
|
||||
@@ -39,7 +39,8 @@ class Field extends MemberVariable {
|
||||
* complete most-derived object.
|
||||
*/
|
||||
int getAByteOffsetIn(Class mostDerivedClass) {
|
||||
result = mostDerivedClass.getABaseClassByteOffset(getDeclaringType()) + getByteOffset()
|
||||
result =
|
||||
mostDerivedClass.getABaseClassByteOffset(this.getDeclaringType()) + this.getByteOffset()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,10 +117,10 @@ class BitField extends Field {
|
||||
int getBitOffset() { fieldoffsets(underlyingElement(this), _, result) }
|
||||
|
||||
/** Holds if this bitfield is anonymous. */
|
||||
predicate isAnonymous() { hasName("(unnamed bitfield)") }
|
||||
predicate isAnonymous() { this.hasName("(unnamed bitfield)") }
|
||||
|
||||
override predicate isInitializable() {
|
||||
// Anonymous bitfields are not initializable.
|
||||
not isAnonymous()
|
||||
not this.isAnonymous()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,10 +24,10 @@ class LinkTarget extends @link_target {
|
||||
* captured as part of the snapshot, then everything is grouped together
|
||||
* into a single dummy link target.
|
||||
*/
|
||||
predicate isDummy() { getBinary().getAbsolutePath() = "" }
|
||||
predicate isDummy() { this.getBinary().getAbsolutePath() = "" }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = getBinary().getAbsolutePath() }
|
||||
string toString() { result = this.getBinary().getAbsolutePath() }
|
||||
|
||||
/**
|
||||
* Gets a function which was compiled into this link target, or had its
|
||||
|
||||
@@ -24,7 +24,7 @@ class NameQualifier extends NameQualifiableElement, @namequalifier {
|
||||
* Gets the expression ultimately qualified by the chain of name
|
||||
* qualifiers. For example, `f()` in `N1::N2::f()`.
|
||||
*/
|
||||
Expr getExpr() { result = getQualifiedElement+() }
|
||||
Expr getExpr() { result = this.getQualifiedElement+() }
|
||||
|
||||
/** Gets a location for this name qualifier. */
|
||||
override Location getLocation() { namequalifiers(underlyingElement(this), _, _, result) }
|
||||
@@ -56,12 +56,12 @@ class NameQualifier extends NameQualifiableElement, @namequalifier {
|
||||
if nqe instanceof SpecialNameQualifyingElement
|
||||
then
|
||||
exists(Access a |
|
||||
a = getQualifiedElement() and
|
||||
a = this.getQualifiedElement() and
|
||||
result = a.getTarget().getDeclaringType()
|
||||
)
|
||||
or
|
||||
exists(FunctionCall c |
|
||||
c = getQualifiedElement() and
|
||||
c = this.getQualifiedElement() and
|
||||
result = c.getTarget().getDeclaringType()
|
||||
)
|
||||
else result = nqe
|
||||
@@ -109,7 +109,7 @@ class NameQualifiableElement extends Element, @namequalifiableelement {
|
||||
* namespace.
|
||||
*/
|
||||
predicate hasGlobalQualifiedName() {
|
||||
getNameQualifier*().getQualifyingElement() instanceof GlobalNamespace
|
||||
this.getNameQualifier*().getQualifyingElement() instanceof GlobalNamespace
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,7 +119,7 @@ class NameQualifiableElement extends Element, @namequalifiableelement {
|
||||
*/
|
||||
predicate hasSuperQualifiedName() {
|
||||
exists(NameQualifier nq, SpecialNameQualifyingElement snqe |
|
||||
nq = getNameQualifier*() and
|
||||
nq = this.getNameQualifier*() and
|
||||
namequalifiers(unresolveElement(nq), _, unresolveElement(snqe), _) and
|
||||
snqe.getName() = "__super"
|
||||
)
|
||||
@@ -164,5 +164,5 @@ library class SpecialNameQualifyingElement extends NameQualifyingElement,
|
||||
/** Gets the name of this special qualifying element. */
|
||||
override string getName() { specialnamequalifyingelements(underlyingElement(this), result) }
|
||||
|
||||
override string toString() { result = getName() }
|
||||
override string toString() { result = this.getName() }
|
||||
}
|
||||
|
||||
@@ -230,8 +230,12 @@ class GlobalNamespace extends Namespace {
|
||||
}
|
||||
|
||||
/**
|
||||
* The C++ `std::` namespace.
|
||||
* The C++ `std::` namespace and its inline namespaces.
|
||||
*/
|
||||
class StdNamespace extends Namespace {
|
||||
StdNamespace() { this.hasName("std") and this.getParentNamespace() instanceof GlobalNamespace }
|
||||
StdNamespace() {
|
||||
this.hasName("std") and this.getParentNamespace() instanceof GlobalNamespace
|
||||
or
|
||||
this.isInline() and this.getParentNamespace() instanceof StdNamespace
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ class NestedFieldAccess extends FieldAccess {
|
||||
|
||||
NestedFieldAccess() {
|
||||
ultimateQualifier = getUltimateQualifier(this) and
|
||||
getTarget() = getANestedField(ultimateQualifier.getType().stripType())
|
||||
this.getTarget() = getANestedField(ultimateQualifier.getType().stripType())
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -130,7 +130,7 @@ class PrintAstNode extends TPrintAstNode {
|
||||
// The exact value of `childIndex` doesn't matter, as long as we preserve the correct order.
|
||||
result =
|
||||
rank[childIndex](PrintAstNode child, int nonConvertedIndex, boolean isConverted |
|
||||
childAndAccessorPredicate(child, _, nonConvertedIndex, isConverted)
|
||||
this.childAndAccessorPredicate(child, _, nonConvertedIndex, isConverted)
|
||||
|
|
||||
// Unconverted children come first, then sort by original child index within each group.
|
||||
child order by isConverted, nonConvertedIndex
|
||||
@@ -143,7 +143,7 @@ class PrintAstNode extends TPrintAstNode {
|
||||
*/
|
||||
private PrintAstNode getConvertedChild(int childIndex) {
|
||||
exists(Expr expr |
|
||||
expr = getChildInternal(childIndex).(AstNode).getAst() and
|
||||
expr = this.getChildInternal(childIndex).(AstNode).getAst() and
|
||||
expr.getFullyConverted() instanceof Conversion and
|
||||
result.(AstNode).getAst() = expr.getFullyConverted() and
|
||||
not expr instanceof Conversion
|
||||
@@ -155,8 +155,8 @@ class PrintAstNode extends TPrintAstNode {
|
||||
* at index `childIndex`, if that node has any conversions.
|
||||
*/
|
||||
private string getConvertedChildAccessorPredicate(int childIndex) {
|
||||
exists(getConvertedChild(childIndex)) and
|
||||
result = getChildAccessorPredicateInternal(childIndex) + ".getFullyConverted()"
|
||||
exists(this.getConvertedChild(childIndex)) and
|
||||
result = this.getChildAccessorPredicateInternal(childIndex) + ".getFullyConverted()"
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -164,12 +164,12 @@ class PrintAstNode extends TPrintAstNode {
|
||||
* within a function are printed, but the query can override
|
||||
* `PrintASTConfiguration.shouldPrintFunction` to filter the output.
|
||||
*/
|
||||
final predicate shouldPrint() { shouldPrintFunction(getEnclosingFunction()) }
|
||||
final predicate shouldPrint() { shouldPrintFunction(this.getEnclosingFunction()) }
|
||||
|
||||
/**
|
||||
* Gets the children of this node.
|
||||
*/
|
||||
final PrintAstNode getAChild() { result = getChild(_) }
|
||||
final PrintAstNode getAChild() { result = this.getChild(_) }
|
||||
|
||||
/**
|
||||
* Gets the parent of this node, if any.
|
||||
@@ -187,7 +187,7 @@ class PrintAstNode extends TPrintAstNode {
|
||||
*/
|
||||
string getProperty(string key) {
|
||||
key = "semmle.label" and
|
||||
result = toString()
|
||||
result = this.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,12 +201,12 @@ class PrintAstNode extends TPrintAstNode {
|
||||
private predicate childAndAccessorPredicate(
|
||||
PrintAstNode child, string childPredicate, int nonConvertedIndex, boolean isConverted
|
||||
) {
|
||||
child = getChildInternal(nonConvertedIndex) and
|
||||
childPredicate = getChildAccessorPredicateInternal(nonConvertedIndex) and
|
||||
child = this.getChildInternal(nonConvertedIndex) and
|
||||
childPredicate = this.getChildAccessorPredicateInternal(nonConvertedIndex) and
|
||||
isConverted = false
|
||||
or
|
||||
child = getConvertedChild(nonConvertedIndex) and
|
||||
childPredicate = getConvertedChildAccessorPredicate(nonConvertedIndex) and
|
||||
child = this.getConvertedChild(nonConvertedIndex) and
|
||||
childPredicate = this.getConvertedChildAccessorPredicate(nonConvertedIndex) and
|
||||
isConverted = true
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ class PrintAstNode extends TPrintAstNode {
|
||||
// The exact value of `childIndex` doesn't matter, as long as we preserve the correct order.
|
||||
result =
|
||||
rank[childIndex](string childPredicate, int nonConvertedIndex, boolean isConverted |
|
||||
childAndAccessorPredicate(_, childPredicate, nonConvertedIndex, isConverted)
|
||||
this.childAndAccessorPredicate(_, childPredicate, nonConvertedIndex, isConverted)
|
||||
|
|
||||
// Unconverted children come first, then sort by original child index within each group.
|
||||
childPredicate order by isConverted, nonConvertedIndex
|
||||
@@ -234,7 +234,9 @@ class PrintAstNode extends TPrintAstNode {
|
||||
/**
|
||||
* Gets the `Function` that contains this node.
|
||||
*/
|
||||
private Function getEnclosingFunction() { result = getParent*().(FunctionNode).getFunction() }
|
||||
private Function getEnclosingFunction() {
|
||||
result = this.getParent*().(FunctionNode).getFunction()
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for PrintAstNode */
|
||||
@@ -253,7 +255,7 @@ private class PrintableElement extends Element {
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
string getAPrimaryQlClass0() { result = getAPrimaryQlClass() }
|
||||
string getAPrimaryQlClass0() { result = this.getAPrimaryQlClass() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -281,7 +283,7 @@ abstract class BaseAstNode extends PrintAstNode {
|
||||
final Locatable getAst() { result = ast }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated Locatable getAST() { result = getAst() }
|
||||
deprecated Locatable getAST() { result = this.getAst() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for BaseAstNode */
|
||||
@@ -311,7 +313,7 @@ class ExprNode extends AstNode {
|
||||
result = super.getProperty(key)
|
||||
or
|
||||
key = "Value" and
|
||||
result = qlClass(expr) + getValue()
|
||||
result = qlClass(expr) + this.getValue()
|
||||
or
|
||||
key = "Type" and
|
||||
result = qlClass(expr.getType()) + expr.getType().toString()
|
||||
@@ -321,7 +323,7 @@ class ExprNode extends AstNode {
|
||||
}
|
||||
|
||||
override string getChildAccessorPredicateInternal(int childIndex) {
|
||||
result = getChildAccessorWithoutConversions(ast, getChildInternal(childIndex).getAst())
|
||||
result = getChildAccessorWithoutConversions(ast, this.getChildInternal(childIndex).getAst())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -441,7 +443,7 @@ class StmtNode extends AstNode {
|
||||
}
|
||||
|
||||
override string getChildAccessorPredicateInternal(int childIndex) {
|
||||
result = getChildAccessorWithoutConversions(ast, getChildInternal(childIndex).getAst())
|
||||
result = getChildAccessorWithoutConversions(ast, this.getChildInternal(childIndex).getAst())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -517,7 +519,7 @@ class ParametersNode extends PrintAstNode, TParametersNode {
|
||||
}
|
||||
|
||||
override string getChildAccessorPredicateInternal(int childIndex) {
|
||||
exists(getChildInternal(childIndex)) and
|
||||
exists(this.getChildInternal(childIndex)) and
|
||||
result = "getParameter(" + childIndex.toString() + ")"
|
||||
}
|
||||
|
||||
@@ -544,7 +546,7 @@ class ConstructorInitializersNode extends PrintAstNode, TConstructorInitializers
|
||||
}
|
||||
|
||||
final override string getChildAccessorPredicateInternal(int childIndex) {
|
||||
exists(getChildInternal(childIndex)) and
|
||||
exists(this.getChildInternal(childIndex)) and
|
||||
result = "getInitializer(" + childIndex.toString() + ")"
|
||||
}
|
||||
|
||||
@@ -571,7 +573,7 @@ class DestructorDestructionsNode extends PrintAstNode, TDestructorDestructionsNo
|
||||
}
|
||||
|
||||
final override string getChildAccessorPredicateInternal(int childIndex) {
|
||||
exists(getChildInternal(childIndex)) and
|
||||
exists(this.getChildInternal(childIndex)) and
|
||||
result = "getDestruction(" + childIndex.toString() + ")"
|
||||
}
|
||||
|
||||
@@ -628,7 +630,7 @@ class FunctionNode extends AstNode {
|
||||
override string getProperty(string key) {
|
||||
result = super.getProperty(key)
|
||||
or
|
||||
key = "semmle.order" and result = getOrder().toString()
|
||||
key = "semmle.order" and result = this.getOrder().toString()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1699,7 +1699,28 @@ class AutoType extends TemplateParameter {
|
||||
|
||||
private predicate suppressUnusedThis(Type t) { any() }
|
||||
|
||||
/** A source code location referring to a type */
|
||||
/**
|
||||
* A source code location referring to a user-defined type.
|
||||
*
|
||||
* Note that only _user-defined_ types have `TypeMention`s. In particular,
|
||||
* built-in types, and derived types with built-in types as their base don't
|
||||
* have any `TypeMention`s. For example, given
|
||||
* ```cpp
|
||||
* struct S { ... };
|
||||
* void f(S s1, int i1) {
|
||||
* S s2;
|
||||
* S* s3;
|
||||
* S& s4 = s2;
|
||||
* decltype(s2) s5;
|
||||
*
|
||||
* int i2;
|
||||
* int* i3;
|
||||
* int i4[10];
|
||||
* }
|
||||
* ```
|
||||
* there will be a `TypeMention` for the mention of `S` at `S s1`, `S s2`, and `S& s4 = s2`,
|
||||
* but not at `decltype(s2) s5`. Additionally, there will be no `TypeMention`s for `int`.
|
||||
*/
|
||||
class TypeMention extends Locatable, @type_mention {
|
||||
override string toString() { result = "type mention" }
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import cpp
|
||||
*/
|
||||
deprecated class StrcatFunction extends Function {
|
||||
StrcatFunction() {
|
||||
getName() =
|
||||
this.getName() =
|
||||
[
|
||||
"strcat", // strcat(dst, src)
|
||||
"strncat", // strncat(dst, src, max_amount)
|
||||
|
||||
@@ -98,7 +98,7 @@ library class DefOrUse extends ControlFlowNodeBase {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate reaches_helper(boolean isDef, SemanticStackVariable v, BasicBlock bb, int i) {
|
||||
getVariable(isDef) = v and
|
||||
this.getVariable(isDef) = v and
|
||||
bb.getNode(i) = this
|
||||
}
|
||||
|
||||
@@ -118,21 +118,21 @@ library class DefOrUse extends ControlFlowNodeBase {
|
||||
* predicates are duplicated for now.
|
||||
*/
|
||||
|
||||
exists(BasicBlock bb, int i | reaches_helper(isDef, v, bb, i) |
|
||||
exists(BasicBlock bb, int i | this.reaches_helper(isDef, v, bb, i) |
|
||||
exists(int j |
|
||||
j > i and
|
||||
(bbDefAt(bb, j, v, defOrUse) or bbUseAt(bb, j, v, defOrUse)) and
|
||||
not exists(int k | firstBarrierAfterThis(isDef, k, v) and k < j)
|
||||
not exists(int k | this.firstBarrierAfterThis(isDef, k, v) and k < j)
|
||||
)
|
||||
or
|
||||
not firstBarrierAfterThis(isDef, _, v) and
|
||||
not this.firstBarrierAfterThis(isDef, _, v) and
|
||||
bbSuccessorEntryReachesDefOrUse(bb, v, defOrUse, _)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate firstBarrierAfterThis(boolean isDef, int j, SemanticStackVariable v) {
|
||||
exists(BasicBlock bb, int i |
|
||||
getVariable(isDef) = v and
|
||||
this.getVariable(isDef) = v and
|
||||
bb.getNode(i) = this and
|
||||
j = min(int k | bbBarrierAt(bb, k, v, _) and k > i)
|
||||
)
|
||||
|
||||
@@ -130,7 +130,7 @@ library class SsaHelper extends int {
|
||||
* Remove any custom phi nodes that are invalid.
|
||||
*/
|
||||
private predicate sanitized_custom_phi_node(StackVariable v, BasicBlock b) {
|
||||
custom_phi_node(v, b) and
|
||||
this.custom_phi_node(v, b) and
|
||||
not addressTakenVariable(v) and
|
||||
not isReferenceVar(v) and
|
||||
b.isReachable()
|
||||
@@ -142,7 +142,7 @@ library class SsaHelper extends int {
|
||||
*/
|
||||
cached
|
||||
predicate phi_node(StackVariable v, BasicBlock b) {
|
||||
frontier_phi_node(v, b) or sanitized_custom_phi_node(v, b)
|
||||
this.frontier_phi_node(v, b) or this.sanitized_custom_phi_node(v, b)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -154,14 +154,15 @@ library class SsaHelper extends int {
|
||||
*/
|
||||
private predicate frontier_phi_node(StackVariable v, BasicBlock b) {
|
||||
exists(BasicBlock x |
|
||||
dominanceFrontier(x, b) and ssa_defn_rec(pragma[only_bind_into](v), pragma[only_bind_into](x))
|
||||
dominanceFrontier(x, b) and
|
||||
this.ssa_defn_rec(pragma[only_bind_into](v), pragma[only_bind_into](x))
|
||||
) and
|
||||
/* We can also eliminate those nodes where the variable is not live on any incoming edge */
|
||||
live_at_start_of_bb(pragma[only_bind_into](v), b)
|
||||
}
|
||||
|
||||
private predicate ssa_defn_rec(StackVariable v, BasicBlock b) {
|
||||
phi_node(v, b)
|
||||
this.phi_node(v, b)
|
||||
or
|
||||
variableUpdate(v, _, b, _)
|
||||
}
|
||||
@@ -172,7 +173,7 @@ library class SsaHelper extends int {
|
||||
*/
|
||||
cached
|
||||
predicate ssa_defn(StackVariable v, ControlFlowNode node, BasicBlock b, int index) {
|
||||
phi_node(v, b) and b.getStart() = node and index = -1
|
||||
this.phi_node(v, b) and b.getStart() = node and index = -1
|
||||
or
|
||||
variableUpdate(v, node, b, index)
|
||||
}
|
||||
@@ -196,7 +197,7 @@ library class SsaHelper extends int {
|
||||
* basic blocks.
|
||||
*/
|
||||
private predicate defUseRank(StackVariable v, BasicBlock b, int rankix, int i) {
|
||||
i = rank[rankix](int j | ssa_defn(v, _, b, j) or ssa_use(v, _, b, j))
|
||||
i = rank[rankix](int j | this.ssa_defn(v, _, b, j) or ssa_use(v, _, b, j))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -206,7 +207,7 @@ library class SsaHelper extends int {
|
||||
* the block.
|
||||
*/
|
||||
private int lastRank(StackVariable v, BasicBlock b) {
|
||||
result = max(int rankix | defUseRank(v, b, rankix, _)) + 1
|
||||
result = max(int rankix | this.defUseRank(v, b, rankix, _)) + 1
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -215,8 +216,8 @@ library class SsaHelper extends int {
|
||||
*/
|
||||
private predicate ssaDefRank(StackVariable v, ControlFlowNode def, BasicBlock b, int rankix) {
|
||||
exists(int i |
|
||||
ssa_defn(v, def, b, i) and
|
||||
defUseRank(v, b, rankix, i)
|
||||
this.ssa_defn(v, def, b, i) and
|
||||
this.defUseRank(v, b, rankix, i)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -232,21 +233,21 @@ library class SsaHelper extends int {
|
||||
// use is understood to happen _before_ the definition. Phi nodes are
|
||||
// at rankidx -1 and will therefore always reach the first node in the
|
||||
// basic block.
|
||||
ssaDefRank(v, def, b, rankix - 1)
|
||||
this.ssaDefRank(v, def, b, rankix - 1)
|
||||
or
|
||||
ssaDefReachesRank(v, def, b, rankix - 1) and
|
||||
rankix <= lastRank(v, b) and // Without this, the predicate would be infinite.
|
||||
not ssaDefRank(v, _, b, rankix - 1) // Range is inclusive of but not past next def.
|
||||
this.ssaDefReachesRank(v, def, b, rankix - 1) and
|
||||
rankix <= this.lastRank(v, b) and // Without this, the predicate would be infinite.
|
||||
not this.ssaDefRank(v, _, b, rankix - 1) // Range is inclusive of but not past next def.
|
||||
}
|
||||
|
||||
/** Holds if SSA variable `(v, def)` reaches the end of block `b`. */
|
||||
cached
|
||||
predicate ssaDefinitionReachesEndOfBB(StackVariable v, ControlFlowNode def, BasicBlock b) {
|
||||
live_at_exit_of_bb(v, b) and ssaDefReachesRank(v, def, b, lastRank(v, b))
|
||||
live_at_exit_of_bb(v, b) and this.ssaDefReachesRank(v, def, b, this.lastRank(v, b))
|
||||
or
|
||||
exists(BasicBlock idom |
|
||||
ssaDefinitionReachesEndOfBB(v, def, idom) and
|
||||
noDefinitionsSinceIDominator(v, idom, b)
|
||||
this.ssaDefinitionReachesEndOfBB(v, def, idom) and
|
||||
this.noDefinitionsSinceIDominator(v, idom, b)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -260,7 +261,7 @@ library class SsaHelper extends int {
|
||||
private predicate noDefinitionsSinceIDominator(StackVariable v, BasicBlock idom, BasicBlock b) {
|
||||
bbIDominates(idom, b) and // It is sufficient to traverse the dominator graph, cf. discussion above.
|
||||
live_at_exit_of_bb(v, b) and
|
||||
not ssa_defn(v, _, b, _)
|
||||
not this.ssa_defn(v, _, b, _)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -269,8 +270,8 @@ library class SsaHelper extends int {
|
||||
*/
|
||||
private predicate ssaDefinitionReachesUseWithinBB(StackVariable v, ControlFlowNode def, Expr use) {
|
||||
exists(BasicBlock b, int rankix, int i |
|
||||
ssaDefReachesRank(v, def, b, rankix) and
|
||||
defUseRank(v, b, rankix, i) and
|
||||
this.ssaDefReachesRank(v, def, b, rankix) and
|
||||
this.defUseRank(v, b, rankix, i) and
|
||||
ssa_use(v, use, b, i)
|
||||
)
|
||||
}
|
||||
@@ -279,12 +280,12 @@ library class SsaHelper extends int {
|
||||
* Holds if SSA variable `(v, def)` reaches the control-flow node `use`.
|
||||
*/
|
||||
private predicate ssaDefinitionReaches(StackVariable v, ControlFlowNode def, Expr use) {
|
||||
ssaDefinitionReachesUseWithinBB(v, def, use)
|
||||
this.ssaDefinitionReachesUseWithinBB(v, def, use)
|
||||
or
|
||||
exists(BasicBlock b |
|
||||
ssa_use(v, use, b, _) and
|
||||
ssaDefinitionReachesEndOfBB(v, def, b.getAPredecessor()) and
|
||||
not ssaDefinitionReachesUseWithinBB(v, _, use)
|
||||
this.ssaDefinitionReachesEndOfBB(v, def, b.getAPredecessor()) and
|
||||
not this.ssaDefinitionReachesUseWithinBB(v, _, use)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -294,10 +295,10 @@ library class SsaHelper extends int {
|
||||
*/
|
||||
cached
|
||||
string toString(ControlFlowNode node, StackVariable v) {
|
||||
if phi_node(v, node)
|
||||
if this.phi_node(v, node)
|
||||
then result = "SSA phi(" + v.getName() + ")"
|
||||
else (
|
||||
ssa_defn(v, node, _, _) and result = "SSA def(" + v.getName() + ")"
|
||||
this.ssa_defn(v, node, _, _) and result = "SSA def(" + v.getName() + ")"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -307,7 +308,7 @@ library class SsaHelper extends int {
|
||||
*/
|
||||
cached
|
||||
VariableAccess getAUse(ControlFlowNode def, StackVariable v) {
|
||||
ssaDefinitionReaches(v, def, result) and
|
||||
this.ssaDefinitionReaches(v, def, result) and
|
||||
ssa_use(v, result, _, _)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import cpp
|
||||
*/
|
||||
abstract class StackVariableReachability extends string {
|
||||
bindingset[this]
|
||||
StackVariableReachability() { length() >= 0 }
|
||||
StackVariableReachability() { this.length() >= 0 }
|
||||
|
||||
/** Holds if `node` is a source for the reachability analysis using variable `v`. */
|
||||
abstract predicate isSource(ControlFlowNode node, StackVariable v);
|
||||
@@ -227,7 +227,7 @@ predicate bbSuccessorEntryReachesLoopInvariant(
|
||||
*/
|
||||
abstract class StackVariableReachabilityWithReassignment extends StackVariableReachability {
|
||||
bindingset[this]
|
||||
StackVariableReachabilityWithReassignment() { length() >= 0 }
|
||||
StackVariableReachabilityWithReassignment() { this.length() >= 0 }
|
||||
|
||||
/** Override this predicate rather than `isSource` (`isSource` is used internally). */
|
||||
abstract predicate isSourceActual(ControlFlowNode node, StackVariable v);
|
||||
@@ -330,7 +330,7 @@ abstract class StackVariableReachabilityWithReassignment extends StackVariableRe
|
||||
*/
|
||||
abstract class StackVariableReachabilityExt extends string {
|
||||
bindingset[this]
|
||||
StackVariableReachabilityExt() { length() >= 0 }
|
||||
StackVariableReachabilityExt() { this.length() >= 0 }
|
||||
|
||||
/** `node` is a source for the reachability analysis using variable `v`. */
|
||||
abstract predicate isSource(ControlFlowNode node, StackVariable v);
|
||||
|
||||
@@ -961,8 +961,16 @@ predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
|
||||
/**
|
||||
* A `Node` at which a cast can occur such that the type should be checked.
|
||||
*/
|
||||
class CastingNode extends Node {
|
||||
class CastingNode instanceof Node {
|
||||
CastingNode() { castingNode(this) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate readStepWithTypes(
|
||||
@@ -1110,9 +1118,17 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable)
|
||||
* The value of a parameter at function entry, viewed as a node in a data
|
||||
* flow graph.
|
||||
*/
|
||||
class ParamNode extends Node {
|
||||
class ParamNode instanceof Node {
|
||||
ParamNode() { parameterNode(this, _, _) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this node is the parameter of callable `c` at the specified
|
||||
* position.
|
||||
@@ -1121,9 +1137,17 @@ class ParamNode extends Node {
|
||||
}
|
||||
|
||||
/** A data-flow node that represents a call argument. */
|
||||
class ArgNode extends Node {
|
||||
class ArgNode instanceof Node {
|
||||
ArgNode() { argumentNode(this, _, _) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Holds if this argument occurs at the given position in the given call. */
|
||||
final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
|
||||
argumentNode(this, call, pos)
|
||||
@@ -1134,9 +1158,17 @@ class ArgNode extends Node {
|
||||
* A node from which flow can return to the caller. This is either a regular
|
||||
* `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.
|
||||
*/
|
||||
class ReturnNodeExt extends Node {
|
||||
class ReturnNodeExt instanceof Node {
|
||||
ReturnNodeExt() { returnNodeExt(this, _) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets the kind of this returned value. */
|
||||
ReturnKindExt getKind() { returnNodeExt(this, result) }
|
||||
}
|
||||
@@ -1145,8 +1177,16 @@ class ReturnNodeExt extends Node {
|
||||
* A node to which data can flow from a call. Either an ordinary out node
|
||||
* or a post-update node associated with a call argument.
|
||||
*/
|
||||
class OutNodeExt extends Node {
|
||||
class OutNodeExt instanceof Node {
|
||||
OutNodeExt() { outNodeExt(this) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -58,6 +58,9 @@ module Consistency {
|
||||
predicate uniqueParameterNodePositionExclude(DataFlowCallable c, ParameterPosition pos, Node p) {
|
||||
none()
|
||||
}
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `identityLocalStep`. */
|
||||
predicate identityLocalStepExclude(Node n) { none() }
|
||||
}
|
||||
|
||||
private class RelevantNode extends Node {
|
||||
@@ -287,4 +290,10 @@ module Consistency {
|
||||
not exists(unique(ContentApprox approx | approx = getContentApprox(c))) and
|
||||
msg = "Non-unique content approximation."
|
||||
}
|
||||
|
||||
query predicate identityLocalStep(Node n, string msg) {
|
||||
simpleLocalFlowStep(n, n) and
|
||||
not any(ConsistencyConfiguration c).identityLocalStepExclude(n) and
|
||||
msg = "Node steps to itself"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,9 +76,9 @@ class GTExpr extends RelationalOperation, @gtexpr {
|
||||
|
||||
override string getOperator() { result = ">" }
|
||||
|
||||
override Expr getGreaterOperand() { result = getLeftOperand() }
|
||||
override Expr getGreaterOperand() { result = this.getLeftOperand() }
|
||||
|
||||
override Expr getLesserOperand() { result = getRightOperand() }
|
||||
override Expr getLesserOperand() { result = this.getRightOperand() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,9 +92,9 @@ class LTExpr extends RelationalOperation, @ltexpr {
|
||||
|
||||
override string getOperator() { result = "<" }
|
||||
|
||||
override Expr getGreaterOperand() { result = getRightOperand() }
|
||||
override Expr getGreaterOperand() { result = this.getRightOperand() }
|
||||
|
||||
override Expr getLesserOperand() { result = getLeftOperand() }
|
||||
override Expr getLesserOperand() { result = this.getLeftOperand() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,9 +108,9 @@ class GEExpr extends RelationalOperation, @geexpr {
|
||||
|
||||
override string getOperator() { result = ">=" }
|
||||
|
||||
override Expr getGreaterOperand() { result = getLeftOperand() }
|
||||
override Expr getGreaterOperand() { result = this.getLeftOperand() }
|
||||
|
||||
override Expr getLesserOperand() { result = getRightOperand() }
|
||||
override Expr getLesserOperand() { result = this.getRightOperand() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,7 +124,7 @@ class LEExpr extends RelationalOperation, @leexpr {
|
||||
|
||||
override string getOperator() { result = "<=" }
|
||||
|
||||
override Expr getGreaterOperand() { result = getRightOperand() }
|
||||
override Expr getGreaterOperand() { result = this.getRightOperand() }
|
||||
|
||||
override Expr getLesserOperand() { result = getLeftOperand() }
|
||||
override Expr getLesserOperand() { result = this.getLeftOperand() }
|
||||
}
|
||||
|
||||
@@ -961,8 +961,16 @@ predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
|
||||
/**
|
||||
* A `Node` at which a cast can occur such that the type should be checked.
|
||||
*/
|
||||
class CastingNode extends Node {
|
||||
class CastingNode instanceof Node {
|
||||
CastingNode() { castingNode(this) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate readStepWithTypes(
|
||||
@@ -1110,9 +1118,17 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable)
|
||||
* The value of a parameter at function entry, viewed as a node in a data
|
||||
* flow graph.
|
||||
*/
|
||||
class ParamNode extends Node {
|
||||
class ParamNode instanceof Node {
|
||||
ParamNode() { parameterNode(this, _, _) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this node is the parameter of callable `c` at the specified
|
||||
* position.
|
||||
@@ -1121,9 +1137,17 @@ class ParamNode extends Node {
|
||||
}
|
||||
|
||||
/** A data-flow node that represents a call argument. */
|
||||
class ArgNode extends Node {
|
||||
class ArgNode instanceof Node {
|
||||
ArgNode() { argumentNode(this, _, _) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Holds if this argument occurs at the given position in the given call. */
|
||||
final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
|
||||
argumentNode(this, call, pos)
|
||||
@@ -1134,9 +1158,17 @@ class ArgNode extends Node {
|
||||
* A node from which flow can return to the caller. This is either a regular
|
||||
* `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.
|
||||
*/
|
||||
class ReturnNodeExt extends Node {
|
||||
class ReturnNodeExt instanceof Node {
|
||||
ReturnNodeExt() { returnNodeExt(this, _) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets the kind of this returned value. */
|
||||
ReturnKindExt getKind() { returnNodeExt(this, result) }
|
||||
}
|
||||
@@ -1145,8 +1177,16 @@ class ReturnNodeExt extends Node {
|
||||
* A node to which data can flow from a call. Either an ordinary out node
|
||||
* or a post-update node associated with a call argument.
|
||||
*/
|
||||
class OutNodeExt extends Node {
|
||||
class OutNodeExt instanceof Node {
|
||||
OutNodeExt() { outNodeExt(this) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -58,6 +58,9 @@ module Consistency {
|
||||
predicate uniqueParameterNodePositionExclude(DataFlowCallable c, ParameterPosition pos, Node p) {
|
||||
none()
|
||||
}
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `identityLocalStep`. */
|
||||
predicate identityLocalStepExclude(Node n) { none() }
|
||||
}
|
||||
|
||||
private class RelevantNode extends Node {
|
||||
@@ -287,4 +290,10 @@ module Consistency {
|
||||
not exists(unique(ContentApprox approx | approx = getContentApprox(c))) and
|
||||
msg = "Non-unique content approximation."
|
||||
}
|
||||
|
||||
query predicate identityLocalStep(Node n, string msg) {
|
||||
simpleLocalFlowStep(n, n) and
|
||||
not any(ConsistencyConfiguration c).identityLocalStepExclude(n) and
|
||||
msg = "Node steps to itself"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,8 +210,8 @@ class IndirectOperand extends Node {
|
||||
this.(RawIndirectOperand).getOperand() = operand and
|
||||
this.(RawIndirectOperand).getIndirectionIndex() = indirectionIndex
|
||||
or
|
||||
this.(OperandNode).getOperand() =
|
||||
Ssa::getIRRepresentationOfIndirectOperand(operand, indirectionIndex)
|
||||
nodeHasOperand(this, Ssa::getIRRepresentationOfIndirectOperand(operand, indirectionIndex),
|
||||
indirectionIndex - 1)
|
||||
}
|
||||
|
||||
/** Gets the underlying operand. */
|
||||
@@ -250,8 +250,8 @@ class IndirectInstruction extends Node {
|
||||
this.(RawIndirectInstruction).getInstruction() = instr and
|
||||
this.(RawIndirectInstruction).getIndirectionIndex() = indirectionIndex
|
||||
or
|
||||
this.(InstructionNode).getInstruction() =
|
||||
Ssa::getIRRepresentationOfIndirectInstruction(instr, indirectionIndex)
|
||||
nodeHasInstruction(this, Ssa::getIRRepresentationOfIndirectInstruction(instr, indirectionIndex),
|
||||
indirectionIndex - 1)
|
||||
}
|
||||
|
||||
/** Gets the underlying instruction. */
|
||||
@@ -607,13 +607,21 @@ OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) {
|
||||
result.getReturnKind() = kind
|
||||
}
|
||||
|
||||
/** A variable that behaves like a global variable. */
|
||||
class GlobalLikeVariable extends Variable {
|
||||
GlobalLikeVariable() {
|
||||
this instanceof Cpp::GlobalOrNamespaceVariable or
|
||||
this instanceof Cpp::StaticLocalVariable
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` in a way that loses the
|
||||
* calling context. For example, this would happen with flow through a
|
||||
* global or static variable.
|
||||
*/
|
||||
predicate jumpStep(Node n1, Node n2) {
|
||||
exists(Cpp::GlobalOrNamespaceVariable v |
|
||||
exists(GlobalLikeVariable v |
|
||||
exists(Ssa::GlobalUse globalUse |
|
||||
v = globalUse.getVariable() and
|
||||
n1.(FinalGlobalValue).getGlobalUse() = globalUse
|
||||
|
||||
@@ -562,6 +562,14 @@ class SsaPhiNode extends Node, TSsaPhiNode {
|
||||
|
||||
/** Gets the source variable underlying this phi node. */
|
||||
Ssa::SourceVariable getSourceVariable() { result = phi.getSourceVariable() }
|
||||
|
||||
/**
|
||||
* Holds if this phi node is a phi-read node.
|
||||
*
|
||||
* Phi-read nodes are like normal phi nodes, but they are inserted based
|
||||
* on reads instead of writes.
|
||||
*/
|
||||
predicate isPhiRead() { phi.isPhiRead() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1540,7 +1548,7 @@ private module Cached {
|
||||
cached
|
||||
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
// Post update node -> Node flow
|
||||
Ssa::ssaFlow(nodeFrom.(PostUpdateNode).getPreUpdateNode(), nodeTo)
|
||||
Ssa::postUpdateFlow(nodeFrom, nodeTo)
|
||||
or
|
||||
// Def-use/Use-use flow
|
||||
Ssa::ssaFlow(nodeFrom, nodeTo)
|
||||
@@ -1903,7 +1911,38 @@ signature predicate guardChecksSig(IRGuardCondition g, Expr e, boolean branch);
|
||||
* in data flow and taint tracking.
|
||||
*/
|
||||
module BarrierGuard<guardChecksSig/3 guardChecks> {
|
||||
/** Gets a node that is safely guarded by the given guard check. */
|
||||
/**
|
||||
* Gets an expression node that is safely guarded by the given guard check.
|
||||
*
|
||||
* For example, given the following code:
|
||||
* ```cpp
|
||||
* int x = source();
|
||||
* // ...
|
||||
* if(is_safe_int(x)) {
|
||||
* sink(x);
|
||||
* }
|
||||
* ```
|
||||
* and the following barrier guard predicate:
|
||||
* ```ql
|
||||
* predicate myGuardChecks(IRGuardCondition g, Expr e, boolean branch) {
|
||||
* exists(Call call |
|
||||
* g.getUnconvertedResultExpression() = call and
|
||||
* call.getTarget().hasName("is_safe_int") and
|
||||
* e = call.getAnArgument() and
|
||||
* branch = true
|
||||
* )
|
||||
* }
|
||||
* ```
|
||||
* implementing `isBarrier` as:
|
||||
* ```ql
|
||||
* predicate isBarrier(DataFlow::Node barrier) {
|
||||
* barrier = DataFlow::BarrierGuard<myGuardChecks/3>::getABarrierNode()
|
||||
* }
|
||||
* ```
|
||||
* will block flow from `x = source()` to `sink(x)`.
|
||||
*
|
||||
* NOTE: If an indirect expression is tracked, use `getAnIndirectBarrierNode` instead.
|
||||
*/
|
||||
ExprNode getABarrierNode() {
|
||||
exists(IRGuardCondition g, Expr e, ValueNumber value, boolean edge |
|
||||
e = value.getAnInstruction().getConvertedResultExpression() and
|
||||
@@ -1912,6 +1951,84 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
|
||||
g.controls(result.getBasicBlock(), edge)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an indirect expression node that is safely guarded by the given guard check.
|
||||
*
|
||||
* For example, given the following code:
|
||||
* ```cpp
|
||||
* int* p;
|
||||
* // ...
|
||||
* *p = source();
|
||||
* if(is_safe_pointer(p)) {
|
||||
* sink(*p);
|
||||
* }
|
||||
* ```
|
||||
* and the following barrier guard check:
|
||||
* ```ql
|
||||
* predicate myGuardChecks(IRGuardCondition g, Expr e, boolean branch) {
|
||||
* exists(Call call |
|
||||
* g.getUnconvertedResultExpression() = call and
|
||||
* call.getTarget().hasName("is_safe_pointer") and
|
||||
* e = call.getAnArgument() and
|
||||
* branch = true
|
||||
* )
|
||||
* }
|
||||
* ```
|
||||
* implementing `isBarrier` as:
|
||||
* ```ql
|
||||
* predicate isBarrier(DataFlow::Node barrier) {
|
||||
* barrier = DataFlow::BarrierGuard<myGuardChecks/3>::getAnIndirectBarrierNode()
|
||||
* }
|
||||
* ```
|
||||
* will block flow from `x = source()` to `sink(x)`.
|
||||
*
|
||||
* NOTE: If a non-indirect expression is tracked, use `getABarrierNode` instead.
|
||||
*/
|
||||
IndirectExprNode getAnIndirectBarrierNode() { result = getAnIndirectBarrierNode(_) }
|
||||
|
||||
/**
|
||||
* Gets an indirect expression node with indirection index `indirectionIndex` that is
|
||||
* safely guarded by the given guard check.
|
||||
*
|
||||
* For example, given the following code:
|
||||
* ```cpp
|
||||
* int* p;
|
||||
* // ...
|
||||
* *p = source();
|
||||
* if(is_safe_pointer(p)) {
|
||||
* sink(*p);
|
||||
* }
|
||||
* ```
|
||||
* and the following barrier guard check:
|
||||
* ```ql
|
||||
* predicate myGuardChecks(IRGuardCondition g, Expr e, boolean branch) {
|
||||
* exists(Call call |
|
||||
* g.getUnconvertedResultExpression() = call and
|
||||
* call.getTarget().hasName("is_safe_pointer") and
|
||||
* e = call.getAnArgument() and
|
||||
* branch = true
|
||||
* )
|
||||
* }
|
||||
* ```
|
||||
* implementing `isBarrier` as:
|
||||
* ```ql
|
||||
* predicate isBarrier(DataFlow::Node barrier) {
|
||||
* barrier = DataFlow::BarrierGuard<myGuardChecks/3>::getAnIndirectBarrierNode(1)
|
||||
* }
|
||||
* ```
|
||||
* will block flow from `x = source()` to `sink(x)`.
|
||||
*
|
||||
* NOTE: If a non-indirect expression is tracked, use `getABarrierNode` instead.
|
||||
*/
|
||||
IndirectExprNode getAnIndirectBarrierNode(int indirectionIndex) {
|
||||
exists(IRGuardCondition g, Expr e, ValueNumber value, boolean edge |
|
||||
e = value.getAnInstruction().getConvertedResultExpression() and
|
||||
result.getConvertedExpr(indirectionIndex) = e and
|
||||
guardChecks(g, value.getAnInstruction().getConvertedResultExpression(), edge) and
|
||||
g.controls(result.getBasicBlock(), edge)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Print the dataflow local store steps in IR dumps.
|
||||
*/
|
||||
|
||||
private import cpp
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
|
||||
private import PrintIRUtilities
|
||||
|
||||
/** A property provider for local IR dataflow store steps. */
|
||||
class FieldFlowPropertyProvider extends IRPropertyProvider {
|
||||
override string getOperandProperty(Operand operand, string key) {
|
||||
exists(PostFieldUpdateNode pfun, Content content |
|
||||
key = "store " + content.toString() and
|
||||
operand = pfun.getPreUpdateNode().(IndirectOperand).getOperand() and
|
||||
result =
|
||||
strictconcat(string element, Node node |
|
||||
storeStep(node, content, pfun) and
|
||||
element = nodeId(node, _, _)
|
||||
|
|
||||
element, ", "
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(Node node2, Content content |
|
||||
key = "read " + content.toString() and
|
||||
operand = node2.(IndirectOperand).getOperand() and
|
||||
result =
|
||||
strictconcat(string element, Node node1 |
|
||||
readStep(node1, content, node2) and
|
||||
element = nodeId(node1, _, _)
|
||||
|
|
||||
element, ", "
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,119 +1,44 @@
|
||||
private import cpp
|
||||
// The `ValueNumbering` library has to be imported right after `cpp` to ensure
|
||||
// that the cached IR gets the same checksum here as it does in queries that use
|
||||
// `ValueNumbering` without `DataFlow`.
|
||||
private import semmle.code.cpp.ir.ValueNumbering
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
|
||||
private import SsaInternals as Ssa
|
||||
private import PrintIRUtilities
|
||||
|
||||
/**
|
||||
* Gets the local dataflow from other nodes in the same function to this node.
|
||||
*/
|
||||
private string getFromFlow(DataFlow::Node useNode, int order1, int order2) {
|
||||
exists(DataFlow::Node defNode, string prefix |
|
||||
(
|
||||
simpleLocalFlowStep(defNode, useNode) and prefix = ""
|
||||
or
|
||||
any(DataFlow::Configuration cfg).isAdditionalFlowStep(defNode, useNode) and
|
||||
defNode.getEnclosingCallable() = useNode.getEnclosingCallable() and
|
||||
prefix = "+"
|
||||
) and
|
||||
if defNode.asInstruction() = useNode.asOperand().getAnyDef()
|
||||
then
|
||||
// Shorthand for flow from the def of this operand.
|
||||
result = prefix + "def" and
|
||||
order1 = -1 and
|
||||
order2 = 0
|
||||
else
|
||||
if defNode.asOperand().getUse() = useNode.asInstruction()
|
||||
then
|
||||
// Shorthand for flow from an operand of this instruction
|
||||
result = prefix + defNode.asOperand().getDumpId() and
|
||||
order1 = -1 and
|
||||
order2 = defNode.asOperand().getDumpSortOrder()
|
||||
else result = prefix + nodeId(defNode, order1, order2)
|
||||
private string getFromFlow(Node node2, int order1, int order2) {
|
||||
exists(Node node1 |
|
||||
simpleLocalFlowStep(node1, node2) and
|
||||
result = nodeId(node1, order1, order2)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the local dataflow from this node to other nodes in the same function.
|
||||
*/
|
||||
private string getToFlow(DataFlow::Node defNode, int order1, int order2) {
|
||||
exists(DataFlow::Node useNode, string prefix |
|
||||
(
|
||||
simpleLocalFlowStep(defNode, useNode) and prefix = ""
|
||||
or
|
||||
any(DataFlow::Configuration cfg).isAdditionalFlowStep(defNode, useNode) and
|
||||
defNode.getEnclosingCallable() = useNode.getEnclosingCallable() and
|
||||
prefix = "+"
|
||||
) and
|
||||
if useNode.asInstruction() = defNode.asOperand().getUse()
|
||||
then
|
||||
// Shorthand for flow to this operand's instruction.
|
||||
result = prefix + "result" and
|
||||
order1 = -1 and
|
||||
order2 = 0
|
||||
else result = prefix + nodeId(useNode, order1, order2)
|
||||
private string getToFlow(Node node1, int order1, int order2) {
|
||||
exists(Node node2 |
|
||||
simpleLocalFlowStep(node1, node2) and
|
||||
result = nodeId(node2, order1, order2)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the properties of the dataflow node `node`.
|
||||
*/
|
||||
private string getNodeProperty(DataFlow::Node node, string key) {
|
||||
private string getNodeProperty(Node node, string key) {
|
||||
// List dataflow into and out of this node. Flow into this node is printed as `src->@`, and flow
|
||||
// out of this node is printed as `@->dest`.
|
||||
key = "flow" and
|
||||
result =
|
||||
strictconcat(string flow, boolean to, int order1, int order2 |
|
||||
flow = getFromFlow(node, order1, order2) + "->@" and to = false
|
||||
flow = getFromFlow(node, order1, order2) + "->" + starsForNode(node) + "@" and to = false
|
||||
or
|
||||
flow = "@->" + getToFlow(node, order1, order2) and to = true
|
||||
flow = starsForNode(node) + "@->" + getToFlow(node, order1, order2) and to = true
|
||||
|
|
||||
flow, ", " order by to, order1, order2, flow
|
||||
)
|
||||
or
|
||||
// Is this node a dataflow sink?
|
||||
key = "sink" and
|
||||
any(DataFlow::Configuration cfg).isSink(node) and
|
||||
result = "true"
|
||||
or
|
||||
// Is this node a dataflow source?
|
||||
key = "source" and
|
||||
any(DataFlow::Configuration cfg).isSource(node) and
|
||||
result = "true"
|
||||
or
|
||||
// Is this node a dataflow barrier, and if so, what kind?
|
||||
key = "barrier" and
|
||||
result =
|
||||
strictconcat(string kind |
|
||||
any(DataFlow::Configuration cfg).isBarrier(node) and kind = "full"
|
||||
or
|
||||
any(DataFlow::Configuration cfg).isBarrierIn(node) and kind = "in"
|
||||
or
|
||||
any(DataFlow::Configuration cfg).isBarrierOut(node) and kind = "out"
|
||||
|
|
||||
kind, ", "
|
||||
)
|
||||
// or
|
||||
// // Is there partial flow from a source to this node?
|
||||
// // This property will only be emitted if partial flow is enabled by overriding
|
||||
// // `DataFlow::Configuration::explorationLimit()`.
|
||||
// key = "pflow" and
|
||||
// result =
|
||||
// strictconcat(DataFlow::PartialPathNode sourceNode, DataFlow::PartialPathNode destNode, int dist,
|
||||
// int order1, int order2 |
|
||||
// any(DataFlow::Configuration cfg).hasPartialFlow(sourceNode, destNode, dist) and
|
||||
// destNode.getNode() = node and
|
||||
// // Only print flow from a source in the same function.
|
||||
// sourceNode.getNode().getEnclosingCallable() = node.getEnclosingCallable()
|
||||
// |
|
||||
// nodeId(sourceNode.getNode(), order1, order2) + "+" + dist.toString(), ", "
|
||||
// order by
|
||||
// order1, order2, dist desc
|
||||
// )
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,16 +46,21 @@ private string getNodeProperty(DataFlow::Node node, string key) {
|
||||
*/
|
||||
class LocalFlowPropertyProvider extends IRPropertyProvider {
|
||||
override string getOperandProperty(Operand operand, string key) {
|
||||
exists(DataFlow::Node node |
|
||||
operand = node.asOperand() and
|
||||
exists(Node node |
|
||||
operand = [node.asOperand(), node.(RawIndirectOperand).getOperand()] and
|
||||
result = getNodeProperty(node, key)
|
||||
)
|
||||
}
|
||||
|
||||
override string getInstructionProperty(Instruction instruction, string key) {
|
||||
exists(DataFlow::Node node |
|
||||
instruction = node.asInstruction() and
|
||||
exists(Node node |
|
||||
instruction = [node.asInstruction(), node.(RawIndirectInstruction).getInstruction()]
|
||||
|
|
||||
result = getNodeProperty(node, key)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate shouldPrintOperand(Operand operand) { not Ssa::ignoreOperand(operand) }
|
||||
|
||||
override predicate shouldPrintInstruction(Instruction instr) { not Ssa::ignoreInstruction(instr) }
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
/**
|
||||
* Print the dataflow local store steps in IR dumps.
|
||||
*/
|
||||
|
||||
private import cpp
|
||||
// The `ValueNumbering` library has to be imported right after `cpp` to ensure
|
||||
// that the cached IR gets the same checksum here as it does in queries that use
|
||||
// `ValueNumbering` without `DataFlow`.
|
||||
private import semmle.code.cpp.ir.ValueNumbering
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
|
||||
private import PrintIRUtilities
|
||||
|
||||
/**
|
||||
* Property provider for local IR dataflow store steps.
|
||||
*/
|
||||
class LocalFlowPropertyProvider extends IRPropertyProvider {
|
||||
override string getInstructionProperty(Instruction instruction, string key) {
|
||||
exists(DataFlow::Node objectNode, Content content |
|
||||
key = "content[" + content.toString() + "]" and
|
||||
instruction = objectNode.asInstruction() and
|
||||
result =
|
||||
strictconcat(string element, DataFlow::Node fieldNode |
|
||||
storeStep(fieldNode, content, objectNode) and
|
||||
element = nodeId(fieldNode, _, _)
|
||||
|
|
||||
element, ", "
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -3,37 +3,59 @@
|
||||
*/
|
||||
|
||||
private import cpp
|
||||
// The `ValueNumbering` library has to be imported right after `cpp` to ensure
|
||||
// that the cached IR gets the same checksum here as it does in queries that use
|
||||
// `ValueNumbering` without `DataFlow`.
|
||||
private import semmle.code.cpp.ir.ValueNumbering
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
|
||||
|
||||
private string stars(int k) {
|
||||
k =
|
||||
[0 .. max([
|
||||
any(RawIndirectInstruction n).getIndirectionIndex(),
|
||||
any(RawIndirectOperand n).getIndirectionIndex()
|
||||
]
|
||||
)] and
|
||||
(if k = 0 then result = "" else result = "*" + stars(k - 1))
|
||||
}
|
||||
|
||||
string starsForNode(Node node) {
|
||||
result = stars(node.(IndirectInstruction).getIndirectionIndex())
|
||||
or
|
||||
result = stars(node.(IndirectOperand).getIndirectionIndex())
|
||||
or
|
||||
not node instanceof IndirectInstruction and
|
||||
not node instanceof IndirectOperand and
|
||||
result = ""
|
||||
}
|
||||
|
||||
private Instruction getInstruction(Node n, string stars) {
|
||||
result = [n.asInstruction(), n.(RawIndirectInstruction).getInstruction()] and
|
||||
stars = starsForNode(n)
|
||||
}
|
||||
|
||||
private Operand getOperand(Node n, string stars) {
|
||||
result = [n.asOperand(), n.(RawIndirectOperand).getOperand()] and
|
||||
stars = starsForNode(n)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a short ID for an IR dataflow node.
|
||||
* - For `Instruction`s, this is just the result ID of the instruction (e.g. `m128`).
|
||||
* - For `Operand`s, this is the label of the operand, prefixed with the result ID of the
|
||||
* instruction and a dot (e.g. `m128.left`).
|
||||
* - For `Variable`s, this is the qualified name of the variable.
|
||||
*/
|
||||
string nodeId(DataFlow::Node node, int order1, int order2) {
|
||||
exists(Instruction instruction | instruction = node.asInstruction() |
|
||||
result = instruction.getResultId() and
|
||||
string nodeId(Node node, int order1, int order2) {
|
||||
exists(Instruction instruction, string stars | instruction = getInstruction(node, stars) |
|
||||
result = stars + instruction.getResultId() and
|
||||
order1 = instruction.getBlock().getDisplayIndex() and
|
||||
order2 = instruction.getDisplayIndexInBlock()
|
||||
)
|
||||
or
|
||||
exists(Operand operand, Instruction instruction |
|
||||
operand = node.asOperand() and
|
||||
exists(Operand operand, Instruction instruction, string stars |
|
||||
operand = getOperand(node, stars) and
|
||||
instruction = operand.getUse()
|
||||
|
|
||||
result = instruction.getResultId() + "." + operand.getDumpId() and
|
||||
result = stars + instruction.getResultId() + "." + operand.getDumpId() and
|
||||
order1 = instruction.getBlock().getDisplayIndex() and
|
||||
order2 = instruction.getDisplayIndexInBlock()
|
||||
)
|
||||
or
|
||||
result = "var(" + node.asVariable().getQualifiedName() + ")" and
|
||||
order1 = 1000000 and
|
||||
order2 = 0
|
||||
}
|
||||
|
||||
@@ -1,7 +1,29 @@
|
||||
import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
/**
|
||||
* Provides a library for global (inter-procedural) data flow analysis of two
|
||||
* values "simultaneously". This can be used, for example, if you want to track
|
||||
* a memory allocation as well as the size of the allocation.
|
||||
*
|
||||
* Intuitively, you can think of this as regular dataflow, but where each node
|
||||
* in the dataflow graph has been replaced by a pair of nodes `(node1, node2)`,
|
||||
* and two node pairs `(n11, n12)`, `(n21, n22)` is then connected by a dataflow
|
||||
* edge if there's a regular dataflow edge between `n11` and `n21`, and `n12`
|
||||
* and `n22`.
|
||||
*
|
||||
* Note that the above intuition does not reflect the actual implementation.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
private import DataFlowPrivate
|
||||
private import DataFlowUtil
|
||||
private import DataFlowImplCommon
|
||||
private import codeql.util.Unit
|
||||
|
||||
/**
|
||||
* Provides classes for performing global (inter-procedural) data flow analyses
|
||||
* on a product dataflow graph.
|
||||
*/
|
||||
module ProductFlow {
|
||||
/** An input configuration for product data-flow. */
|
||||
signature module ConfigSig {
|
||||
/**
|
||||
* Holds if `(source1, source2)` is a relevant data flow source.
|
||||
@@ -67,6 +89,9 @@ module ProductFlow {
|
||||
default predicate isBarrierIn2(DataFlow::Node node) { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The output of a global data flow computation.
|
||||
*/
|
||||
module Global<ConfigSig Config> {
|
||||
private module StateConfig implements StateConfigSig {
|
||||
class FlowState1 = Unit;
|
||||
@@ -135,6 +160,7 @@ module ProductFlow {
|
||||
import GlobalWithState<StateConfig>
|
||||
}
|
||||
|
||||
/** An input configuration for data flow using flow state. */
|
||||
signature module StateConfigSig {
|
||||
bindingset[this]
|
||||
class FlowState1;
|
||||
@@ -244,6 +270,9 @@ module ProductFlow {
|
||||
default predicate isBarrierIn2(DataFlow::Node node) { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The output of a global data flow computation.
|
||||
*/
|
||||
module GlobalWithState<StateConfigSig Config> {
|
||||
class PathNode1 = Flow1::PathNode;
|
||||
|
||||
@@ -257,6 +286,7 @@ module ProductFlow {
|
||||
|
||||
class FlowState2 = Config::FlowState2;
|
||||
|
||||
/** Holds if data can flow from `(source1, source2)` to `(sink1, sink2)`. */
|
||||
predicate flowPath(
|
||||
Flow1::PathNode source1, Flow2::PathNode source2, Flow1::PathNode sink1, Flow2::PathNode sink2
|
||||
) {
|
||||
@@ -287,9 +317,9 @@ module ProductFlow {
|
||||
predicate isBarrierIn(DataFlow::Node node) { Config::isBarrierIn1(node) }
|
||||
}
|
||||
|
||||
module Flow1 = DataFlow::GlobalWithState<Config1>;
|
||||
private module Flow1 = DataFlow::GlobalWithState<Config1>;
|
||||
|
||||
module Config2 implements DataFlow::StateConfigSig {
|
||||
private module Config2 implements DataFlow::StateConfigSig {
|
||||
class FlowState = FlowState2;
|
||||
|
||||
predicate isSource(DataFlow::Node source, FlowState state) {
|
||||
@@ -319,27 +349,90 @@ module ProductFlow {
|
||||
predicate isBarrierIn(DataFlow::Node node) { Config::isBarrierIn2(node) }
|
||||
}
|
||||
|
||||
module Flow2 = DataFlow::GlobalWithState<Config2>;
|
||||
private module Flow2 = DataFlow::GlobalWithState<Config2>;
|
||||
|
||||
private predicate isSourcePair(Flow1::PathNode node1, Flow2::PathNode node2) {
|
||||
Config::isSourcePair(node1.getNode(), node1.getState(), node2.getNode(), node2.getState())
|
||||
}
|
||||
|
||||
private predicate isSinkPair(Flow1::PathNode node1, Flow2::PathNode node2) {
|
||||
Config::isSinkPair(node1.getNode(), node1.getState(), node2.getNode(), node2.getState())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate fwdReachableInterprocEntry(Flow1::PathNode node1, Flow2::PathNode node2) {
|
||||
isSourcePair(node1, node2)
|
||||
or
|
||||
fwdIsSuccessor(_, _, node1, node2)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate reachableInterprocEntry(
|
||||
Flow1::PathNode source1, Flow2::PathNode source2, Flow1::PathNode node1, Flow2::PathNode node2
|
||||
private predicate fwdIsSuccessorExit(
|
||||
Flow1::PathNode mid1, Flow2::PathNode mid2, Flow1::PathNode succ1, Flow2::PathNode succ2
|
||||
) {
|
||||
Config::isSourcePair(node1.getNode(), node1.getState(), node2.getNode(), node2.getState()) and
|
||||
node1 = source1 and
|
||||
node2 = source2
|
||||
isSinkPair(mid1, mid2) and
|
||||
succ1 = mid1 and
|
||||
succ2 = mid2
|
||||
or
|
||||
exists(
|
||||
Flow1::PathNode midEntry1, Flow2::PathNode midEntry2, Flow1::PathNode midExit1,
|
||||
Flow2::PathNode midExit2
|
||||
|
|
||||
reachableInterprocEntry(source1, source2, midEntry1, midEntry2) and
|
||||
interprocEdgePair(midExit1, midExit2, node1, node2) and
|
||||
localPathStep1*(midEntry1, midExit1) and
|
||||
localPathStep2*(midEntry2, midExit2)
|
||||
interprocEdgePair(mid1, mid2, succ1, succ2)
|
||||
}
|
||||
|
||||
private predicate fwdIsSuccessor1(
|
||||
Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode mid1, Flow2::PathNode mid2,
|
||||
Flow1::PathNode succ1, Flow2::PathNode succ2
|
||||
) {
|
||||
fwdReachableInterprocEntry(pred1, pred2) and
|
||||
localPathStep1*(pred1, mid1) and
|
||||
fwdIsSuccessorExit(pragma[only_bind_into](mid1), pragma[only_bind_into](mid2), succ1, succ2)
|
||||
}
|
||||
|
||||
private predicate fwdIsSuccessor2(
|
||||
Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode mid1, Flow2::PathNode mid2,
|
||||
Flow1::PathNode succ1, Flow2::PathNode succ2
|
||||
) {
|
||||
fwdReachableInterprocEntry(pred1, pred2) and
|
||||
localPathStep2*(pred2, mid2) and
|
||||
fwdIsSuccessorExit(pragma[only_bind_into](mid1), pragma[only_bind_into](mid2), succ1, succ2)
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
private predicate fwdIsSuccessor(
|
||||
Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode succ1, Flow2::PathNode succ2
|
||||
) {
|
||||
exists(Flow1::PathNode mid1, Flow2::PathNode mid2 |
|
||||
fwdIsSuccessor1(pred1, pred2, mid1, mid2, succ1, succ2) and
|
||||
fwdIsSuccessor2(pred1, pred2, mid1, mid2, succ1, succ2)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate revReachableInterprocEntry(Flow1::PathNode node1, Flow2::PathNode node2) {
|
||||
fwdReachableInterprocEntry(node1, node2) and
|
||||
isSinkPair(node1, node2)
|
||||
or
|
||||
exists(Flow1::PathNode succ1, Flow2::PathNode succ2 |
|
||||
revReachableInterprocEntry(succ1, succ2) and
|
||||
fwdIsSuccessor(node1, node2, succ1, succ2)
|
||||
)
|
||||
}
|
||||
|
||||
private newtype TNodePair =
|
||||
TMkNodePair(Flow1::PathNode node1, Flow2::PathNode node2) {
|
||||
revReachableInterprocEntry(node1, node2)
|
||||
}
|
||||
|
||||
private predicate pathSucc(TNodePair n1, TNodePair n2) {
|
||||
exists(Flow1::PathNode n11, Flow2::PathNode n12, Flow1::PathNode n21, Flow2::PathNode n22 |
|
||||
n1 = TMkNodePair(n11, n12) and
|
||||
n2 = TMkNodePair(n21, n22) and
|
||||
fwdIsSuccessor(n11, n12, n21, n22)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate pathSuccPlus(TNodePair n1, TNodePair n2) = fastTC(pathSucc/2)(n1, n2)
|
||||
|
||||
private predicate localPathStep1(Flow1::PathNode pred, Flow1::PathNode succ) {
|
||||
Flow1::PathGraph::edges(pred, succ) and
|
||||
pragma[only_bind_out](pred.getNode().getEnclosingCallable()) =
|
||||
@@ -352,43 +445,133 @@ module ProductFlow {
|
||||
pragma[only_bind_out](succ.getNode().getEnclosingCallable())
|
||||
}
|
||||
|
||||
private newtype TKind =
|
||||
TInto(DataFlowCall call) {
|
||||
intoImpl1(_, _, call) or
|
||||
intoImpl2(_, _, call)
|
||||
} or
|
||||
TOutOf(DataFlowCall call) {
|
||||
outImpl1(_, _, call) or
|
||||
outImpl2(_, _, call)
|
||||
} or
|
||||
TJump()
|
||||
|
||||
private predicate intoImpl1(Flow1::PathNode pred1, Flow1::PathNode succ1, DataFlowCall call) {
|
||||
Flow1::PathGraph::edges(pred1, succ1) and
|
||||
pred1.getNode().(ArgumentNode).getCall() = call and
|
||||
succ1.getNode() instanceof ParameterNode
|
||||
}
|
||||
|
||||
private predicate into1(Flow1::PathNode pred1, Flow1::PathNode succ1, TKind kind) {
|
||||
exists(DataFlowCall call |
|
||||
kind = TInto(call) and
|
||||
intoImpl1(pred1, succ1, call)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate outImpl1(Flow1::PathNode pred1, Flow1::PathNode succ1, DataFlowCall call) {
|
||||
Flow1::PathGraph::edges(pred1, succ1) and
|
||||
exists(ReturnKindExt returnKind |
|
||||
succ1.getNode() = returnKind.getAnOutNode(call) and
|
||||
pred1.getNode().(ReturnNodeExt).getKind() = returnKind
|
||||
)
|
||||
}
|
||||
|
||||
private predicate out1(Flow1::PathNode pred1, Flow1::PathNode succ1, TKind kind) {
|
||||
exists(DataFlowCall call |
|
||||
outImpl1(pred1, succ1, call) and
|
||||
kind = TOutOf(call)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate intoImpl2(Flow2::PathNode pred2, Flow2::PathNode succ2, DataFlowCall call) {
|
||||
Flow2::PathGraph::edges(pred2, succ2) and
|
||||
pred2.getNode().(ArgumentNode).getCall() = call and
|
||||
succ2.getNode() instanceof ParameterNode
|
||||
}
|
||||
|
||||
private predicate into2(Flow2::PathNode pred2, Flow2::PathNode succ2, TKind kind) {
|
||||
exists(DataFlowCall call |
|
||||
kind = TInto(call) and
|
||||
intoImpl2(pred2, succ2, call)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate outImpl2(Flow2::PathNode pred2, Flow2::PathNode succ2, DataFlowCall call) {
|
||||
Flow2::PathGraph::edges(pred2, succ2) and
|
||||
exists(ReturnKindExt returnKind |
|
||||
succ2.getNode() = returnKind.getAnOutNode(call) and
|
||||
pred2.getNode().(ReturnNodeExt).getKind() = returnKind
|
||||
)
|
||||
}
|
||||
|
||||
private predicate out2(Flow2::PathNode pred2, Flow2::PathNode succ2, TKind kind) {
|
||||
exists(DataFlowCall call |
|
||||
kind = TOutOf(call) and
|
||||
outImpl2(pred2, succ2, call)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate interprocEdge1(
|
||||
Declaration predDecl, Declaration succDecl, Flow1::PathNode pred1, Flow1::PathNode succ1
|
||||
Declaration predDecl, Declaration succDecl, Flow1::PathNode pred1, Flow1::PathNode succ1,
|
||||
TKind kind
|
||||
) {
|
||||
Flow1::PathGraph::edges(pred1, succ1) and
|
||||
predDecl != succDecl and
|
||||
pred1.getNode().getEnclosingCallable() = predDecl and
|
||||
succ1.getNode().getEnclosingCallable() = succDecl
|
||||
succ1.getNode().getEnclosingCallable() = succDecl and
|
||||
(
|
||||
into1(pred1, succ1, kind)
|
||||
or
|
||||
out1(pred1, succ1, kind)
|
||||
or
|
||||
kind = TJump() and
|
||||
not into1(pred1, succ1, _) and
|
||||
not out1(pred1, succ1, _)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate interprocEdge2(
|
||||
Declaration predDecl, Declaration succDecl, Flow2::PathNode pred2, Flow2::PathNode succ2
|
||||
Declaration predDecl, Declaration succDecl, Flow2::PathNode pred2, Flow2::PathNode succ2,
|
||||
TKind kind
|
||||
) {
|
||||
Flow2::PathGraph::edges(pred2, succ2) and
|
||||
predDecl != succDecl and
|
||||
pred2.getNode().getEnclosingCallable() = predDecl and
|
||||
succ2.getNode().getEnclosingCallable() = succDecl
|
||||
succ2.getNode().getEnclosingCallable() = succDecl and
|
||||
(
|
||||
into2(pred2, succ2, kind)
|
||||
or
|
||||
out2(pred2, succ2, kind)
|
||||
or
|
||||
kind = TJump() and
|
||||
not into2(pred2, succ2, _) and
|
||||
not out2(pred2, succ2, _)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate interprocEdgePair(
|
||||
Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode succ1, Flow2::PathNode succ2
|
||||
) {
|
||||
exists(Declaration predDecl, Declaration succDecl |
|
||||
interprocEdge1(predDecl, succDecl, pred1, succ1) and
|
||||
interprocEdge2(predDecl, succDecl, pred2, succ2)
|
||||
exists(Declaration predDecl, Declaration succDecl, TKind kind |
|
||||
interprocEdge1(predDecl, succDecl, pred1, succ1, kind) and
|
||||
interprocEdge2(predDecl, succDecl, pred2, succ2, kind)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate reachable(
|
||||
Flow1::PathNode source1, Flow2::PathNode source2, Flow1::PathNode sink1, Flow2::PathNode sink2
|
||||
) {
|
||||
exists(Flow1::PathNode mid1, Flow2::PathNode mid2 |
|
||||
reachableInterprocEntry(source1, source2, mid1, mid2) and
|
||||
Config::isSinkPair(sink1.getNode(), sink1.getState(), sink2.getNode(), sink2.getState()) and
|
||||
localPathStep1*(mid1, sink1) and
|
||||
localPathStep2*(mid2, sink2)
|
||||
isSourcePair(source1, source2) and
|
||||
isSinkPair(sink1, sink2) and
|
||||
exists(TNodePair n1, TNodePair n2 |
|
||||
n1 = TMkNodePair(source1, source2) and
|
||||
n2 = TMkNodePair(sink1, sink2)
|
||||
|
|
||||
pathSuccPlus(n1, n2) or
|
||||
n1 = n2
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -145,14 +145,14 @@ private newtype TDefOrUseImpl =
|
||||
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 Cpp::GlobalOrNamespaceVariable
|
||||
base.(VariableAddressInstruction).getAstVariable() instanceof GlobalLikeVariable
|
||||
)
|
||||
} or
|
||||
TUseImpl(Operand operand, int indirectionIndex) {
|
||||
isUse(_, operand, _, _, indirectionIndex) and
|
||||
not isDef(_, _, operand, _, _, _)
|
||||
} or
|
||||
TGlobalUse(Cpp::GlobalOrNamespaceVariable v, IRFunction f, int indirectionIndex) {
|
||||
TGlobalUse(GlobalLikeVariable v, IRFunction f, int indirectionIndex) {
|
||||
// Represents a final "use" of a global variable to ensure that
|
||||
// the assignment to a global variable isn't ruled out as dead.
|
||||
exists(VariableAddressInstruction vai, int defIndex |
|
||||
@@ -162,7 +162,7 @@ private newtype TDefOrUseImpl =
|
||||
indirectionIndex = [0 .. defIndex] + 1
|
||||
)
|
||||
} or
|
||||
TGlobalDefImpl(Cpp::GlobalOrNamespaceVariable v, IRFunction f, int indirectionIndex) {
|
||||
TGlobalDefImpl(GlobalLikeVariable v, IRFunction f, int indirectionIndex) {
|
||||
// Represents the initial "definition" of a global variable when entering
|
||||
// a function body.
|
||||
exists(VariableAddressInstruction vai |
|
||||
@@ -458,7 +458,7 @@ class FinalParameterUse extends UseImpl, TFinalParameterUse {
|
||||
}
|
||||
|
||||
class GlobalUse extends UseImpl, TGlobalUse {
|
||||
Cpp::GlobalOrNamespaceVariable global;
|
||||
GlobalLikeVariable global;
|
||||
IRFunction f;
|
||||
|
||||
GlobalUse() { this = TGlobalUse(global, f, ind) }
|
||||
@@ -468,7 +468,7 @@ class GlobalUse extends UseImpl, TGlobalUse {
|
||||
override int getIndirection() { result = ind + 1 }
|
||||
|
||||
/** Gets the global variable associated with this use. */
|
||||
Cpp::GlobalOrNamespaceVariable getVariable() { result = global }
|
||||
GlobalLikeVariable getVariable() { result = global }
|
||||
|
||||
/** Gets the `IRFunction` whose body is exited from after this use. */
|
||||
IRFunction getIRFunction() { result = f }
|
||||
@@ -496,14 +496,14 @@ class GlobalUse extends UseImpl, TGlobalUse {
|
||||
}
|
||||
|
||||
class GlobalDefImpl extends DefOrUseImpl, TGlobalDefImpl {
|
||||
Cpp::GlobalOrNamespaceVariable global;
|
||||
GlobalLikeVariable global;
|
||||
IRFunction f;
|
||||
int indirectionIndex;
|
||||
|
||||
GlobalDefImpl() { this = TGlobalDefImpl(global, f, indirectionIndex) }
|
||||
|
||||
/** Gets the global variable associated with this definition. */
|
||||
Cpp::GlobalOrNamespaceVariable getVariable() { result = global }
|
||||
GlobalLikeVariable getVariable() { result = global }
|
||||
|
||||
/** Gets the `IRFunction` whose body is evaluated after this definition. */
|
||||
IRFunction getIRFunction() { result = f }
|
||||
@@ -657,27 +657,20 @@ private predicate indirectConversionFlowStep(Node nFrom, Node nTo) {
|
||||
* So this predicate recurses back along conversions and `PointerArithmeticInstruction`s to find the
|
||||
* first use that has provides use-use flow, and uses that target as the target of the `nodeFrom`.
|
||||
*/
|
||||
private predicate adjustForPointerArith(
|
||||
DefOrUse defOrUse, Node nodeFrom, UseOrPhi use, boolean uncertain
|
||||
) {
|
||||
nodeFrom = any(PostUpdateNode pun).getPreUpdateNode() and
|
||||
exists(Node adjusted |
|
||||
indirectConversionFlowStep*(adjusted, nodeFrom) and
|
||||
nodeToDefOrUse(adjusted, defOrUse, uncertain) and
|
||||
private predicate adjustForPointerArith(PostUpdateNode pun, UseOrPhi use) {
|
||||
exists(DefOrUse defOrUse, Node adjusted |
|
||||
indirectConversionFlowStep*(adjusted, pun.getPreUpdateNode()) and
|
||||
nodeToDefOrUse(adjusted, defOrUse, _) and
|
||||
adjacentDefRead(defOrUse, use)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate ssaFlowImpl(SsaDefOrUse defOrUse, Node nodeFrom, Node nodeTo, boolean uncertain) {
|
||||
// `nodeFrom = any(PostUpdateNode pun).getPreUpdateNode()` is implied by adjustedForPointerArith.
|
||||
exists(UseOrPhi use |
|
||||
adjustForPointerArith(defOrUse, nodeFrom, use, uncertain) and
|
||||
useToNode(use, nodeTo)
|
||||
or
|
||||
not nodeFrom = any(PostUpdateNode pun).getPreUpdateNode() and
|
||||
nodeToDefOrUse(nodeFrom, defOrUse, uncertain) and
|
||||
adjacentDefRead(defOrUse, use) and
|
||||
useToNode(use, nodeTo)
|
||||
useToNode(use, nodeTo) and
|
||||
nodeFrom != nodeTo
|
||||
or
|
||||
// Initial global variable value to a first use
|
||||
nodeFrom.(InitialGlobalValue).getGlobalDef() = defOrUse and
|
||||
@@ -712,11 +705,28 @@ private Node getAPriorDefinition(SsaDefOrUse defOrUse) {
|
||||
/** Holds if there is def-use or use-use flow from `nodeFrom` to `nodeTo`. */
|
||||
predicate ssaFlow(Node nodeFrom, Node nodeTo) {
|
||||
exists(Node nFrom, boolean uncertain, SsaDefOrUse defOrUse |
|
||||
ssaFlowImpl(defOrUse, nFrom, nodeTo, uncertain) and
|
||||
ssaFlowImpl(defOrUse, nFrom, nodeTo, uncertain) and nodeFrom != nodeTo
|
||||
|
|
||||
if uncertain = true then nodeFrom = [nFrom, getAPriorDefinition(defOrUse)] else nodeFrom = nFrom
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isArgumentOfCallable(DataFlowCall call, ArgumentNode arg) {
|
||||
arg.argumentOf(call, _)
|
||||
}
|
||||
|
||||
/** Holds if there is def-use or use-use flow from `pun` to `nodeTo`. */
|
||||
predicate postUpdateFlow(PostUpdateNode pun, Node nodeTo) {
|
||||
exists(UseOrPhi use, Node preUpdate |
|
||||
adjustForPointerArith(pun, use) and
|
||||
useToNode(use, nodeTo) and
|
||||
preUpdate = pun.getPreUpdateNode() and
|
||||
not exists(DataFlowCall call |
|
||||
isArgumentOfCallable(call, preUpdate) and isArgumentOfCallable(call, nodeTo)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `use` is a use of `sv` and is a next adjacent use of `phi` in
|
||||
* index `i1` in basic block `bb1`.
|
||||
@@ -742,6 +752,7 @@ predicate fromPhiNode(SsaPhiNode nodeFrom, Node nodeTo) {
|
||||
fromPhiNodeToUse(phi, sv, bb1, i1, use)
|
||||
or
|
||||
exists(PhiNode phiTo |
|
||||
phi != phiTo and
|
||||
lastRefRedefExt(phi, _, _, phiTo) and
|
||||
nodeTo.(SsaPhiNode).getPhiNode() = phiTo
|
||||
)
|
||||
@@ -760,13 +771,14 @@ private predicate variableWriteCand(IRBlock bb, int i, SourceVariable v) {
|
||||
}
|
||||
|
||||
private predicate sourceVariableIsGlobal(
|
||||
SourceVariable sv, Cpp::GlobalOrNamespaceVariable global, IRFunction func, int indirectionIndex
|
||||
SourceVariable sv, GlobalLikeVariable global, IRFunction func, int indirectionIndex
|
||||
) {
|
||||
exists(IRVariable irVar, BaseIRVariable base |
|
||||
sourceVariableHasBaseAndIndex(sv, base, indirectionIndex) and
|
||||
irVar = base.getIRVariable() and
|
||||
irVar.getEnclosingIRFunction() = func and
|
||||
global = irVar.getAst()
|
||||
global = irVar.getAst() and
|
||||
not irVar instanceof IRDynamicInitializationFlag
|
||||
)
|
||||
}
|
||||
|
||||
@@ -919,7 +931,7 @@ class GlobalDef extends TGlobalDef, SsaDefOrUse {
|
||||
IRFunction getIRFunction() { result = global.getIRFunction() }
|
||||
|
||||
/** Gets the global variable associated with this definition. */
|
||||
Cpp::GlobalOrNamespaceVariable getVariable() { result = global.getVariable() }
|
||||
GlobalLikeVariable getVariable() { result = global.getVariable() }
|
||||
}
|
||||
|
||||
class Phi extends TPhi, SsaDefOrUse {
|
||||
@@ -997,6 +1009,14 @@ class PhiNode extends SsaImpl::DefinitionExt {
|
||||
this instanceof SsaImpl::PhiNode or
|
||||
this instanceof SsaImpl::PhiReadNode
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this phi node is a phi-read node.
|
||||
*
|
||||
* Phi-read nodes are like normal phi nodes, but they are inserted based
|
||||
* on reads instead of writes.
|
||||
*/
|
||||
predicate isPhiRead() { this instanceof SsaImpl::PhiReadNode }
|
||||
}
|
||||
|
||||
class DefinitionExt = SsaImpl::DefinitionExt;
|
||||
|
||||
@@ -39,7 +39,7 @@ class IRType extends TIRType {
|
||||
* Gets a string that uniquely identifies this `IRType`. This string is often the same as the
|
||||
* result of `IRType.toString()`, but for some types it may be more verbose to ensure uniqueness.
|
||||
*/
|
||||
string getIdentityString() { result = toString() }
|
||||
string getIdentityString() { result = this.toString() }
|
||||
|
||||
/**
|
||||
* Gets the size of the type, in bytes, if known.
|
||||
@@ -206,7 +206,7 @@ class IRFloatingPointType extends IRNumericType, TIRFloatingPointType {
|
||||
IRFloatingPointType() { this = TIRFloatingPointType(_, base, domain) }
|
||||
|
||||
final override string toString() {
|
||||
result = getDomainPrefix() + getBaseString() + byteSize.toString()
|
||||
result = this.getDomainPrefix() + this.getBaseString() + byteSize.toString()
|
||||
}
|
||||
|
||||
final override Language::LanguageType getCanonicalLanguageType() {
|
||||
|
||||
@@ -135,11 +135,11 @@ class Opcode extends TOpcode {
|
||||
* Holds if the instruction must have an operand with the specified `OperandTag`.
|
||||
*/
|
||||
final predicate hasOperand(OperandTag tag) {
|
||||
hasOperandInternal(tag)
|
||||
this.hasOperandInternal(tag)
|
||||
or
|
||||
hasAddressOperand() and tag instanceof AddressOperandTag
|
||||
this.hasAddressOperand() and tag instanceof AddressOperandTag
|
||||
or
|
||||
hasBufferSizeOperand() and tag instanceof BufferSizeOperandTag
|
||||
this.hasBufferSizeOperand() and tag instanceof BufferSizeOperandTag
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -77,4 +77,16 @@ class IRPropertyProvider extends TIRPropertyProvider {
|
||||
* Gets the value of the property named `key` for the specified operand.
|
||||
*/
|
||||
string getOperandProperty(Operand operand, string key) { none() }
|
||||
|
||||
/**
|
||||
* Holds if the instruction `instr` should be included when printing
|
||||
* the IR instructions.
|
||||
*/
|
||||
predicate shouldPrintInstruction(Instruction instr) { any() }
|
||||
|
||||
/**
|
||||
* Holds if the operand `operand` should be included when printing the an
|
||||
* instruction's operand list.
|
||||
*/
|
||||
predicate shouldPrintOperand(Operand operand) { any() }
|
||||
}
|
||||
|
||||
@@ -45,7 +45,9 @@ class IRFunction extends IRFunctionBase {
|
||||
* Gets the block containing the entry point of this function.
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock getEntryBlock() { result.getFirstInstruction() = getEnterFunctionInstruction() }
|
||||
final IRBlock getEntryBlock() {
|
||||
result.getFirstInstruction() = this.getEnterFunctionInstruction()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all instructions in this function.
|
||||
|
||||
@@ -39,12 +39,12 @@ class IRVariable extends TIRVariable {
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
*/
|
||||
final Language::Type getType() { getLanguageType().hasType(result, false) }
|
||||
final Language::Type getType() { this.getLanguageType().hasType(result, false) }
|
||||
|
||||
/**
|
||||
* Gets the language-neutral type of the variable.
|
||||
*/
|
||||
final IRType getIRType() { result = getLanguageType().getIRType() }
|
||||
final IRType getIRType() { result = this.getLanguageType().getIRType() }
|
||||
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
@@ -58,7 +58,7 @@ class IRVariable extends TIRVariable {
|
||||
Language::AST getAst() { none() }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated Language::AST getAST() { result = getAst() }
|
||||
deprecated Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
/**
|
||||
* Gets an identifier string for the variable. This identifier is unique
|
||||
@@ -69,7 +69,7 @@ class IRVariable extends TIRVariable {
|
||||
/**
|
||||
* Gets the source location of this variable.
|
||||
*/
|
||||
final Language::Location getLocation() { result = getAst().getLocation() }
|
||||
final Language::Location getLocation() { result = this.getAst().getLocation() }
|
||||
|
||||
/**
|
||||
* Gets the IR for the function that references this variable.
|
||||
@@ -91,15 +91,15 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
|
||||
|
||||
IRUserVariable() { this = TIRUserVariable(var, type, func) }
|
||||
|
||||
final override string toString() { result = getVariable().toString() }
|
||||
final override string toString() { result = this.getVariable().toString() }
|
||||
|
||||
final override Language::AST getAst() { result = var }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = getAst() }
|
||||
deprecated override Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = getVariable().toString() + " " + getVariable().getLocation().toString()
|
||||
result = this.getVariable().toString() + " " + this.getVariable().getLocation().toString()
|
||||
}
|
||||
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
@@ -166,9 +166,9 @@ class IRGeneratedVariable extends IRVariable {
|
||||
final override Language::AST getAst() { result = ast }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = getAst() }
|
||||
deprecated override Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
override string toString() { result = getBaseString() + getLocationString() }
|
||||
override string toString() { result = this.getBaseString() + this.getLocationString() }
|
||||
|
||||
override string getUniqueId() { none() }
|
||||
|
||||
@@ -272,7 +272,7 @@ class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
|
||||
final override predicate isReadOnly() { any() }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal)
|
||||
result = "String: " + this.getLocationString() + "=" + Language::getStringLiteralText(literal)
|
||||
}
|
||||
|
||||
final override string getBaseString() { result = "#string" }
|
||||
@@ -303,7 +303,8 @@ class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitial
|
||||
final Language::Variable getVariable() { result = var }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = "Init: " + getVariable().toString() + " " + getVariable().getLocation().toString()
|
||||
result =
|
||||
"Init: " + this.getVariable().toString() + " " + this.getVariable().getLocation().toString()
|
||||
}
|
||||
|
||||
final override string getBaseString() { result = "#init:" + var.toString() + ":" }
|
||||
@@ -332,5 +333,5 @@ class IRParameter extends IRAutomaticVariable {
|
||||
* An IR variable representing a positional parameter.
|
||||
*/
|
||||
class IRPositionalParameter extends IRParameter, IRAutomaticUserVariable {
|
||||
final override int getIndex() { result = getVariable().(Language::Parameter).getIndex() }
|
||||
final override int getIndex() { result = this.getVariable().(Language::Parameter).getIndex() }
|
||||
}
|
||||
|
||||
@@ -42,6 +42,14 @@ private predicate shouldPrintFunction(Language::Declaration decl) {
|
||||
exists(PrintIRConfiguration config | config.shouldPrintFunction(decl))
|
||||
}
|
||||
|
||||
private predicate shouldPrintInstruction(Instruction i) {
|
||||
exists(IRPropertyProvider provider | provider.shouldPrintInstruction(i))
|
||||
}
|
||||
|
||||
private predicate shouldPrintOperand(Operand operand) {
|
||||
exists(IRPropertyProvider provider | provider.shouldPrintOperand(operand))
|
||||
}
|
||||
|
||||
private string getAdditionalInstructionProperty(Instruction instr, string key) {
|
||||
exists(IRPropertyProvider provider | result = provider.getInstructionProperty(instr, key))
|
||||
}
|
||||
@@ -84,7 +92,9 @@ private string getOperandPropertyString(Operand operand) {
|
||||
private newtype TPrintableIRNode =
|
||||
TPrintableIRFunction(IRFunction irFunc) { shouldPrintFunction(irFunc.getFunction()) } or
|
||||
TPrintableIRBlock(IRBlock block) { shouldPrintFunction(block.getEnclosingFunction()) } or
|
||||
TPrintableInstruction(Instruction instr) { shouldPrintFunction(instr.getEnclosingFunction()) }
|
||||
TPrintableInstruction(Instruction instr) {
|
||||
shouldPrintInstruction(instr) and shouldPrintFunction(instr.getEnclosingFunction())
|
||||
}
|
||||
|
||||
/**
|
||||
* A node to be emitted in the IR graph.
|
||||
@@ -127,13 +137,13 @@ abstract private class PrintableIRNode extends TPrintableIRNode {
|
||||
* Gets the value of the node property with the specified key.
|
||||
*/
|
||||
string getProperty(string key) {
|
||||
key = "semmle.label" and result = getLabel()
|
||||
key = "semmle.label" and result = this.getLabel()
|
||||
or
|
||||
key = "semmle.order" and result = getOrder().toString()
|
||||
key = "semmle.order" and result = this.getOrder().toString()
|
||||
or
|
||||
key = "semmle.graphKind" and result = getGraphKind()
|
||||
key = "semmle.graphKind" and result = this.getGraphKind()
|
||||
or
|
||||
key = "semmle.forceText" and forceText() and result = "true"
|
||||
key = "semmle.forceText" and this.forceText() and result = "true"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +188,7 @@ private class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
|
||||
|
||||
PrintableIRBlock() { this = TPrintableIRBlock(block) }
|
||||
|
||||
override string toString() { result = getLabel() }
|
||||
override string toString() { result = this.getLabel() }
|
||||
|
||||
override Language::Location getLocation() { result = block.getLocation() }
|
||||
|
||||
@@ -223,7 +233,7 @@ private class PrintableInstruction extends PrintableIRNode, TPrintableInstructio
|
||||
|
|
||||
resultString = instr.getResultString() and
|
||||
operationString = instr.getOperationString() and
|
||||
operandsString = getOperandsString() and
|
||||
operandsString = this.getOperandsString() and
|
||||
columnWidths(block, resultWidth, operationWidth) and
|
||||
result =
|
||||
resultString + getPaddingString(resultWidth - resultString.length()) + " = " +
|
||||
@@ -252,7 +262,8 @@ private class PrintableInstruction extends PrintableIRNode, TPrintableInstructio
|
||||
private string getOperandsString() {
|
||||
result =
|
||||
concat(Operand operand |
|
||||
operand = instr.getAnOperand()
|
||||
operand = instr.getAnOperand() and
|
||||
shouldPrintOperand(operand)
|
||||
|
|
||||
operand.getDumpString() + getOperandPropertyString(operand), ", "
|
||||
order by
|
||||
|
||||
@@ -7,17 +7,19 @@ private import internal.ValueNumberingImports
|
||||
class ValueNumber extends TValueNumber {
|
||||
final string toString() { result = "GVN" }
|
||||
|
||||
final string getDebugString() { result = strictconcat(getAnInstruction().getResultId(), ", ") }
|
||||
final string getDebugString() {
|
||||
result = strictconcat(this.getAnInstruction().getResultId(), ", ")
|
||||
}
|
||||
|
||||
final Language::Location getLocation() {
|
||||
if
|
||||
exists(Instruction i |
|
||||
i = getAnInstruction() and not i.getLocation() instanceof Language::UnknownLocation
|
||||
i = this.getAnInstruction() and not i.getLocation() instanceof Language::UnknownLocation
|
||||
)
|
||||
then
|
||||
result =
|
||||
min(Language::Location l |
|
||||
l = getAnInstruction().getLocation() and not l instanceof Language::UnknownLocation
|
||||
l = this.getAnInstruction().getLocation() and not l instanceof Language::UnknownLocation
|
||||
|
|
||||
l
|
||||
order by
|
||||
@@ -40,7 +42,7 @@ class ValueNumber extends TValueNumber {
|
||||
final Instruction getExampleInstruction() {
|
||||
result =
|
||||
min(Instruction instr |
|
||||
instr = getAnInstruction()
|
||||
instr = this.getAnInstruction()
|
||||
|
|
||||
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
|
||||
)
|
||||
|
||||
@@ -22,7 +22,7 @@ private newtype TAllocation =
|
||||
abstract class Allocation extends TAllocation {
|
||||
abstract string toString();
|
||||
|
||||
final string getAllocationString() { result = toString() }
|
||||
final string getAllocationString() { result = this.toString() }
|
||||
|
||||
abstract Instruction getABaseInstruction();
|
||||
|
||||
|
||||
@@ -95,7 +95,9 @@ private newtype TMemoryLocation =
|
||||
*/
|
||||
abstract class MemoryLocation extends TMemoryLocation {
|
||||
final string toString() {
|
||||
if isMayAccess() then result = "?" + toStringInternal() else result = toStringInternal()
|
||||
if this.isMayAccess()
|
||||
then result = "?" + this.toStringInternal()
|
||||
else result = this.toStringInternal()
|
||||
}
|
||||
|
||||
abstract string toStringInternal();
|
||||
@@ -110,7 +112,7 @@ abstract class MemoryLocation extends TMemoryLocation {
|
||||
|
||||
abstract Location getLocation();
|
||||
|
||||
final IRType getIRType() { result = getType().getIRType() }
|
||||
final IRType getIRType() { result = this.getType().getIRType() }
|
||||
|
||||
abstract predicate isMayAccess();
|
||||
|
||||
@@ -136,7 +138,7 @@ abstract class MemoryLocation extends TMemoryLocation {
|
||||
final predicate canReuseSsa() { none() }
|
||||
|
||||
/** DEPRECATED: Alias for canReuseSsa */
|
||||
deprecated predicate canReuseSSA() { canReuseSsa() }
|
||||
deprecated predicate canReuseSSA() { this.canReuseSsa() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -191,19 +193,19 @@ class VariableMemoryLocation extends TVariableMemoryLocation, AllocationMemoryLo
|
||||
}
|
||||
|
||||
private string getIntervalString() {
|
||||
if coversEntireVariable()
|
||||
if this.coversEntireVariable()
|
||||
then result = ""
|
||||
else result = Interval::getIntervalString(startBitOffset, endBitOffset)
|
||||
}
|
||||
|
||||
private string getTypeString() {
|
||||
if coversEntireVariable() and type = var.getIRType()
|
||||
if this.coversEntireVariable() and type = var.getIRType()
|
||||
then result = ""
|
||||
else result = "<" + languageType.toString() + ">"
|
||||
}
|
||||
|
||||
final override string toStringInternal() {
|
||||
result = var.toString() + getIntervalString() + getTypeString()
|
||||
result = var.toString() + this.getIntervalString() + this.getTypeString()
|
||||
}
|
||||
|
||||
final override Language::LanguageType getType() {
|
||||
@@ -236,7 +238,7 @@ class VariableMemoryLocation extends TVariableMemoryLocation, AllocationMemoryLo
|
||||
/**
|
||||
* Holds if this memory location covers the entire variable.
|
||||
*/
|
||||
final predicate coversEntireVariable() { varIRTypeHasBitRange(startBitOffset, endBitOffset) }
|
||||
final predicate coversEntireVariable() { this.varIRTypeHasBitRange(startBitOffset, endBitOffset) }
|
||||
|
||||
pragma[noinline]
|
||||
private predicate varIRTypeHasBitRange(int start, int end) {
|
||||
@@ -262,7 +264,7 @@ class EntireAllocationMemoryLocation extends TEntireAllocationMemoryLocation,
|
||||
class EntireAllocationVirtualVariable extends EntireAllocationMemoryLocation, VirtualVariable {
|
||||
EntireAllocationVirtualVariable() {
|
||||
not allocationEscapes(var) and
|
||||
not isMayAccess()
|
||||
not this.isMayAccess()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,8 +277,8 @@ class VariableVirtualVariable extends VariableMemoryLocation, VirtualVariable {
|
||||
VariableVirtualVariable() {
|
||||
not allocationEscapes(var) and
|
||||
type = var.getIRType() and
|
||||
coversEntireVariable() and
|
||||
not isMayAccess()
|
||||
this.coversEntireVariable() and
|
||||
not this.isMayAccess()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,7 +339,7 @@ class AllNonLocalMemory extends TAllNonLocalMemory, MemoryLocation {
|
||||
// instruction, which provides the initial definition for all memory outside of the current
|
||||
// function's stack frame. This memory includes string literals and other read-only globals, so
|
||||
// we allow such an access to be the definition for a use of a read-only location.
|
||||
not isMayAccess()
|
||||
not this.isMayAccess()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,7 +362,7 @@ class AllAliasedMemory extends TAllAliasedMemory, MemoryLocation {
|
||||
|
||||
final override Location getLocation() { result = irFunc.getLocation() }
|
||||
|
||||
final override string getUniqueId() { result = " " + toString() }
|
||||
final override string getUniqueId() { result = " " + this.toString() }
|
||||
|
||||
final override VirtualVariable getVirtualVariable() { result = TAllAliasedMemory(irFunc, false) }
|
||||
|
||||
@@ -369,7 +371,7 @@ class AllAliasedMemory extends TAllAliasedMemory, MemoryLocation {
|
||||
|
||||
/** A virtual variable that groups all escaped memory within a function. */
|
||||
class AliasedVirtualVariable extends AllAliasedMemory, VirtualVariable {
|
||||
AliasedVirtualVariable() { not isMayAccess() }
|
||||
AliasedVirtualVariable() { not this.isMayAccess() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -34,9 +34,13 @@ private module Cached {
|
||||
|
||||
cached
|
||||
predicate hasUnreachedInstructionCached(IRFunction irFunc) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
exists(OldIR::Instruction oldInstruction |
|
||||
irFunc = oldInstruction.getEnclosingIRFunction() and
|
||||
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _)
|
||||
(
|
||||
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _)
|
||||
or
|
||||
oldInstruction.getOpcode() instanceof Opcode::Unreached
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -366,21 +370,19 @@ private module Cached {
|
||||
then
|
||||
result = getChi(getOldInstruction(instruction)) and
|
||||
kind instanceof GotoEdge
|
||||
else (
|
||||
else
|
||||
exists(OldInstruction oldInstruction |
|
||||
oldInstruction = getOldInstruction(instruction) and
|
||||
(
|
||||
oldInstruction = getOldInstruction(instruction)
|
||||
or
|
||||
instruction = getChi(oldInstruction)
|
||||
) and
|
||||
(
|
||||
if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind)
|
||||
then result = unreachedInstruction(instruction.getEnclosingIRFunction())
|
||||
else result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(OldInstruction oldInstruction |
|
||||
instruction = getChi(oldInstruction) and
|
||||
result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
|
||||
@@ -40,7 +40,9 @@ abstract class OperandTag extends TOperandTag {
|
||||
/**
|
||||
* Gets a label that will appear before the operand when the IR is printed.
|
||||
*/
|
||||
final string getLabel() { if alwaysPrintLabel() then result = getId() + ":" else result = "" }
|
||||
final string getLabel() {
|
||||
if this.alwaysPrintLabel() then result = this.getId() + ":" else result = ""
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an identifier that uniquely identifies this operand within its instruction.
|
||||
|
||||
@@ -19,6 +19,9 @@ newtype TInstruction =
|
||||
) {
|
||||
IRConstruction::Raw::hasInstruction(tag1, tag2)
|
||||
} or
|
||||
TRawUnreachedInstruction(IRFunctionBase irFunc) {
|
||||
IRConstruction::hasUnreachedInstruction(irFunc)
|
||||
} or
|
||||
TUnaliasedSsaPhiInstruction(
|
||||
TRawInstruction blockStartInstr, UnaliasedSsa::Ssa::MemoryLocation memoryLocation
|
||||
) {
|
||||
|
||||
@@ -77,4 +77,16 @@ class IRPropertyProvider extends TIRPropertyProvider {
|
||||
* Gets the value of the property named `key` for the specified operand.
|
||||
*/
|
||||
string getOperandProperty(Operand operand, string key) { none() }
|
||||
|
||||
/**
|
||||
* Holds if the instruction `instr` should be included when printing
|
||||
* the IR instructions.
|
||||
*/
|
||||
predicate shouldPrintInstruction(Instruction instr) { any() }
|
||||
|
||||
/**
|
||||
* Holds if the operand `operand` should be included when printing the an
|
||||
* instruction's operand list.
|
||||
*/
|
||||
predicate shouldPrintOperand(Operand operand) { any() }
|
||||
}
|
||||
|
||||
@@ -45,7 +45,9 @@ class IRFunction extends IRFunctionBase {
|
||||
* Gets the block containing the entry point of this function.
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock getEntryBlock() { result.getFirstInstruction() = getEnterFunctionInstruction() }
|
||||
final IRBlock getEntryBlock() {
|
||||
result.getFirstInstruction() = this.getEnterFunctionInstruction()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all instructions in this function.
|
||||
|
||||
@@ -39,12 +39,12 @@ class IRVariable extends TIRVariable {
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
*/
|
||||
final Language::Type getType() { getLanguageType().hasType(result, false) }
|
||||
final Language::Type getType() { this.getLanguageType().hasType(result, false) }
|
||||
|
||||
/**
|
||||
* Gets the language-neutral type of the variable.
|
||||
*/
|
||||
final IRType getIRType() { result = getLanguageType().getIRType() }
|
||||
final IRType getIRType() { result = this.getLanguageType().getIRType() }
|
||||
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
@@ -58,7 +58,7 @@ class IRVariable extends TIRVariable {
|
||||
Language::AST getAst() { none() }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated Language::AST getAST() { result = getAst() }
|
||||
deprecated Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
/**
|
||||
* Gets an identifier string for the variable. This identifier is unique
|
||||
@@ -69,7 +69,7 @@ class IRVariable extends TIRVariable {
|
||||
/**
|
||||
* Gets the source location of this variable.
|
||||
*/
|
||||
final Language::Location getLocation() { result = getAst().getLocation() }
|
||||
final Language::Location getLocation() { result = this.getAst().getLocation() }
|
||||
|
||||
/**
|
||||
* Gets the IR for the function that references this variable.
|
||||
@@ -91,15 +91,15 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
|
||||
|
||||
IRUserVariable() { this = TIRUserVariable(var, type, func) }
|
||||
|
||||
final override string toString() { result = getVariable().toString() }
|
||||
final override string toString() { result = this.getVariable().toString() }
|
||||
|
||||
final override Language::AST getAst() { result = var }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = getAst() }
|
||||
deprecated override Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = getVariable().toString() + " " + getVariable().getLocation().toString()
|
||||
result = this.getVariable().toString() + " " + this.getVariable().getLocation().toString()
|
||||
}
|
||||
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
@@ -166,9 +166,9 @@ class IRGeneratedVariable extends IRVariable {
|
||||
final override Language::AST getAst() { result = ast }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = getAst() }
|
||||
deprecated override Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
override string toString() { result = getBaseString() + getLocationString() }
|
||||
override string toString() { result = this.getBaseString() + this.getLocationString() }
|
||||
|
||||
override string getUniqueId() { none() }
|
||||
|
||||
@@ -272,7 +272,7 @@ class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
|
||||
final override predicate isReadOnly() { any() }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal)
|
||||
result = "String: " + this.getLocationString() + "=" + Language::getStringLiteralText(literal)
|
||||
}
|
||||
|
||||
final override string getBaseString() { result = "#string" }
|
||||
@@ -303,7 +303,8 @@ class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitial
|
||||
final Language::Variable getVariable() { result = var }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = "Init: " + getVariable().toString() + " " + getVariable().getLocation().toString()
|
||||
result =
|
||||
"Init: " + this.getVariable().toString() + " " + this.getVariable().getLocation().toString()
|
||||
}
|
||||
|
||||
final override string getBaseString() { result = "#init:" + var.toString() + ":" }
|
||||
@@ -332,5 +333,5 @@ class IRParameter extends IRAutomaticVariable {
|
||||
* An IR variable representing a positional parameter.
|
||||
*/
|
||||
class IRPositionalParameter extends IRParameter, IRAutomaticUserVariable {
|
||||
final override int getIndex() { result = getVariable().(Language::Parameter).getIndex() }
|
||||
final override int getIndex() { result = this.getVariable().(Language::Parameter).getIndex() }
|
||||
}
|
||||
|
||||
@@ -42,6 +42,14 @@ private predicate shouldPrintFunction(Language::Declaration decl) {
|
||||
exists(PrintIRConfiguration config | config.shouldPrintFunction(decl))
|
||||
}
|
||||
|
||||
private predicate shouldPrintInstruction(Instruction i) {
|
||||
exists(IRPropertyProvider provider | provider.shouldPrintInstruction(i))
|
||||
}
|
||||
|
||||
private predicate shouldPrintOperand(Operand operand) {
|
||||
exists(IRPropertyProvider provider | provider.shouldPrintOperand(operand))
|
||||
}
|
||||
|
||||
private string getAdditionalInstructionProperty(Instruction instr, string key) {
|
||||
exists(IRPropertyProvider provider | result = provider.getInstructionProperty(instr, key))
|
||||
}
|
||||
@@ -84,7 +92,9 @@ private string getOperandPropertyString(Operand operand) {
|
||||
private newtype TPrintableIRNode =
|
||||
TPrintableIRFunction(IRFunction irFunc) { shouldPrintFunction(irFunc.getFunction()) } or
|
||||
TPrintableIRBlock(IRBlock block) { shouldPrintFunction(block.getEnclosingFunction()) } or
|
||||
TPrintableInstruction(Instruction instr) { shouldPrintFunction(instr.getEnclosingFunction()) }
|
||||
TPrintableInstruction(Instruction instr) {
|
||||
shouldPrintInstruction(instr) and shouldPrintFunction(instr.getEnclosingFunction())
|
||||
}
|
||||
|
||||
/**
|
||||
* A node to be emitted in the IR graph.
|
||||
@@ -127,13 +137,13 @@ abstract private class PrintableIRNode extends TPrintableIRNode {
|
||||
* Gets the value of the node property with the specified key.
|
||||
*/
|
||||
string getProperty(string key) {
|
||||
key = "semmle.label" and result = getLabel()
|
||||
key = "semmle.label" and result = this.getLabel()
|
||||
or
|
||||
key = "semmle.order" and result = getOrder().toString()
|
||||
key = "semmle.order" and result = this.getOrder().toString()
|
||||
or
|
||||
key = "semmle.graphKind" and result = getGraphKind()
|
||||
key = "semmle.graphKind" and result = this.getGraphKind()
|
||||
or
|
||||
key = "semmle.forceText" and forceText() and result = "true"
|
||||
key = "semmle.forceText" and this.forceText() and result = "true"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +188,7 @@ private class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
|
||||
|
||||
PrintableIRBlock() { this = TPrintableIRBlock(block) }
|
||||
|
||||
override string toString() { result = getLabel() }
|
||||
override string toString() { result = this.getLabel() }
|
||||
|
||||
override Language::Location getLocation() { result = block.getLocation() }
|
||||
|
||||
@@ -223,7 +233,7 @@ private class PrintableInstruction extends PrintableIRNode, TPrintableInstructio
|
||||
|
|
||||
resultString = instr.getResultString() and
|
||||
operationString = instr.getOperationString() and
|
||||
operandsString = getOperandsString() and
|
||||
operandsString = this.getOperandsString() and
|
||||
columnWidths(block, resultWidth, operationWidth) and
|
||||
result =
|
||||
resultString + getPaddingString(resultWidth - resultString.length()) + " = " +
|
||||
@@ -252,7 +262,8 @@ private class PrintableInstruction extends PrintableIRNode, TPrintableInstructio
|
||||
private string getOperandsString() {
|
||||
result =
|
||||
concat(Operand operand |
|
||||
operand = instr.getAnOperand()
|
||||
operand = instr.getAnOperand() and
|
||||
shouldPrintOperand(operand)
|
||||
|
|
||||
operand.getDumpString() + getOperandPropertyString(operand), ", "
|
||||
order by
|
||||
|
||||
@@ -7,17 +7,19 @@ private import internal.ValueNumberingImports
|
||||
class ValueNumber extends TValueNumber {
|
||||
final string toString() { result = "GVN" }
|
||||
|
||||
final string getDebugString() { result = strictconcat(getAnInstruction().getResultId(), ", ") }
|
||||
final string getDebugString() {
|
||||
result = strictconcat(this.getAnInstruction().getResultId(), ", ")
|
||||
}
|
||||
|
||||
final Language::Location getLocation() {
|
||||
if
|
||||
exists(Instruction i |
|
||||
i = getAnInstruction() and not i.getLocation() instanceof Language::UnknownLocation
|
||||
i = this.getAnInstruction() and not i.getLocation() instanceof Language::UnknownLocation
|
||||
)
|
||||
then
|
||||
result =
|
||||
min(Language::Location l |
|
||||
l = getAnInstruction().getLocation() and not l instanceof Language::UnknownLocation
|
||||
l = this.getAnInstruction().getLocation() and not l instanceof Language::UnknownLocation
|
||||
|
|
||||
l
|
||||
order by
|
||||
@@ -40,7 +42,7 @@ class ValueNumber extends TValueNumber {
|
||||
final Instruction getExampleInstruction() {
|
||||
result =
|
||||
min(Instruction instr |
|
||||
instr = getAnInstruction()
|
||||
instr = this.getAnInstruction()
|
||||
|
|
||||
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
|
||||
)
|
||||
|
||||
@@ -178,9 +178,9 @@ module Raw {
|
||||
}
|
||||
}
|
||||
|
||||
class TStageInstruction = TRawInstruction;
|
||||
class TStageInstruction = TRawInstruction or TRawUnreachedInstruction;
|
||||
|
||||
predicate hasInstruction(TRawInstruction instr) { any() }
|
||||
predicate hasInstruction(TStageInstruction instr) { any() }
|
||||
|
||||
predicate hasModeledMemoryResult(Instruction instruction) { none() }
|
||||
|
||||
@@ -368,6 +368,11 @@ private predicate isStrictlyForwardGoto(GotoStmt goto) {
|
||||
|
||||
Locatable getInstructionAst(TStageInstruction instr) {
|
||||
result = getInstructionTranslatedElement(instr).getAst()
|
||||
or
|
||||
exists(IRFunction irFunc |
|
||||
instr = TRawUnreachedInstruction(irFunc) and
|
||||
result = irFunc.getFunction()
|
||||
)
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for getInstructionAst */
|
||||
@@ -377,14 +382,22 @@ deprecated Locatable getInstructionAST(TStageInstruction instr) {
|
||||
|
||||
CppType getInstructionResultType(TStageInstruction instr) {
|
||||
getInstructionTranslatedElement(instr).hasInstruction(_, getInstructionTag(instr), result)
|
||||
or
|
||||
instr instanceof TRawUnreachedInstruction and
|
||||
result = getVoidType()
|
||||
}
|
||||
|
||||
predicate getInstructionOpcode(Opcode opcode, TStageInstruction instr) {
|
||||
getInstructionTranslatedElement(instr).hasInstruction(opcode, getInstructionTag(instr), _)
|
||||
or
|
||||
instr instanceof TRawUnreachedInstruction and
|
||||
opcode instanceof Opcode::Unreached
|
||||
}
|
||||
|
||||
IRFunctionBase getInstructionEnclosingIRFunction(TStageInstruction instr) {
|
||||
result.getFunction() = getInstructionTranslatedElement(instr).getFunction()
|
||||
or
|
||||
instr = TRawUnreachedInstruction(result)
|
||||
}
|
||||
|
||||
Instruction getPrimaryInstructionForSideEffect(SideEffectInstruction instruction) {
|
||||
@@ -393,6 +406,16 @@ Instruction getPrimaryInstructionForSideEffect(SideEffectInstruction instruction
|
||||
.getPrimaryInstructionForSideEffect(getInstructionTag(instruction))
|
||||
}
|
||||
|
||||
predicate hasUnreachedInstruction(IRFunction func) {
|
||||
exists(Call c |
|
||||
c.getEnclosingFunction() = func.getFunction() and
|
||||
any(Options opt).exits(c.getTarget())
|
||||
) and
|
||||
not exists(TranslatedUnreachableReturnStmt return |
|
||||
return.getEnclosingFunction().getFunction() = func.getFunction()
|
||||
)
|
||||
}
|
||||
|
||||
import CachedForDebugging
|
||||
|
||||
cached
|
||||
|
||||
@@ -34,6 +34,7 @@ newtype TInstructionTag =
|
||||
CallTargetTag() or
|
||||
CallTag() or
|
||||
CallSideEffectTag() or
|
||||
CallNoReturnTag() or
|
||||
AllocationSizeTag() or
|
||||
AllocationElementSizeTag() or
|
||||
AllocationExtentConvertTag() or
|
||||
|
||||
@@ -8,6 +8,7 @@ private import SideEffects
|
||||
private import TranslatedElement
|
||||
private import TranslatedExpr
|
||||
private import TranslatedFunction
|
||||
private import DefaultOptions as DefaultOptions
|
||||
|
||||
/**
|
||||
* Gets the `CallInstruction` from the `TranslatedCallExpr` for the specified expression.
|
||||
@@ -30,68 +31,74 @@ abstract class TranslatedCall extends TranslatedExpr {
|
||||
// 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
|
||||
// calls.
|
||||
id = -2 and result = getQualifier()
|
||||
id = -2 and result = this.getQualifier()
|
||||
or
|
||||
id = -1 and result = getCallTarget()
|
||||
id = -1 and result = this.getCallTarget()
|
||||
or
|
||||
result = getArgument(id)
|
||||
result = this.getArgument(id)
|
||||
or
|
||||
id = getNumberOfArguments() and result = getSideEffects()
|
||||
id = this.getNumberOfArguments() and result = this.getSideEffects()
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
if exists(getQualifier())
|
||||
then result = getQualifier().getFirstInstruction()
|
||||
else result = getFirstCallTargetInstruction()
|
||||
if exists(this.getQualifier())
|
||||
then result = this.getQualifier().getFirstInstruction()
|
||||
else result = this.getFirstCallTargetInstruction()
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = CallTag() and
|
||||
opcode instanceof Opcode::Call and
|
||||
resultType = getTypeForPRValue(getCallResultType())
|
||||
resultType = getTypeForPRValue(this.getCallResultType())
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getQualifier() and
|
||||
result = getFirstCallTargetInstruction()
|
||||
child = this.getQualifier() and
|
||||
result = this.getFirstCallTargetInstruction()
|
||||
or
|
||||
child = getCallTarget() and
|
||||
result = getFirstArgumentOrCallInstruction()
|
||||
child = this.getCallTarget() and
|
||||
result = this.getFirstArgumentOrCallInstruction()
|
||||
or
|
||||
exists(int argIndex |
|
||||
child = getArgument(argIndex) and
|
||||
if exists(getArgument(argIndex + 1))
|
||||
then result = getArgument(argIndex + 1).getFirstInstruction()
|
||||
else result = getInstruction(CallTag())
|
||||
child = this.getArgument(argIndex) and
|
||||
if exists(this.getArgument(argIndex + 1))
|
||||
then result = this.getArgument(argIndex + 1).getFirstInstruction()
|
||||
else result = this.getInstruction(CallTag())
|
||||
)
|
||||
or
|
||||
child = getSideEffects() and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
child = this.getSideEffects() and
|
||||
if this.isNoReturn()
|
||||
then
|
||||
result =
|
||||
any(UnreachedInstruction instr |
|
||||
this.getEnclosingFunction().getFunction() = instr.getEnclosingFunction()
|
||||
)
|
||||
else result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
tag = CallTag() and
|
||||
result = getSideEffects().getFirstInstruction()
|
||||
result = this.getSideEffects().getFirstInstruction()
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = CallTag() and
|
||||
(
|
||||
operandTag instanceof CallTargetOperandTag and
|
||||
result = getCallTargetResult()
|
||||
result = this.getCallTargetResult()
|
||||
or
|
||||
operandTag instanceof ThisArgumentOperandTag and
|
||||
result = getQualifierResult()
|
||||
result = this.getQualifierResult()
|
||||
or
|
||||
exists(PositionalArgumentOperandTag argTag |
|
||||
argTag = operandTag and
|
||||
result = getArgument(argTag.getArgIndex()).getResult()
|
||||
result = this.getArgument(argTag.getArgIndex()).getResult()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
final override Instruction getResult() { result = getInstruction(CallTag()) }
|
||||
final override Instruction getResult() { result = this.getInstruction(CallTag()) }
|
||||
|
||||
/**
|
||||
* Gets the result type of the call.
|
||||
@@ -101,7 +108,7 @@ abstract class TranslatedCall extends TranslatedExpr {
|
||||
/**
|
||||
* Holds if the call has a `this` argument.
|
||||
*/
|
||||
predicate hasQualifier() { exists(getQualifier()) }
|
||||
predicate hasQualifier() { exists(this.getQualifier()) }
|
||||
|
||||
/**
|
||||
* Gets the `TranslatedExpr` for the indirect target of the call, if any.
|
||||
@@ -114,7 +121,9 @@ abstract class TranslatedCall extends TranslatedExpr {
|
||||
* it can be overridden by a subclass for cases where there is a call target
|
||||
* that is not computed from an expression (e.g. a direct call).
|
||||
*/
|
||||
Instruction getFirstCallTargetInstruction() { result = getCallTarget().getFirstInstruction() }
|
||||
Instruction getFirstCallTargetInstruction() {
|
||||
result = this.getCallTarget().getFirstInstruction()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result value is the target of the call. By
|
||||
@@ -122,7 +131,7 @@ abstract class TranslatedCall extends TranslatedExpr {
|
||||
* overridden by a subclass for cases where there is a call target that is not
|
||||
* computed from an expression (e.g. a direct call).
|
||||
*/
|
||||
Instruction getCallTargetResult() { result = getCallTarget().getResult() }
|
||||
Instruction getCallTargetResult() { result = this.getCallTarget().getResult() }
|
||||
|
||||
/**
|
||||
* Gets the `TranslatedExpr` for the qualifier of the call (i.e. the value
|
||||
@@ -136,7 +145,7 @@ abstract class TranslatedCall extends TranslatedExpr {
|
||||
* overridden by a subclass for cases where there is a `this` argument that is
|
||||
* not computed from a child expression (e.g. a constructor call).
|
||||
*/
|
||||
Instruction getQualifierResult() { result = getQualifier().getResult() }
|
||||
Instruction getQualifierResult() { result = this.getQualifier().getResult() }
|
||||
|
||||
/**
|
||||
* Gets the argument with the specified `index`. Does not include the `this`
|
||||
@@ -151,9 +160,9 @@ abstract class TranslatedCall extends TranslatedExpr {
|
||||
* argument. Otherwise, returns the call instruction.
|
||||
*/
|
||||
final Instruction getFirstArgumentOrCallInstruction() {
|
||||
if hasArguments()
|
||||
then result = getArgument(0).getFirstInstruction()
|
||||
else result = getInstruction(CallTag())
|
||||
if this.hasArguments()
|
||||
then result = this.getArgument(0).getFirstInstruction()
|
||||
else result = this.getInstruction(CallTag())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,6 +170,8 @@ abstract class TranslatedCall extends TranslatedExpr {
|
||||
*/
|
||||
abstract predicate hasArguments();
|
||||
|
||||
predicate isNoReturn() { none() }
|
||||
|
||||
final TranslatedSideEffects getSideEffects() { result.getExpr() = expr }
|
||||
}
|
||||
|
||||
@@ -175,17 +186,17 @@ abstract class TranslatedSideEffects extends TranslatedElement {
|
||||
/** Gets the expression whose side effects are being modeled. */
|
||||
abstract Expr getExpr();
|
||||
|
||||
final override Locatable getAst() { result = getExpr() }
|
||||
final override Locatable getAst() { result = this.getExpr() }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
final override Declaration getFunction() { result = getEnclosingDeclaration(getExpr()) }
|
||||
final override Declaration getFunction() { result = getEnclosingDeclaration(this.getExpr()) }
|
||||
|
||||
final override TranslatedElement getChild(int i) {
|
||||
result =
|
||||
rank[i + 1](TranslatedSideEffect tse, int group, int indexInGroup |
|
||||
tse.getPrimaryExpr() = getExpr() and
|
||||
tse.getPrimaryExpr() = this.getExpr() and
|
||||
tse.sortOrder(group, indexInGroup)
|
||||
|
|
||||
tse order by group, indexInGroup
|
||||
@@ -194,10 +205,10 @@ abstract class TranslatedSideEffects extends TranslatedElement {
|
||||
|
||||
final override Instruction getChildSuccessor(TranslatedElement te) {
|
||||
exists(int i |
|
||||
getChild(i) = te and
|
||||
if exists(getChild(i + 1))
|
||||
then result = getChild(i + 1).getFirstInstruction()
|
||||
else result = getParent().getChildSuccessor(this)
|
||||
this.getChild(i) = te and
|
||||
if exists(this.getChild(i + 1))
|
||||
then result = this.getChild(i + 1).getFirstInstruction()
|
||||
else result = this.getParent().getChildSuccessor(this)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -206,10 +217,10 @@ abstract class TranslatedSideEffects extends TranslatedElement {
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = getChild(0).getFirstInstruction()
|
||||
result = this.getChild(0).getFirstInstruction()
|
||||
or
|
||||
// Some functions, like `std::move()`, have no side effects whatsoever.
|
||||
not exists(getChild(0)) and result = getParent().getChildSuccessor(this)
|
||||
not exists(this.getChild(0)) and result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
@@ -225,10 +236,10 @@ abstract class TranslatedSideEffects extends TranslatedElement {
|
||||
*/
|
||||
abstract class TranslatedDirectCall extends TranslatedCall {
|
||||
final override Instruction getFirstCallTargetInstruction() {
|
||||
result = getInstruction(CallTargetTag())
|
||||
result = this.getInstruction(CallTargetTag())
|
||||
}
|
||||
|
||||
final override Instruction getCallTargetResult() { result = getInstruction(CallTargetTag()) }
|
||||
final override Instruction getCallTargetResult() { result = this.getInstruction(CallTargetTag()) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
TranslatedCall.super.hasInstruction(opcode, tag, resultType)
|
||||
@@ -243,7 +254,7 @@ abstract class TranslatedDirectCall extends TranslatedCall {
|
||||
or
|
||||
tag = CallTargetTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = getFirstArgumentOrCallInstruction()
|
||||
result = this.getFirstArgumentOrCallInstruction()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,6 +277,8 @@ abstract class TranslatedCallExpr extends TranslatedNonConstantExpr, TranslatedC
|
||||
}
|
||||
|
||||
final override int getNumberOfArguments() { result = expr.getNumberOfArguments() }
|
||||
|
||||
final override predicate isNoReturn() { any(Options opt).exits(expr.getTarget()) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -290,12 +303,12 @@ class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall {
|
||||
}
|
||||
|
||||
override Instruction getQualifierResult() {
|
||||
hasQualifier() and
|
||||
result = getQualifier().getResult()
|
||||
this.hasQualifier() and
|
||||
result = this.getQualifier().getResult()
|
||||
}
|
||||
|
||||
override predicate hasQualifier() {
|
||||
exists(getQualifier()) and
|
||||
exists(this.getQualifier()) and
|
||||
not exists(MemberFunction func | expr.getTarget() = func and func.isStatic())
|
||||
}
|
||||
}
|
||||
@@ -311,7 +324,7 @@ class TranslatedStructorCall extends TranslatedFunctionCall {
|
||||
|
||||
override Instruction getQualifierResult() {
|
||||
exists(StructorCallContext context |
|
||||
context = getParent() and
|
||||
context = this.getParent() and
|
||||
result = context.getReceiver()
|
||||
)
|
||||
}
|
||||
@@ -362,24 +375,26 @@ abstract class TranslatedSideEffect extends TranslatedElement {
|
||||
|
||||
final override Instruction getChildSuccessor(TranslatedElement child) { none() }
|
||||
|
||||
final override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
|
||||
tag = OnlyInstructionTag() and
|
||||
sideEffectInstruction(opcode, type)
|
||||
this.sideEffectInstruction(opcode, type)
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
result = getParent().getChildSuccessor(this) and
|
||||
result = this.getParent().getChildSuccessor(this) and
|
||||
tag = OnlyInstructionTag() and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
final override Declaration getFunction() { result = getParent().getFunction() }
|
||||
final override Declaration getFunction() { result = this.getParent().getFunction() }
|
||||
|
||||
final override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = getParent().(TranslatedSideEffects).getPrimaryInstruction()
|
||||
result = this.getParent().(TranslatedSideEffects).getPrimaryInstruction()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -417,18 +432,18 @@ abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect {
|
||||
TranslatedArgumentSideEffect() { any() }
|
||||
|
||||
override string toString() {
|
||||
isWrite() and
|
||||
result = "(write side effect for " + getArgString() + ")"
|
||||
this.isWrite() and
|
||||
result = "(write side effect for " + this.getArgString() + ")"
|
||||
or
|
||||
not isWrite() and
|
||||
result = "(read side effect for " + getArgString() + ")"
|
||||
not this.isWrite() and
|
||||
result = "(read side effect for " + this.getArgString() + ")"
|
||||
}
|
||||
|
||||
override Call getPrimaryExpr() { result = call }
|
||||
|
||||
override predicate sortOrder(int group, int indexInGroup) {
|
||||
indexInGroup = index and
|
||||
if isWrite() then group = argumentWriteGroup() else group = argumentReadGroup()
|
||||
if this.isWrite() then group = argumentWriteGroup() else group = argumentReadGroup()
|
||||
}
|
||||
|
||||
final override int getInstructionIndex(InstructionTag tag) {
|
||||
@@ -439,20 +454,20 @@ abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect {
|
||||
final override predicate sideEffectInstruction(Opcode opcode, CppType type) {
|
||||
opcode = sideEffectOpcode and
|
||||
(
|
||||
isWrite() and
|
||||
this.isWrite() and
|
||||
(
|
||||
opcode instanceof BufferAccessOpcode and
|
||||
type = getUnknownType()
|
||||
or
|
||||
not opcode instanceof BufferAccessOpcode and
|
||||
exists(Type indirectionType | indirectionType = getIndirectionType() |
|
||||
exists(Type indirectionType | indirectionType = this.getIndirectionType() |
|
||||
if indirectionType instanceof VoidType
|
||||
then type = getUnknownType()
|
||||
else type = getTypeForPRValueOrUnknown(indirectionType)
|
||||
)
|
||||
)
|
||||
or
|
||||
not isWrite() and
|
||||
not this.isWrite() and
|
||||
type = getVoidType()
|
||||
)
|
||||
}
|
||||
@@ -460,7 +475,7 @@ abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect {
|
||||
final override CppType getInstructionMemoryOperandType(
|
||||
InstructionTag tag, TypedOperandTag operandTag
|
||||
) {
|
||||
not isWrite() and
|
||||
not this.isWrite() and
|
||||
if sideEffectOpcode instanceof BufferAccessOpcode
|
||||
then
|
||||
result = getUnknownType() and
|
||||
@@ -469,7 +484,7 @@ abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect {
|
||||
else
|
||||
exists(Type operandType |
|
||||
tag instanceof OnlyInstructionTag and
|
||||
operandType = getIndirectionType() and
|
||||
operandType = this.getIndirectionType() and
|
||||
operandTag instanceof SideEffectOperandTag
|
||||
|
|
||||
// If the type we select is an incomplete type (e.g. a forward-declared `struct`), there will
|
||||
@@ -481,7 +496,7 @@ abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect {
|
||||
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag instanceof OnlyInstructionTag and
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getArgInstruction()
|
||||
result = this.getArgInstruction()
|
||||
or
|
||||
tag instanceof OnlyInstructionTag and
|
||||
operandTag instanceof BufferSizeOperandTag and
|
||||
@@ -522,7 +537,7 @@ class TranslatedArgumentExprSideEffect extends TranslatedArgumentSideEffect,
|
||||
final override Locatable getAst() { result = arg }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
final override Type getIndirectionType() {
|
||||
result = arg.getUnspecifiedType().(DerivedType).getBaseType()
|
||||
@@ -557,7 +572,7 @@ class TranslatedStructorQualifierSideEffect extends TranslatedArgumentSideEffect
|
||||
final override Locatable getAst() { result = call }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
final override Type getIndirectionType() { result = call.getTarget().getDeclaringType() }
|
||||
|
||||
@@ -581,7 +596,7 @@ class TranslatedCallSideEffect extends TranslatedSideEffect, TTranslatedCallSide
|
||||
override Locatable getAst() { result = expr }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
override Expr getPrimaryExpr() { result = expr }
|
||||
|
||||
@@ -622,7 +637,7 @@ class TranslatedAllocationSideEffect extends TranslatedSideEffect, TTranslatedAl
|
||||
override Locatable getAst() { result = expr }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
override Expr getPrimaryExpr() { result = expr }
|
||||
|
||||
@@ -635,7 +650,7 @@ class TranslatedAllocationSideEffect extends TranslatedSideEffect, TTranslatedAl
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = OnlyInstructionTag() and
|
||||
operandTag = addressOperand() and
|
||||
result = getPrimaryInstructionForSideEffect(OnlyInstructionTag())
|
||||
result = this.getPrimaryInstructionForSideEffect(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override predicate sideEffectInstruction(Opcode opcode, CppType type) {
|
||||
|
||||
@@ -22,9 +22,9 @@ abstract class TranslatedCondition extends TranslatedElement {
|
||||
final override Locatable getAst() { result = expr }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
final ConditionContext getConditionContext() { result = getParent() }
|
||||
final ConditionContext getConditionContext() { result = this.getParent() }
|
||||
|
||||
final Expr getExpr() { result = expr }
|
||||
|
||||
@@ -42,9 +42,11 @@ abstract class TranslatedFlexibleCondition extends TranslatedCondition, Conditio
|
||||
{
|
||||
TranslatedFlexibleCondition() { this = TTranslatedFlexibleCondition(expr) }
|
||||
|
||||
final override TranslatedElement getChild(int id) { id = 0 and result = getOperand() }
|
||||
final override TranslatedElement getChild(int id) { id = 0 and result = this.getOperand() }
|
||||
|
||||
final override Instruction getFirstInstruction() { result = getOperand().getFirstInstruction() }
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = this.getOperand().getFirstInstruction()
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
@@ -61,13 +63,13 @@ class TranslatedParenthesisCondition extends TranslatedFlexibleCondition {
|
||||
override ParenthesisExpr expr;
|
||||
|
||||
final override Instruction getChildTrueSuccessor(TranslatedCondition child) {
|
||||
child = getOperand() and
|
||||
result = getConditionContext().getChildTrueSuccessor(this)
|
||||
child = this.getOperand() and
|
||||
result = this.getConditionContext().getChildTrueSuccessor(this)
|
||||
}
|
||||
|
||||
final override Instruction getChildFalseSuccessor(TranslatedCondition child) {
|
||||
child = getOperand() and
|
||||
result = getConditionContext().getChildFalseSuccessor(this)
|
||||
child = this.getOperand() and
|
||||
result = this.getConditionContext().getChildFalseSuccessor(this)
|
||||
}
|
||||
|
||||
final override TranslatedCondition getOperand() {
|
||||
@@ -79,13 +81,13 @@ class TranslatedNotCondition extends TranslatedFlexibleCondition {
|
||||
override NotExpr expr;
|
||||
|
||||
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
|
||||
child = getOperand() and
|
||||
result = getConditionContext().getChildFalseSuccessor(this)
|
||||
child = this.getOperand() and
|
||||
result = this.getConditionContext().getChildFalseSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
|
||||
child = getOperand() and
|
||||
result = getConditionContext().getChildTrueSuccessor(this)
|
||||
child = this.getOperand() and
|
||||
result = this.getConditionContext().getChildTrueSuccessor(this)
|
||||
}
|
||||
|
||||
override TranslatedCondition getOperand() {
|
||||
@@ -103,13 +105,13 @@ abstract class TranslatedBinaryLogicalOperation extends TranslatedNativeConditio
|
||||
override BinaryLogicalOperation expr;
|
||||
|
||||
final override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = getLeftOperand()
|
||||
id = 0 and result = this.getLeftOperand()
|
||||
or
|
||||
id = 1 and result = getRightOperand()
|
||||
id = 1 and result = this.getRightOperand()
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = getLeftOperand().getFirstInstruction()
|
||||
result = this.getLeftOperand().getFirstInstruction()
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
@@ -131,16 +133,16 @@ class TranslatedLogicalAndExpr extends TranslatedBinaryLogicalOperation {
|
||||
TranslatedLogicalAndExpr() { expr instanceof LogicalAndExpr }
|
||||
|
||||
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
|
||||
child = getLeftOperand() and
|
||||
result = getRightOperand().getFirstInstruction()
|
||||
child = this.getLeftOperand() and
|
||||
result = this.getRightOperand().getFirstInstruction()
|
||||
or
|
||||
child = getRightOperand() and
|
||||
result = getConditionContext().getChildTrueSuccessor(this)
|
||||
child = this.getRightOperand() and
|
||||
result = this.getConditionContext().getChildTrueSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
|
||||
(child = getLeftOperand() or child = getRightOperand()) and
|
||||
result = getConditionContext().getChildFalseSuccessor(this)
|
||||
(child = this.getLeftOperand() or child = this.getRightOperand()) and
|
||||
result = this.getConditionContext().getChildFalseSuccessor(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,25 +150,25 @@ class TranslatedLogicalOrExpr extends TranslatedBinaryLogicalOperation {
|
||||
override LogicalOrExpr expr;
|
||||
|
||||
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
|
||||
(child = getLeftOperand() or child = getRightOperand()) and
|
||||
result = getConditionContext().getChildTrueSuccessor(this)
|
||||
(child = this.getLeftOperand() or child = this.getRightOperand()) and
|
||||
result = this.getConditionContext().getChildTrueSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
|
||||
child = getLeftOperand() and
|
||||
result = getRightOperand().getFirstInstruction()
|
||||
child = this.getLeftOperand() and
|
||||
result = this.getRightOperand().getFirstInstruction()
|
||||
or
|
||||
child = getRightOperand() and
|
||||
result = getConditionContext().getChildFalseSuccessor(this)
|
||||
child = this.getRightOperand() and
|
||||
result = this.getConditionContext().getChildFalseSuccessor(this)
|
||||
}
|
||||
}
|
||||
|
||||
class TranslatedValueCondition extends TranslatedCondition, TTranslatedValueCondition {
|
||||
TranslatedValueCondition() { this = TTranslatedValueCondition(expr) }
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = getValueExpr() }
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = this.getValueExpr() }
|
||||
|
||||
override Instruction getFirstInstruction() { result = getValueExpr().getFirstInstruction() }
|
||||
override Instruction getFirstInstruction() { result = this.getValueExpr().getFirstInstruction() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = ValueConditionConditionalBranchTag() and
|
||||
@@ -175,25 +177,25 @@ class TranslatedValueCondition extends TranslatedCondition, TTranslatedValueCond
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getValueExpr() and
|
||||
result = getInstruction(ValueConditionConditionalBranchTag())
|
||||
child = this.getValueExpr() and
|
||||
result = this.getInstruction(ValueConditionConditionalBranchTag())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = ValueConditionConditionalBranchTag() and
|
||||
(
|
||||
kind instanceof TrueEdge and
|
||||
result = getConditionContext().getChildTrueSuccessor(this)
|
||||
result = this.getConditionContext().getChildTrueSuccessor(this)
|
||||
or
|
||||
kind instanceof FalseEdge and
|
||||
result = getConditionContext().getChildFalseSuccessor(this)
|
||||
result = this.getConditionContext().getChildFalseSuccessor(this)
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = ValueConditionConditionalBranchTag() and
|
||||
operandTag instanceof ConditionOperandTag and
|
||||
result = getValueExpr().getResult()
|
||||
result = this.getValueExpr().getResult()
|
||||
}
|
||||
|
||||
private TranslatedExpr getValueExpr() { result = getTranslatedExpr(expr) }
|
||||
|
||||
@@ -47,7 +47,7 @@ abstract class TranslatedDeclarationEntry extends TranslatedElement, TTranslated
|
||||
final override Locatable getAst() { result = entry.getAst() }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,19 +60,19 @@ abstract class TranslatedLocalVariableDeclaration extends TranslatedVariableInit
|
||||
*/
|
||||
abstract LocalVariable getVariable();
|
||||
|
||||
final override Type getTargetType() { result = getVariableType(getVariable()) }
|
||||
final override Type getTargetType() { result = getVariableType(this.getVariable()) }
|
||||
|
||||
final override TranslatedInitialization getInitialization() {
|
||||
result =
|
||||
getTranslatedInitialization(getVariable().getInitializer().getExpr().getFullyConverted())
|
||||
getTranslatedInitialization(this.getVariable().getInitializer().getExpr().getFullyConverted())
|
||||
}
|
||||
|
||||
final override Instruction getInitializationSuccessor() {
|
||||
result = getParent().getChildSuccessor(this)
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
final override IRVariable getIRVariable() {
|
||||
result = getIRUserVariable(getFunction(), getVariable())
|
||||
result = getIRUserVariable(this.getFunction(), this.getVariable())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ class TranslatedStaticLocalVariableDeclarationEntry extends TranslatedDeclaratio
|
||||
|
||||
TranslatedStaticLocalVariableDeclarationEntry() { var = entry.getDeclaration() }
|
||||
|
||||
final override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() }
|
||||
final override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() }
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
|
||||
tag = DynamicInitializationFlagAddressTag() and
|
||||
@@ -148,39 +148,39 @@ class TranslatedStaticLocalVariableDeclarationEntry extends TranslatedDeclaratio
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = getInstruction(DynamicInitializationFlagAddressTag())
|
||||
result = this.getInstruction(DynamicInitializationFlagAddressTag())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = DynamicInitializationFlagAddressTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = getInstruction(DynamicInitializationFlagLoadTag())
|
||||
result = this.getInstruction(DynamicInitializationFlagLoadTag())
|
||||
or
|
||||
tag = DynamicInitializationFlagLoadTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = getInstruction(DynamicInitializationConditionalBranchTag())
|
||||
result = this.getInstruction(DynamicInitializationConditionalBranchTag())
|
||||
or
|
||||
tag = DynamicInitializationConditionalBranchTag() and
|
||||
(
|
||||
kind instanceof TrueEdge and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
or
|
||||
kind instanceof FalseEdge and
|
||||
result = getInitialization().getFirstInstruction()
|
||||
result = this.getInitialization().getFirstInstruction()
|
||||
)
|
||||
or
|
||||
tag = DynamicInitializationFlagConstantTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = getInstruction(DynamicInitializationFlagStoreTag())
|
||||
result = this.getInstruction(DynamicInitializationFlagStoreTag())
|
||||
or
|
||||
tag = DynamicInitializationFlagStoreTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
final override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getInitialization() and
|
||||
result = getInstruction(DynamicInitializationFlagConstantTag())
|
||||
child = this.getInitialization() and
|
||||
result = this.getInstruction(DynamicInitializationFlagConstantTag())
|
||||
}
|
||||
|
||||
final override IRDynamicInitializationFlag getInstructionVariable(InstructionTag tag) {
|
||||
@@ -196,20 +196,20 @@ class TranslatedStaticLocalVariableDeclarationEntry extends TranslatedDeclaratio
|
||||
tag = DynamicInitializationFlagLoadTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getInstruction(DynamicInitializationFlagAddressTag())
|
||||
result = this.getInstruction(DynamicInitializationFlagAddressTag())
|
||||
)
|
||||
or
|
||||
tag = DynamicInitializationConditionalBranchTag() and
|
||||
operandTag instanceof ConditionOperandTag and
|
||||
result = getInstruction(DynamicInitializationFlagLoadTag())
|
||||
result = this.getInstruction(DynamicInitializationFlagLoadTag())
|
||||
or
|
||||
tag = DynamicInitializationFlagStoreTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getInstruction(DynamicInitializationFlagAddressTag())
|
||||
result = this.getInstruction(DynamicInitializationFlagAddressTag())
|
||||
or
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
result = getInstruction(DynamicInitializationFlagConstantTag())
|
||||
result = this.getInstruction(DynamicInitializationFlagConstantTag())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -238,7 +238,7 @@ class TranslatedStaticLocalVariableInitialization extends TranslatedElement,
|
||||
final override Locatable getAst() { result = entry.getAst() }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
final override LocalVariable getVariable() { result = var }
|
||||
|
||||
@@ -267,7 +267,7 @@ class TranslatedConditionDecl extends TranslatedLocalVariableDeclaration, TTrans
|
||||
override Locatable getAst() { result = conditionDeclExpr }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
override Declaration getFunction() { result = getEnclosingFunction(conditionDeclExpr) }
|
||||
|
||||
|
||||
@@ -821,7 +821,7 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
abstract Locatable getAst();
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated Locatable getAST() { result = getAst() }
|
||||
deprecated Locatable getAST() { result = this.getAst() }
|
||||
|
||||
/**
|
||||
* Get the first instruction to be executed in the evaluation of this element.
|
||||
@@ -831,7 +831,7 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
/**
|
||||
* Get the immediate child elements of this element.
|
||||
*/
|
||||
final TranslatedElement getAChild() { result = getChild(_) }
|
||||
final TranslatedElement getAChild() { result = this.getChild(_) }
|
||||
|
||||
/**
|
||||
* Gets the immediate child element of this element. The `id` is unique
|
||||
@@ -844,25 +844,29 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
* Gets the an identifier string for the element. This id is unique within
|
||||
* the scope of the element's function.
|
||||
*/
|
||||
final int getId() { result = getUniqueId() }
|
||||
final int getId() { result = this.getUniqueId() }
|
||||
|
||||
private TranslatedElement getChildByRank(int rankIndex) {
|
||||
result =
|
||||
rank[rankIndex + 1](TranslatedElement child, int id | child = getChild(id) | child order by id)
|
||||
rank[rankIndex + 1](TranslatedElement child, int id |
|
||||
child = this.getChild(id)
|
||||
|
|
||||
child order by id
|
||||
)
|
||||
}
|
||||
|
||||
language[monotonicAggregates]
|
||||
private int getDescendantCount() {
|
||||
result =
|
||||
1 + sum(TranslatedElement child | child = getChildByRank(_) | child.getDescendantCount())
|
||||
1 + sum(TranslatedElement child | child = this.getChildByRank(_) | child.getDescendantCount())
|
||||
}
|
||||
|
||||
private int getUniqueId() {
|
||||
if not exists(getParent())
|
||||
if not exists(this.getParent())
|
||||
then result = 0
|
||||
else
|
||||
exists(TranslatedElement parent |
|
||||
parent = getParent() and
|
||||
parent = this.getParent() and
|
||||
if this = parent.getChildByRank(0)
|
||||
then result = 1 + parent.getUniqueId()
|
||||
else
|
||||
@@ -908,7 +912,7 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
* there is no enclosing `try`.
|
||||
*/
|
||||
Instruction getExceptionSuccessorInstruction() {
|
||||
result = getParent().getExceptionSuccessorInstruction()
|
||||
result = this.getParent().getExceptionSuccessorInstruction()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1022,14 +1026,14 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
exists(Locatable ast |
|
||||
result.getAst() = ast and
|
||||
result.getTag() = tag and
|
||||
hasTempVariableAndAst(tag, ast)
|
||||
this.hasTempVariableAndAst(tag, ast)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate hasTempVariableAndAst(TempVariableTag tag, Locatable ast) {
|
||||
hasTempVariable(tag, _) and
|
||||
ast = getAst()
|
||||
this.hasTempVariable(tag, _) and
|
||||
ast = this.getAst()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -68,7 +68,7 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
|
||||
final override Locatable getAst() { result = func }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
/**
|
||||
* Gets the function being translated.
|
||||
@@ -76,15 +76,15 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
|
||||
final override Function getFunction() { result = func }
|
||||
|
||||
final override TranslatedElement getChild(int id) {
|
||||
id = -5 and result = getReadEffects()
|
||||
id = -5 and result = this.getReadEffects()
|
||||
or
|
||||
id = -4 and result = getConstructorInitList()
|
||||
id = -4 and result = this.getConstructorInitList()
|
||||
or
|
||||
id = -3 and result = getBody()
|
||||
id = -3 and result = this.getBody()
|
||||
or
|
||||
id = -2 and result = getDestructorDestructionList()
|
||||
id = -2 and result = this.getDestructorDestructionList()
|
||||
or
|
||||
id >= -1 and result = getParameter(id)
|
||||
id >= -1 and result = this.getParameter(id)
|
||||
}
|
||||
|
||||
final private TranslatedConstructorInitList getConstructorInitList() {
|
||||
@@ -109,64 +109,66 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
|
||||
result = getTranslatedEllipsisParameter(func)
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction() { result = getInstruction(EnterFunctionTag()) }
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = this.getInstruction(EnterFunctionTag())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
tag = EnterFunctionTag() and
|
||||
result = getInstruction(AliasedDefinitionTag())
|
||||
result = this.getInstruction(AliasedDefinitionTag())
|
||||
or
|
||||
tag = AliasedDefinitionTag() and
|
||||
result = getInstruction(InitializeNonLocalTag())
|
||||
result = this.getInstruction(InitializeNonLocalTag())
|
||||
or
|
||||
(
|
||||
tag = InitializeNonLocalTag() and
|
||||
if exists(getThisType())
|
||||
then result = getParameter(-1).getFirstInstruction()
|
||||
if exists(this.getThisType())
|
||||
then result = this.getParameter(-1).getFirstInstruction()
|
||||
else
|
||||
if exists(getParameter(0))
|
||||
then result = getParameter(0).getFirstInstruction()
|
||||
else result = getBody().getFirstInstruction()
|
||||
if exists(this.getParameter(0))
|
||||
then result = this.getParameter(0).getFirstInstruction()
|
||||
else result = this.getBody().getFirstInstruction()
|
||||
)
|
||||
or
|
||||
tag = ReturnValueAddressTag() and
|
||||
result = getInstruction(ReturnTag())
|
||||
result = this.getInstruction(ReturnTag())
|
||||
or
|
||||
tag = ReturnTag() and
|
||||
result = getInstruction(AliasedUseTag())
|
||||
result = this.getInstruction(AliasedUseTag())
|
||||
or
|
||||
tag = UnwindTag() and
|
||||
result = getInstruction(AliasedUseTag())
|
||||
result = this.getInstruction(AliasedUseTag())
|
||||
or
|
||||
tag = AliasedUseTag() and
|
||||
result = getInstruction(ExitFunctionTag())
|
||||
result = this.getInstruction(ExitFunctionTag())
|
||||
)
|
||||
}
|
||||
|
||||
final override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
exists(int paramIndex |
|
||||
child = getParameter(paramIndex) and
|
||||
child = this.getParameter(paramIndex) and
|
||||
if
|
||||
exists(func.getParameter(paramIndex + 1)) or
|
||||
getEllipsisParameterIndexForFunction(func) = paramIndex + 1
|
||||
then result = getParameter(paramIndex + 1).getFirstInstruction()
|
||||
else result = getConstructorInitList().getFirstInstruction()
|
||||
then result = this.getParameter(paramIndex + 1).getFirstInstruction()
|
||||
else result = this.getConstructorInitList().getFirstInstruction()
|
||||
)
|
||||
or
|
||||
child = getConstructorInitList() and
|
||||
result = getBody().getFirstInstruction()
|
||||
child = this.getConstructorInitList() and
|
||||
result = this.getBody().getFirstInstruction()
|
||||
or
|
||||
child = getBody() and
|
||||
result = getReturnSuccessorInstruction()
|
||||
child = this.getBody() and
|
||||
result = this.getReturnSuccessorInstruction()
|
||||
or
|
||||
child = getDestructorDestructionList() and
|
||||
result = getReadEffects().getFirstInstruction()
|
||||
child = this.getDestructorDestructionList() and
|
||||
result = this.getReadEffects().getFirstInstruction()
|
||||
or
|
||||
child = getReadEffects() and
|
||||
if hasReturnValue()
|
||||
then result = getInstruction(ReturnValueAddressTag())
|
||||
else result = getInstruction(ReturnTag())
|
||||
child = this.getReadEffects() and
|
||||
if this.hasReturnValue()
|
||||
then result = this.getInstruction(ReturnValueAddressTag())
|
||||
else result = this.getInstruction(ReturnTag())
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
@@ -185,13 +187,13 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
|
||||
or
|
||||
tag = ReturnValueAddressTag() and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
resultType = getTypeForGLValue(getReturnType()) and
|
||||
hasReturnValue()
|
||||
resultType = getTypeForGLValue(this.getReturnType()) and
|
||||
this.hasReturnValue()
|
||||
or
|
||||
(
|
||||
tag = ReturnTag() and
|
||||
resultType = getVoidType() and
|
||||
if hasReturnValue()
|
||||
if this.hasReturnValue()
|
||||
then opcode instanceof Opcode::ReturnValue
|
||||
else opcode instanceof Opcode::ReturnVoid
|
||||
)
|
||||
@@ -217,23 +219,23 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
|
||||
}
|
||||
|
||||
final override Instruction getExceptionSuccessorInstruction() {
|
||||
result = getInstruction(UnwindTag())
|
||||
result = this.getInstruction(UnwindTag())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = ReturnTag() and
|
||||
hasReturnValue() and
|
||||
this.hasReturnValue() and
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getInstruction(ReturnValueAddressTag())
|
||||
result = this.getInstruction(ReturnValueAddressTag())
|
||||
}
|
||||
|
||||
final override CppType getInstructionMemoryOperandType(
|
||||
InstructionTag tag, TypedOperandTag operandTag
|
||||
) {
|
||||
tag = ReturnTag() and
|
||||
hasReturnValue() and
|
||||
this.hasReturnValue() and
|
||||
operandTag instanceof LoadOperandTag and
|
||||
result = getTypeForPRValue(getReturnType())
|
||||
result = getTypeForPRValue(this.getReturnType())
|
||||
or
|
||||
tag = AliasedUseTag() and
|
||||
operandTag instanceof SideEffectOperandTag and
|
||||
@@ -242,7 +244,7 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
|
||||
|
||||
final override IRVariable getInstructionVariable(InstructionTag tag) {
|
||||
tag = ReturnValueAddressTag() and
|
||||
result = getReturnVariable()
|
||||
result = this.getReturnVariable()
|
||||
}
|
||||
|
||||
final override predicate needsUnknownOpaqueType(int byteSize) {
|
||||
@@ -251,15 +253,15 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
|
||||
|
||||
final override predicate hasTempVariable(TempVariableTag tag, CppType type) {
|
||||
tag = ReturnValueTempVar() and
|
||||
hasReturnValue() and
|
||||
type = getTypeForPRValue(getReturnType())
|
||||
this.hasReturnValue() and
|
||||
type = getTypeForPRValue(this.getReturnType())
|
||||
or
|
||||
tag = EllipsisTempVar() and
|
||||
func.isVarargs() and
|
||||
type = getEllipsisVariablePRValueType()
|
||||
or
|
||||
tag = ThisTempVar() and
|
||||
type = getTypeForGLValue(getThisType())
|
||||
type = getTypeForGLValue(this.getThisType())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -267,7 +269,7 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
|
||||
* statement.
|
||||
*/
|
||||
final Instruction getReturnSuccessorInstruction() {
|
||||
result = getDestructorDestructionList().getFirstInstruction()
|
||||
result = this.getDestructorDestructionList().getFirstInstruction()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -368,25 +370,25 @@ abstract class TranslatedParameter extends TranslatedElement {
|
||||
final override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = getInstruction(InitializerVariableAddressTag())
|
||||
result = this.getInstruction(InitializerVariableAddressTag())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
tag = InitializerVariableAddressTag() and
|
||||
result = getInstruction(InitializerStoreTag())
|
||||
result = this.getInstruction(InitializerStoreTag())
|
||||
or
|
||||
tag = InitializerStoreTag() and
|
||||
if hasIndirection()
|
||||
then result = getInstruction(InitializerIndirectAddressTag())
|
||||
else result = getParent().getChildSuccessor(this)
|
||||
if this.hasIndirection()
|
||||
then result = this.getInstruction(InitializerIndirectAddressTag())
|
||||
else result = this.getParent().getChildSuccessor(this)
|
||||
or
|
||||
tag = InitializerIndirectAddressTag() and
|
||||
result = getInstruction(InitializerIndirectStoreTag())
|
||||
result = this.getInstruction(InitializerIndirectStoreTag())
|
||||
or
|
||||
tag = InitializerIndirectStoreTag() and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -395,21 +397,21 @@ abstract class TranslatedParameter extends TranslatedElement {
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = InitializerVariableAddressTag() and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
resultType = getGLValueType()
|
||||
resultType = this.getGLValueType()
|
||||
or
|
||||
tag = InitializerStoreTag() and
|
||||
opcode instanceof Opcode::InitializeParameter and
|
||||
resultType = getPRValueType()
|
||||
resultType = this.getPRValueType()
|
||||
or
|
||||
hasIndirection() and
|
||||
this.hasIndirection() and
|
||||
tag = InitializerIndirectAddressTag() and
|
||||
opcode instanceof Opcode::Load and
|
||||
resultType = getPRValueType()
|
||||
resultType = this.getPRValueType()
|
||||
or
|
||||
hasIndirection() and
|
||||
this.hasIndirection() and
|
||||
tag = InitializerIndirectStoreTag() and
|
||||
opcode instanceof Opcode::InitializeIndirection and
|
||||
resultType = getInitializationResultType()
|
||||
resultType = this.getInitializationResultType()
|
||||
}
|
||||
|
||||
final override IRVariable getInstructionVariable(InstructionTag tag) {
|
||||
@@ -418,26 +420,26 @@ abstract class TranslatedParameter extends TranslatedElement {
|
||||
tag = InitializerVariableAddressTag() or
|
||||
tag = InitializerIndirectStoreTag()
|
||||
) and
|
||||
result = getIRVariable()
|
||||
result = this.getIRVariable()
|
||||
}
|
||||
|
||||
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = InitializerStoreTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getInstruction(InitializerVariableAddressTag())
|
||||
result = this.getInstruction(InitializerVariableAddressTag())
|
||||
)
|
||||
or
|
||||
// this feels a little strange, but I think it's the best we can do
|
||||
tag = InitializerIndirectAddressTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getInstruction(InitializerVariableAddressTag())
|
||||
result = this.getInstruction(InitializerVariableAddressTag())
|
||||
)
|
||||
or
|
||||
tag = InitializerIndirectStoreTag() and
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getInstruction(InitializerIndirectAddressTag())
|
||||
result = this.getInstruction(InitializerIndirectAddressTag())
|
||||
}
|
||||
|
||||
abstract predicate hasIndirection();
|
||||
@@ -465,7 +467,7 @@ class TranslatedThisParameter extends TranslatedParameter, TTranslatedThisParame
|
||||
final override Locatable getAst() { result = func }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
final override Function getFunction() { result = func }
|
||||
|
||||
@@ -500,7 +502,7 @@ class TranslatedPositionalParameter extends TranslatedParameter, TTranslatedPara
|
||||
final override Locatable getAst() { result = param }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
final override Function getFunction() {
|
||||
result = param.getFunction() or
|
||||
@@ -522,7 +524,7 @@ class TranslatedPositionalParameter extends TranslatedParameter, TTranslatedPara
|
||||
final override CppType getInitializationResultType() { result = getUnknownType() }
|
||||
|
||||
final override IRAutomaticUserVariable getIRVariable() {
|
||||
result = getIRUserVariable(getFunction(), param)
|
||||
result = getIRUserVariable(this.getFunction(), param)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -540,7 +542,7 @@ class TranslatedEllipsisParameter extends TranslatedParameter, TTranslatedEllips
|
||||
final override Locatable getAst() { result = func }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
final override Function getFunction() { result = func }
|
||||
|
||||
@@ -579,7 +581,7 @@ class TranslatedConstructorInitList extends TranslatedElement, InitializationCon
|
||||
override Locatable getAst() { result = func }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
exists(ConstructorFieldInit fieldInit |
|
||||
@@ -599,9 +601,9 @@ class TranslatedConstructorInitList extends TranslatedElement, InitializationCon
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if exists(getChild(0))
|
||||
then result = getChild(0).getFirstInstruction()
|
||||
else result = getParent().getChildSuccessor(this)
|
||||
if exists(this.getChild(0))
|
||||
then result = this.getChild(0).getFirstInstruction()
|
||||
else result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
@@ -614,10 +616,10 @@ class TranslatedConstructorInitList extends TranslatedElement, InitializationCon
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
exists(int id |
|
||||
child = getChild(id) and
|
||||
if exists(getChild(id + 1))
|
||||
then result = getChild(id + 1).getFirstInstruction()
|
||||
else result = getParent().getChildSuccessor(this)
|
||||
child = this.getChild(id) and
|
||||
if exists(this.getChild(id + 1))
|
||||
then result = this.getChild(id + 1).getFirstInstruction()
|
||||
else result = this.getParent().getChildSuccessor(this)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -651,7 +653,7 @@ class TranslatedDestructorDestructionList extends TranslatedElement,
|
||||
override Locatable getAst() { result = func }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
exists(DestructorFieldDestruction fieldDestruction |
|
||||
@@ -666,9 +668,9 @@ class TranslatedDestructorDestructionList extends TranslatedElement,
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if exists(getChild(0))
|
||||
then result = getChild(0).getFirstInstruction()
|
||||
else result = getParent().getChildSuccessor(this)
|
||||
if exists(this.getChild(0))
|
||||
then result = this.getChild(0).getFirstInstruction()
|
||||
else result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
@@ -681,10 +683,10 @@ class TranslatedDestructorDestructionList extends TranslatedElement,
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
exists(int id |
|
||||
child = getChild(id) and
|
||||
if exists(getChild(id + 1))
|
||||
then result = getChild(id + 1).getFirstInstruction()
|
||||
else result = getParent().getChildSuccessor(this)
|
||||
child = this.getChild(id) and
|
||||
if exists(this.getChild(id + 1))
|
||||
then result = this.getChild(id + 1).getFirstInstruction()
|
||||
else result = this.getParent().getChildSuccessor(this)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -699,7 +701,7 @@ class TranslatedReadEffects extends TranslatedElement, TTranslatedReadEffects {
|
||||
override Locatable getAst() { result = func }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
override Function getFunction() { result = func }
|
||||
|
||||
@@ -713,25 +715,25 @@ class TranslatedReadEffects extends TranslatedElement, TTranslatedReadEffects {
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if exists(getAChild())
|
||||
if exists(this.getAChild())
|
||||
then
|
||||
result =
|
||||
min(TranslatedElement child, int id | child = getChild(id) | child order by id)
|
||||
min(TranslatedElement child, int id | child = this.getChild(id) | child order by id)
|
||||
.getFirstInstruction()
|
||||
else result = getParent().getChildSuccessor(this)
|
||||
else result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
exists(int id | child = getChild(id) |
|
||||
if exists(TranslatedReadEffect child2, int id2 | id2 > id and child2 = getChild(id2))
|
||||
exists(int id | child = this.getChild(id) |
|
||||
if exists(TranslatedReadEffect child2, int id2 | id2 > id and child2 = this.getChild(id2))
|
||||
then
|
||||
result =
|
||||
min(TranslatedReadEffect child2, int id2 |
|
||||
child2 = getChild(id2) and id2 > id
|
||||
child2 = this.getChild(id2) and id2 > id
|
||||
|
|
||||
child2 order by id2
|
||||
).getFirstInstruction()
|
||||
else result = getParent().getChildSuccessor(this)
|
||||
else result = this.getParent().getChildSuccessor(this)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -758,10 +760,10 @@ abstract class TranslatedReadEffect extends TranslatedElement {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
kind = EdgeKind::gotoEdge() and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
|
||||
override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
opcode instanceof Opcode::ReturnIndirection and
|
||||
@@ -786,7 +788,7 @@ class TranslatedThisReadEffect extends TranslatedReadEffect, TTranslatedThisRead
|
||||
override Locatable getAst() { result = func }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
override Function getFunction() { result = func }
|
||||
|
||||
@@ -812,7 +814,7 @@ class TranslatedParameterReadEffect extends TranslatedReadEffect, TTranslatedPar
|
||||
override Locatable getAst() { result = param }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
override string toString() { result = "read effect: " + param.toString() }
|
||||
|
||||
@@ -826,6 +828,6 @@ class TranslatedParameterReadEffect extends TranslatedReadEffect, TTranslatedPar
|
||||
|
||||
final override IRVariable getInstructionVariable(InstructionTag tag) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = getIRUserVariable(getFunction(), param)
|
||||
result = getIRUserVariable(this.getFunction(), param)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,64 +35,64 @@ abstract class InitializationContext extends TranslatedElement {
|
||||
* declarations, `return` statements, and `throw` expressions.
|
||||
*/
|
||||
abstract class TranslatedVariableInitialization extends TranslatedElement, InitializationContext {
|
||||
final override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() }
|
||||
final override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() }
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = getInstruction(InitializerVariableAddressTag())
|
||||
result = this.getInstruction(InitializerVariableAddressTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = InitializerVariableAddressTag() and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
resultType = getTypeForGLValue(getTargetType())
|
||||
resultType = getTypeForGLValue(this.getTargetType())
|
||||
or
|
||||
hasUninitializedInstruction() and
|
||||
this.hasUninitializedInstruction() and
|
||||
tag = InitializerStoreTag() and
|
||||
opcode instanceof Opcode::Uninitialized and
|
||||
resultType = getTypeForPRValue(getTargetType())
|
||||
resultType = getTypeForPRValue(this.getTargetType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
(
|
||||
tag = InitializerVariableAddressTag() and
|
||||
kind instanceof GotoEdge and
|
||||
if hasUninitializedInstruction()
|
||||
then result = getInstruction(InitializerStoreTag())
|
||||
else result = getInitialization().getFirstInstruction()
|
||||
if this.hasUninitializedInstruction()
|
||||
then result = this.getInstruction(InitializerStoreTag())
|
||||
else result = this.getInitialization().getFirstInstruction()
|
||||
)
|
||||
or
|
||||
hasUninitializedInstruction() and
|
||||
this.hasUninitializedInstruction() and
|
||||
kind instanceof GotoEdge and
|
||||
tag = InitializerStoreTag() and
|
||||
(
|
||||
result = getInitialization().getFirstInstruction()
|
||||
result = this.getInitialization().getFirstInstruction()
|
||||
or
|
||||
not exists(getInitialization()) and result = getInitializationSuccessor()
|
||||
not exists(this.getInitialization()) and result = this.getInitializationSuccessor()
|
||||
)
|
||||
}
|
||||
|
||||
final override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getInitialization() and result = getInitializationSuccessor()
|
||||
child = this.getInitialization() and result = this.getInitializationSuccessor()
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
hasUninitializedInstruction() and
|
||||
this.hasUninitializedInstruction() and
|
||||
tag = InitializerStoreTag() and
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getInstruction(InitializerVariableAddressTag())
|
||||
result = this.getInstruction(InitializerVariableAddressTag())
|
||||
}
|
||||
|
||||
final override IRVariable getInstructionVariable(InstructionTag tag) {
|
||||
(
|
||||
tag = InitializerVariableAddressTag()
|
||||
or
|
||||
hasUninitializedInstruction() and tag = InitializerStoreTag()
|
||||
this.hasUninitializedInstruction() and tag = InitializerStoreTag()
|
||||
) and
|
||||
result = getIRVariable()
|
||||
result = this.getIRVariable()
|
||||
}
|
||||
|
||||
final override Instruction getTargetAddress() {
|
||||
result = getInstruction(InitializerVariableAddressTag())
|
||||
result = this.getInstruction(InitializerVariableAddressTag())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,13 +116,13 @@ abstract class TranslatedVariableInitialization extends TranslatedElement, Initi
|
||||
*/
|
||||
final predicate hasUninitializedInstruction() {
|
||||
(
|
||||
not exists(getInitialization()) or
|
||||
getInitialization() instanceof TranslatedListInitialization or
|
||||
getInitialization() instanceof TranslatedConstructorInitialization or
|
||||
getInitialization().(TranslatedStringLiteralInitialization).zeroInitRange(_, _)
|
||||
not exists(this.getInitialization()) or
|
||||
this.getInitialization() instanceof TranslatedListInitialization or
|
||||
this.getInitialization() instanceof TranslatedConstructorInitialization or
|
||||
this.getInitialization().(TranslatedStringLiteralInitialization).zeroInitRange(_, _)
|
||||
) and
|
||||
// Variables with static or thread-local storage duration are zero-initialized at program startup.
|
||||
getIRVariable() instanceof IRAutomaticVariable
|
||||
this.getIRVariable() instanceof IRAutomaticVariable
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn
|
||||
final override Locatable getAst() { result = expr }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
/**
|
||||
* Gets the expression that is doing the initialization.
|
||||
@@ -157,7 +157,7 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn
|
||||
* Gets the initialization context that describes the location being
|
||||
* initialized.
|
||||
*/
|
||||
final InitializationContext getContext() { result = getParent() }
|
||||
final InitializationContext getContext() { result = this.getParent() }
|
||||
|
||||
final TranslatedFunction getEnclosingFunction() {
|
||||
result = getTranslatedFunction(this.getFunction())
|
||||
@@ -169,17 +169,17 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn
|
||||
*/
|
||||
abstract class TranslatedListInitialization extends TranslatedInitialization, InitializationContext {
|
||||
override Instruction getFirstInstruction() {
|
||||
result = getChild(0).getFirstInstruction()
|
||||
result = this.getChild(0).getFirstInstruction()
|
||||
or
|
||||
not exists(getChild(0)) and result = getParent().getChildSuccessor(this)
|
||||
not exists(this.getChild(0)) and result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
exists(int index |
|
||||
child = getChild(index) and
|
||||
if exists(getChild(index + 1))
|
||||
then result = getChild(index + 1).getFirstInstruction()
|
||||
else result = getParent().getChildSuccessor(this)
|
||||
child = this.getChild(index) and
|
||||
if exists(this.getChild(index + 1))
|
||||
then result = this.getChild(index + 1).getFirstInstruction()
|
||||
else result = this.getParent().getChildSuccessor(this)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -189,9 +189,9 @@ abstract class TranslatedListInitialization extends TranslatedInitialization, In
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getTargetAddress() { result = getContext().getTargetAddress() }
|
||||
override Instruction getTargetAddress() { result = this.getContext().getTargetAddress() }
|
||||
|
||||
override Type getTargetType() { result = getContext().getTargetType() }
|
||||
override Type getTargetType() { result = this.getContext().getTargetType() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -237,9 +237,11 @@ class TranslatedArrayListInitialization extends TranslatedListInitialization {
|
||||
abstract class TranslatedDirectInitialization extends TranslatedInitialization {
|
||||
TranslatedDirectInitialization() { not expr instanceof AggregateLiteral }
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = getInitializer() }
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = this.getInitializer() }
|
||||
|
||||
override Instruction getFirstInstruction() { result = getInitializer().getFirstInstruction() }
|
||||
override Instruction getFirstInstruction() {
|
||||
result = this.getInitializer().getFirstInstruction()
|
||||
}
|
||||
|
||||
final TranslatedExpr getInitializer() { result = getTranslatedExpr(expr) }
|
||||
}
|
||||
@@ -258,27 +260,27 @@ class TranslatedSimpleDirectInitialization extends TranslatedDirectInitializatio
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = InitializerStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getTypeForPRValue(getContext().getTargetType())
|
||||
resultType = getTypeForPRValue(this.getContext().getTargetType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = InitializerStoreTag() and
|
||||
result = getParent().getChildSuccessor(this) and
|
||||
result = this.getParent().getChildSuccessor(this) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getInitializer() and result = getInstruction(InitializerStoreTag())
|
||||
child = this.getInitializer() and result = this.getInstruction(InitializerStoreTag())
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = InitializerStoreTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getContext().getTargetAddress()
|
||||
result = this.getContext().getTargetAddress()
|
||||
or
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
result = getInitializer().getResult()
|
||||
result = this.getInitializer().getResult()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -305,13 +307,13 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
|
||||
// If the initializer string isn't large enough to fill the target, then
|
||||
// we have to generate another instruction sequence to store a constant
|
||||
// zero into the remainder of the array.
|
||||
zeroInitRange(_, elementCount) and
|
||||
this.zeroInitRange(_, elementCount) and
|
||||
(
|
||||
// Create a constant zero whose size is the size of the remaining
|
||||
// space in the target array.
|
||||
tag = ZeroPadStringConstantTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType = getUnknownOpaqueType(elementCount * getElementType().getSize())
|
||||
resultType = getUnknownOpaqueType(elementCount * this.getElementType().getSize())
|
||||
or
|
||||
// The index of the first element to be zero initialized.
|
||||
tag = ZeroPadStringElementIndexTag() and
|
||||
@@ -321,12 +323,12 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
|
||||
// Compute the address of the first element to be zero initialized.
|
||||
tag = ZeroPadStringElementAddressTag() and
|
||||
opcode instanceof Opcode::PointerAdd and
|
||||
resultType = getTypeForGLValue(getElementType())
|
||||
resultType = getTypeForGLValue(this.getElementType())
|
||||
or
|
||||
// Store the constant zero into the remainder of the string.
|
||||
tag = ZeroPadStringStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getUnknownOpaqueType(elementCount * getElementType().getSize())
|
||||
resultType = getUnknownOpaqueType(elementCount * this.getElementType().getSize())
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -335,78 +337,78 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
tag = InitializerLoadStringTag() and
|
||||
result = getInstruction(InitializerStoreTag())
|
||||
result = this.getInstruction(InitializerStoreTag())
|
||||
or
|
||||
if zeroInitRange(_, _)
|
||||
if this.zeroInitRange(_, _)
|
||||
then (
|
||||
tag = InitializerStoreTag() and
|
||||
result = getInstruction(ZeroPadStringConstantTag())
|
||||
result = this.getInstruction(ZeroPadStringConstantTag())
|
||||
or
|
||||
tag = ZeroPadStringConstantTag() and
|
||||
result = getInstruction(ZeroPadStringElementIndexTag())
|
||||
result = this.getInstruction(ZeroPadStringElementIndexTag())
|
||||
or
|
||||
tag = ZeroPadStringElementIndexTag() and
|
||||
result = getInstruction(ZeroPadStringElementAddressTag())
|
||||
result = this.getInstruction(ZeroPadStringElementAddressTag())
|
||||
or
|
||||
tag = ZeroPadStringElementAddressTag() and
|
||||
result = getInstruction(ZeroPadStringStoreTag())
|
||||
result = this.getInstruction(ZeroPadStringStoreTag())
|
||||
or
|
||||
tag = ZeroPadStringStoreTag() and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
) else (
|
||||
tag = InitializerStoreTag() and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getInitializer() and result = getInstruction(InitializerLoadStringTag())
|
||||
child = this.getInitializer() and result = this.getInstruction(InitializerLoadStringTag())
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = InitializerLoadStringTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getInitializer().getResult()
|
||||
result = this.getInitializer().getResult()
|
||||
)
|
||||
or
|
||||
tag = InitializerStoreTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getContext().getTargetAddress()
|
||||
result = this.getContext().getTargetAddress()
|
||||
or
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
result = getInstruction(InitializerLoadStringTag())
|
||||
result = this.getInstruction(InitializerLoadStringTag())
|
||||
)
|
||||
or
|
||||
tag = ZeroPadStringElementAddressTag() and
|
||||
(
|
||||
operandTag instanceof LeftOperandTag and
|
||||
result = getContext().getTargetAddress()
|
||||
result = this.getContext().getTargetAddress()
|
||||
or
|
||||
operandTag instanceof RightOperandTag and
|
||||
result = getInstruction(ZeroPadStringElementIndexTag())
|
||||
result = this.getInstruction(ZeroPadStringElementIndexTag())
|
||||
)
|
||||
or
|
||||
tag = ZeroPadStringStoreTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getInstruction(ZeroPadStringElementAddressTag())
|
||||
result = this.getInstruction(ZeroPadStringElementAddressTag())
|
||||
or
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
result = getInstruction(ZeroPadStringConstantTag())
|
||||
result = this.getInstruction(ZeroPadStringConstantTag())
|
||||
)
|
||||
}
|
||||
|
||||
override int getInstructionElementSize(InstructionTag tag) {
|
||||
tag = ZeroPadStringElementAddressTag() and
|
||||
result = max(getElementType().getSize())
|
||||
result = max(this.getElementType().getSize())
|
||||
}
|
||||
|
||||
override string getInstructionConstantValue(InstructionTag tag) {
|
||||
exists(int startIndex |
|
||||
zeroInitRange(startIndex, _) and
|
||||
this.zeroInitRange(startIndex, _) and
|
||||
(
|
||||
tag = ZeroPadStringConstantTag() and
|
||||
result = "0"
|
||||
@@ -419,13 +421,13 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
|
||||
|
||||
override predicate needsUnknownOpaqueType(int byteSize) {
|
||||
exists(int elementCount |
|
||||
zeroInitRange(_, elementCount) and
|
||||
byteSize = elementCount * getElementType().getSize()
|
||||
this.zeroInitRange(_, elementCount) and
|
||||
byteSize = elementCount * this.getElementType().getSize()
|
||||
)
|
||||
}
|
||||
|
||||
private Type getElementType() {
|
||||
result = getContext().getTargetType().getUnspecifiedType().(ArrayType).getBaseType()
|
||||
result = this.getContext().getTargetType().getUnspecifiedType().(ArrayType).getBaseType()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -435,7 +437,8 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
|
||||
predicate zeroInitRange(int startIndex, int elementCount) {
|
||||
exists(int targetCount |
|
||||
startIndex = expr.getUnspecifiedType().(ArrayType).getArraySize() and
|
||||
targetCount = getContext().getTargetType().getUnspecifiedType().(ArrayType).getArraySize() and
|
||||
targetCount =
|
||||
this.getContext().getTargetType().getUnspecifiedType().(ArrayType).getArraySize() and
|
||||
elementCount = targetCount - startIndex and
|
||||
elementCount > 0
|
||||
)
|
||||
@@ -454,14 +457,14 @@ class TranslatedConstructorInitialization extends TranslatedDirectInitialization
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getInitializer() and result = getParent().getChildSuccessor(this)
|
||||
child = this.getInitializer() and result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getReceiver() { result = getContext().getTargetAddress() }
|
||||
override Instruction getReceiver() { result = this.getContext().getTargetAddress() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -491,7 +494,7 @@ abstract class TranslatedFieldInitialization extends TranslatedElement {
|
||||
final override Locatable getAst() { result = ast }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
final override Declaration getFunction() {
|
||||
result = getEnclosingFunction(ast) or
|
||||
@@ -499,7 +502,9 @@ abstract class TranslatedFieldInitialization extends TranslatedElement {
|
||||
result = getEnclosingVariable(ast).(StaticInitializedStaticLocalVariable)
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction() { result = getInstruction(getFieldAddressTag()) }
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = this.getInstruction(this.getFieldAddressTag())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the zero-based index describing the order in which this field is to be
|
||||
@@ -508,19 +513,19 @@ abstract class TranslatedFieldInitialization extends TranslatedElement {
|
||||
final int getOrder() { result = field.getInitializationOrder() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = getFieldAddressTag() and
|
||||
tag = this.getFieldAddressTag() and
|
||||
opcode instanceof Opcode::FieldAddress and
|
||||
resultType = getTypeForGLValue(field.getType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = getFieldAddressTag() and
|
||||
tag = this.getFieldAddressTag() and
|
||||
operandTag instanceof UnaryOperandTag and
|
||||
result = getParent().(InitializationContext).getTargetAddress()
|
||||
result = this.getParent().(InitializationContext).getTargetAddress()
|
||||
}
|
||||
|
||||
override Field getInstructionField(InstructionTag tag) {
|
||||
tag = getFieldAddressTag() and result = field
|
||||
tag = this.getFieldAddressTag() and result = field
|
||||
}
|
||||
|
||||
final InstructionTag getFieldAddressTag() { result = InitializerFieldAddressTag() }
|
||||
@@ -545,21 +550,23 @@ class TranslatedExplicitFieldInitialization extends TranslatedFieldInitializatio
|
||||
this = TTranslatedExplicitFieldInitialization(ast, field, expr, position)
|
||||
}
|
||||
|
||||
override Instruction getTargetAddress() { result = getInstruction(getFieldAddressTag()) }
|
||||
override Instruction getTargetAddress() {
|
||||
result = this.getInstruction(this.getFieldAddressTag())
|
||||
}
|
||||
|
||||
override Type getTargetType() { result = field.getUnspecifiedType() }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = getFieldAddressTag() and
|
||||
result = getInitialization().getFirstInstruction() and
|
||||
tag = this.getFieldAddressTag() and
|
||||
result = this.getInitialization().getFirstInstruction() and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getInitialization() and result = getParent().getChildSuccessor(this)
|
||||
child = this.getInitialization() and result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() }
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() }
|
||||
|
||||
private TranslatedInitialization getInitialization() {
|
||||
result = getTranslatedInitialization(expr)
|
||||
@@ -584,11 +591,11 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization,
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
TranslatedFieldInitialization.super.hasInstruction(opcode, tag, resultType)
|
||||
or
|
||||
tag = getFieldDefaultValueTag() and
|
||||
tag = this.getFieldDefaultValueTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType = getTypeForPRValue(field.getType())
|
||||
or
|
||||
tag = getFieldDefaultValueStoreTag() and
|
||||
tag = this.getFieldDefaultValueStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getTypeForPRValue(field.getUnspecifiedType())
|
||||
}
|
||||
@@ -596,32 +603,32 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization,
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
tag = getFieldAddressTag() and
|
||||
result = getInstruction(getFieldDefaultValueTag())
|
||||
tag = this.getFieldAddressTag() and
|
||||
result = this.getInstruction(this.getFieldDefaultValueTag())
|
||||
or
|
||||
tag = getFieldDefaultValueTag() and
|
||||
result = getInstruction(getFieldDefaultValueStoreTag())
|
||||
tag = this.getFieldDefaultValueTag() and
|
||||
result = this.getInstruction(this.getFieldDefaultValueStoreTag())
|
||||
or
|
||||
tag = getFieldDefaultValueStoreTag() and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
tag = this.getFieldDefaultValueStoreTag() and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
)
|
||||
}
|
||||
|
||||
override string getInstructionConstantValue(InstructionTag tag) {
|
||||
tag = getFieldDefaultValueTag() and
|
||||
tag = this.getFieldDefaultValueTag() and
|
||||
result = getZeroValue(field.getUnspecifiedType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
result = TranslatedFieldInitialization.super.getInstructionRegisterOperand(tag, operandTag)
|
||||
or
|
||||
tag = getFieldDefaultValueStoreTag() and
|
||||
tag = this.getFieldDefaultValueStoreTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getInstruction(getFieldAddressTag())
|
||||
result = this.getInstruction(this.getFieldAddressTag())
|
||||
or
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
result = getInstruction(getFieldDefaultValueTag())
|
||||
result = this.getInstruction(this.getFieldDefaultValueTag())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -644,13 +651,13 @@ abstract class TranslatedElementInitialization extends TranslatedElement {
|
||||
ArrayOrVectorAggregateLiteral initList;
|
||||
|
||||
final override string toString() {
|
||||
result = initList.toString() + "[" + getElementIndex().toString() + "]"
|
||||
result = initList.toString() + "[" + this.getElementIndex().toString() + "]"
|
||||
}
|
||||
|
||||
final override Locatable getAst() { result = initList }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
final override Declaration getFunction() {
|
||||
result = getEnclosingFunction(initList)
|
||||
@@ -660,43 +667,45 @@ abstract class TranslatedElementInitialization extends TranslatedElement {
|
||||
result = getEnclosingVariable(initList).(StaticInitializedStaticLocalVariable)
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction() { result = getInstruction(getElementIndexTag()) }
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = this.getInstruction(this.getElementIndexTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = getElementIndexTag() and
|
||||
tag = this.getElementIndexTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType = getIntType()
|
||||
or
|
||||
tag = getElementAddressTag() and
|
||||
tag = this.getElementAddressTag() and
|
||||
opcode instanceof Opcode::PointerAdd and
|
||||
resultType = getTypeForGLValue(getElementType())
|
||||
resultType = getTypeForGLValue(this.getElementType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = getElementIndexTag() and
|
||||
result = getInstruction(getElementAddressTag()) and
|
||||
tag = this.getElementIndexTag() and
|
||||
result = this.getInstruction(this.getElementAddressTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = getElementAddressTag() and
|
||||
tag = this.getElementAddressTag() and
|
||||
(
|
||||
operandTag instanceof LeftOperandTag and
|
||||
result = getParent().(InitializationContext).getTargetAddress()
|
||||
result = this.getParent().(InitializationContext).getTargetAddress()
|
||||
or
|
||||
operandTag instanceof RightOperandTag and
|
||||
result = getInstruction(getElementIndexTag())
|
||||
result = this.getInstruction(this.getElementIndexTag())
|
||||
)
|
||||
}
|
||||
|
||||
override int getInstructionElementSize(InstructionTag tag) {
|
||||
tag = getElementAddressTag() and
|
||||
result = max(getElementType().getSize())
|
||||
tag = this.getElementAddressTag() and
|
||||
result = max(this.getElementType().getSize())
|
||||
}
|
||||
|
||||
override string getInstructionConstantValue(InstructionTag tag) {
|
||||
tag = getElementIndexTag() and
|
||||
result = getElementIndex().toString()
|
||||
tag = this.getElementIndexTag() and
|
||||
result = this.getElementIndex().toString()
|
||||
}
|
||||
|
||||
abstract int getElementIndex();
|
||||
@@ -726,23 +735,25 @@ class TranslatedExplicitElementInitialization extends TranslatedElementInitializ
|
||||
this = TTranslatedExplicitElementInitialization(initList, elementIndex, position)
|
||||
}
|
||||
|
||||
override Instruction getTargetAddress() { result = getInstruction(getElementAddressTag()) }
|
||||
override Instruction getTargetAddress() {
|
||||
result = this.getInstruction(this.getElementAddressTag())
|
||||
}
|
||||
|
||||
override Type getTargetType() { result = getElementType() }
|
||||
override Type getTargetType() { result = this.getElementType() }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
result = TranslatedElementInitialization.super.getInstructionSuccessor(tag, kind)
|
||||
or
|
||||
tag = getElementAddressTag() and
|
||||
result = getInitialization().getFirstInstruction() and
|
||||
tag = this.getElementAddressTag() and
|
||||
result = this.getInitialization().getFirstInstruction() and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getInitialization() and result = getParent().getChildSuccessor(this)
|
||||
child = this.getInitialization() and result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() }
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() }
|
||||
|
||||
override int getElementIndex() { result = elementIndex }
|
||||
|
||||
@@ -773,13 +784,13 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
TranslatedElementInitialization.super.hasInstruction(opcode, tag, resultType)
|
||||
or
|
||||
tag = getElementDefaultValueTag() and
|
||||
tag = this.getElementDefaultValueTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType = getDefaultValueType()
|
||||
resultType = this.getDefaultValueType()
|
||||
or
|
||||
tag = getElementDefaultValueStoreTag() and
|
||||
tag = this.getElementDefaultValueStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getDefaultValueType()
|
||||
resultType = this.getDefaultValueType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
@@ -787,34 +798,34 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
or
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
tag = getElementAddressTag() and
|
||||
result = getInstruction(getElementDefaultValueTag())
|
||||
tag = this.getElementAddressTag() and
|
||||
result = this.getInstruction(this.getElementDefaultValueTag())
|
||||
or
|
||||
tag = getElementDefaultValueTag() and
|
||||
result = getInstruction(getElementDefaultValueStoreTag())
|
||||
tag = this.getElementDefaultValueTag() and
|
||||
result = this.getInstruction(this.getElementDefaultValueStoreTag())
|
||||
or
|
||||
tag = getElementDefaultValueStoreTag() and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
tag = this.getElementDefaultValueStoreTag() and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
)
|
||||
}
|
||||
|
||||
override string getInstructionConstantValue(InstructionTag tag) {
|
||||
result = TranslatedElementInitialization.super.getInstructionConstantValue(tag)
|
||||
or
|
||||
tag = getElementDefaultValueTag() and
|
||||
result = getZeroValue(getElementType())
|
||||
tag = this.getElementDefaultValueTag() and
|
||||
result = getZeroValue(this.getElementType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
result = TranslatedElementInitialization.super.getInstructionRegisterOperand(tag, operandTag)
|
||||
or
|
||||
tag = getElementDefaultValueStoreTag() and
|
||||
tag = this.getElementDefaultValueStoreTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getInstruction(getElementAddressTag())
|
||||
result = this.getInstruction(this.getElementAddressTag())
|
||||
or
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
result = getInstruction(getElementDefaultValueTag())
|
||||
result = this.getInstruction(this.getElementDefaultValueTag())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -825,7 +836,7 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
override int getElementIndex() { result = elementIndex }
|
||||
|
||||
override predicate needsUnknownOpaqueType(int byteSize) {
|
||||
elementCount != 0 and byteSize = elementCount * getElementType().getSize()
|
||||
elementCount != 0 and byteSize = elementCount * this.getElementType().getSize()
|
||||
}
|
||||
|
||||
private InstructionTag getElementDefaultValueTag() {
|
||||
@@ -838,8 +849,8 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
|
||||
private CppType getDefaultValueType() {
|
||||
if elementCount = 1
|
||||
then result = getTypeForPRValue(getElementType())
|
||||
else result = getUnknownOpaqueType(elementCount * getElementType().getSize())
|
||||
then result = getTypeForPRValue(this.getElementType())
|
||||
else result = getUnknownOpaqueType(elementCount * this.getElementType().getSize())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -849,18 +860,18 @@ abstract class TranslatedStructorCallFromStructor extends TranslatedElement, Str
|
||||
final override Locatable getAst() { result = call }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
final override TranslatedElement getChild(int id) {
|
||||
id = 0 and
|
||||
result = getStructorCall()
|
||||
result = this.getStructorCall()
|
||||
}
|
||||
|
||||
final override Function getFunction() { result = getEnclosingFunction(call) }
|
||||
|
||||
final override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getStructorCall() and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
child = this.getStructorCall() and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
final TranslatedExpr getStructorCall() { result = getTranslatedExpr(call) }
|
||||
@@ -871,7 +882,9 @@ abstract class TranslatedStructorCallFromStructor extends TranslatedElement, Str
|
||||
* destructor from within a derived class constructor or destructor.
|
||||
*/
|
||||
abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStructor {
|
||||
final override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
@@ -882,15 +895,15 @@ abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStru
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = getStructorCall().getFirstInstruction()
|
||||
result = this.getStructorCall().getFirstInstruction()
|
||||
}
|
||||
|
||||
final override Instruction getReceiver() { result = getInstruction(OnlyInstructionTag()) }
|
||||
final override Instruction getReceiver() { result = this.getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = OnlyInstructionTag() and
|
||||
operandTag instanceof UnaryOperandTag and
|
||||
result = getTranslatedFunction(getFunction()).getInitializeThisInstruction()
|
||||
result = getTranslatedFunction(this.getFunction()).getInitializeThisInstruction()
|
||||
}
|
||||
|
||||
final override predicate getInstructionInheritance(
|
||||
@@ -898,7 +911,7 @@ abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStru
|
||||
) {
|
||||
tag = OnlyInstructionTag() and
|
||||
baseClass = call.getTarget().getDeclaringType().getUnspecifiedType() and
|
||||
derivedClass = getFunction().getDeclaringType().getUnspecifiedType()
|
||||
derivedClass = this.getFunction().getDeclaringType().getUnspecifiedType()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -924,7 +937,7 @@ class TranslatedConstructorDelegationInit extends TranslatedConstructorCallFromC
|
||||
final override string toString() { result = "delegation construct: " + call.toString() }
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = getStructorCall().getFirstInstruction()
|
||||
result = this.getStructorCall().getFirstInstruction()
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
@@ -934,7 +947,7 @@ class TranslatedConstructorDelegationInit extends TranslatedConstructorCallFromC
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
final override Instruction getReceiver() {
|
||||
result = getTranslatedFunction(getFunction()).getInitializeThisInstruction()
|
||||
result = getTranslatedFunction(this.getFunction()).getInitializeThisInstruction()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -981,11 +994,11 @@ class TranslatedConstructorBareInit extends TranslatedElement, TTranslatedConstr
|
||||
override Locatable getAst() { result = init }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
final override string toString() { result = "construct base (no constructor)" }
|
||||
|
||||
override Instruction getFirstInstruction() { result = getParent().getChildSuccessor(this) }
|
||||
override Instruction getFirstInstruction() { result = this.getParent().getChildSuccessor(this) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
|
||||
@@ -240,7 +240,7 @@ abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt {
|
||||
final override Locatable getAst() { result = stmt }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
final override Function getFunction() { result = stmt.getEnclosingFunction() }
|
||||
}
|
||||
@@ -254,7 +254,7 @@ class TranslatedEmptyStmt extends TranslatedStmt {
|
||||
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
|
||||
override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
@@ -264,7 +264,7 @@ class TranslatedEmptyStmt extends TranslatedStmt {
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = getParent().getChildSuccessor(this) and
|
||||
result = this.getParent().getChildSuccessor(this) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
@@ -279,19 +279,19 @@ class TranslatedEmptyStmt extends TranslatedStmt {
|
||||
class TranslatedDeclStmt extends TranslatedStmt {
|
||||
override DeclStmt stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) { result = getDeclarationEntry(id) }
|
||||
override TranslatedElement getChild(int id) { result = this.getDeclarationEntry(id) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
result = getDeclarationEntry(0).getFirstInstruction()
|
||||
result = this.getDeclarationEntry(0).getFirstInstruction()
|
||||
or
|
||||
not exists(getDeclarationEntry(0)) and result = getParent().getChildSuccessor(this)
|
||||
not exists(this.getDeclarationEntry(0)) and result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
private int getChildCount() { result = count(getDeclarationEntry(_)) }
|
||||
private int getChildCount() { result = count(this.getDeclarationEntry(_)) }
|
||||
|
||||
IRDeclarationEntry getIRDeclarationEntry(int index) {
|
||||
result.hasIndex(index) and
|
||||
@@ -319,10 +319,10 @@ class TranslatedDeclStmt extends TranslatedStmt {
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
exists(int index |
|
||||
child = getDeclarationEntry(index) and
|
||||
if index = (getChildCount() - 1)
|
||||
then result = getParent().getChildSuccessor(this)
|
||||
else result = getDeclarationEntry(index + 1).getFirstInstruction()
|
||||
child = this.getDeclarationEntry(index) and
|
||||
if index = (this.getChildCount() - 1)
|
||||
then result = this.getParent().getChildSuccessor(this)
|
||||
else result = this.getDeclarationEntry(index + 1).getFirstInstruction()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -332,19 +332,19 @@ class TranslatedExprStmt extends TranslatedStmt {
|
||||
|
||||
TranslatedExpr getExpr() { result = getTranslatedExpr(stmt.getExpr().getFullyConverted()) }
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = getExpr() }
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = this.getExpr() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() { result = getExpr().getFirstInstruction() }
|
||||
override Instruction getFirstInstruction() { result = this.getExpr().getFirstInstruction() }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getExpr() and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
child = this.getExpr() and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,16 +363,18 @@ class TranslatedReturnValueStmt extends TranslatedReturnStmt, TranslatedVariable
|
||||
TranslatedReturnValueStmt() { stmt.hasExpr() and hasReturnValue(stmt.getEnclosingFunction()) }
|
||||
|
||||
final override Instruction getInitializationSuccessor() {
|
||||
result = getEnclosingFunction().getReturnSuccessorInstruction()
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction()
|
||||
}
|
||||
|
||||
final override Type getTargetType() { result = getEnclosingFunction().getReturnType() }
|
||||
final override Type getTargetType() { result = this.getEnclosingFunction().getReturnType() }
|
||||
|
||||
final override TranslatedInitialization getInitialization() {
|
||||
result = getTranslatedInitialization(stmt.getExpr().getFullyConverted())
|
||||
}
|
||||
|
||||
final override IRVariable getIRVariable() { result = getEnclosingFunction().getReturnVariable() }
|
||||
final override IRVariable getIRVariable() {
|
||||
result = this.getEnclosingFunction().getReturnVariable()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -385,10 +387,10 @@ class TranslatedReturnVoidExpressionStmt extends TranslatedReturnStmt {
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and
|
||||
result = getExpr()
|
||||
result = this.getExpr()
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() { result = getExpr().getFirstInstruction() }
|
||||
override Instruction getFirstInstruction() { result = this.getExpr().getFirstInstruction() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
@@ -398,13 +400,13 @@ class TranslatedReturnVoidExpressionStmt extends TranslatedReturnStmt {
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = getEnclosingFunction().getReturnSuccessorInstruction() and
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction() and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getExpr() and
|
||||
result = getInstruction(OnlyInstructionTag())
|
||||
child = this.getExpr() and
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
private TranslatedExpr getExpr() { result = getTranslatedExpr(stmt.getExpr()) }
|
||||
@@ -421,7 +423,7 @@ class TranslatedReturnVoidStmt extends TranslatedReturnStmt {
|
||||
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
|
||||
override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
@@ -431,7 +433,7 @@ class TranslatedReturnVoidStmt extends TranslatedReturnStmt {
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = getEnclosingFunction().getReturnSuccessorInstruction() and
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction() and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
@@ -452,7 +454,7 @@ class TranslatedUnreachableReturnStmt extends TranslatedReturnStmt {
|
||||
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
|
||||
override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
@@ -511,9 +513,9 @@ class TranslatedTryStmt extends TranslatedStmt {
|
||||
override TryOrMicrosoftTryStmt stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = getBody()
|
||||
id = 0 and result = this.getBody()
|
||||
or
|
||||
result = getHandler(id - 1)
|
||||
result = this.getHandler(id - 1)
|
||||
or
|
||||
id = stmt.getNumberOfCatchClauses() + 1 and
|
||||
result = this.getFinally()
|
||||
@@ -525,7 +527,7 @@ class TranslatedTryStmt extends TranslatedStmt {
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getFirstInstruction() { result = getBody().getFirstInstruction() }
|
||||
override Instruction getFirstInstruction() { result = this.getBody().getFirstInstruction() }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
// All non-finally children go to the successor of the `try` if
|
||||
@@ -546,19 +548,19 @@ class TranslatedTryStmt extends TranslatedStmt {
|
||||
|
||||
final Instruction getNextHandler(TranslatedHandler handler) {
|
||||
exists(int index |
|
||||
handler = getHandler(index) and
|
||||
result = getHandler(index + 1).getFirstInstruction()
|
||||
handler = this.getHandler(index) and
|
||||
result = this.getHandler(index + 1).getFirstInstruction()
|
||||
)
|
||||
or
|
||||
// The last catch clause flows to the exception successor of the parent
|
||||
// of the `try`, because the exception successor of the `try` itself is
|
||||
// the first catch clause.
|
||||
handler = getHandler(stmt.getNumberOfCatchClauses() - 1) and
|
||||
result = getParent().getExceptionSuccessorInstruction()
|
||||
handler = this.getHandler(stmt.getNumberOfCatchClauses() - 1) and
|
||||
result = this.getParent().getExceptionSuccessorInstruction()
|
||||
}
|
||||
|
||||
final override Instruction getExceptionSuccessorInstruction() {
|
||||
result = getHandler(0).getFirstInstruction()
|
||||
result = this.getHandler(0).getFirstInstruction()
|
||||
}
|
||||
|
||||
private TranslatedElement getHandler(int index) { result = stmt.getTranslatedHandler(index) }
|
||||
@@ -571,19 +573,19 @@ class TranslatedTryStmt extends TranslatedStmt {
|
||||
class TranslatedBlock extends TranslatedStmt {
|
||||
override BlockStmt stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) { result = getStmt(id) }
|
||||
override TranslatedElement getChild(int id) { result = this.getStmt(id) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
isEmpty() and
|
||||
this.isEmpty() and
|
||||
opcode instanceof Opcode::NoOp and
|
||||
tag = OnlyInstructionTag() and
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if isEmpty()
|
||||
then result = getInstruction(OnlyInstructionTag())
|
||||
else result = getStmt(0).getFirstInstruction()
|
||||
if this.isEmpty()
|
||||
then result = this.getInstruction(OnlyInstructionTag())
|
||||
else result = this.getStmt(0).getFirstInstruction()
|
||||
}
|
||||
|
||||
private predicate isEmpty() { not exists(stmt.getStmt(0)) }
|
||||
@@ -594,16 +596,16 @@ class TranslatedBlock extends TranslatedStmt {
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = getParent().getChildSuccessor(this) and
|
||||
result = this.getParent().getChildSuccessor(this) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
exists(int index |
|
||||
child = getStmt(index) and
|
||||
if index = (getStmtCount() - 1)
|
||||
then result = getParent().getChildSuccessor(this)
|
||||
else result = getStmt(index + 1).getFirstInstruction()
|
||||
child = this.getStmt(index) and
|
||||
if index = (this.getStmtCount() - 1)
|
||||
then result = this.getParent().getChildSuccessor(this)
|
||||
else result = this.getStmt(index + 1).getFirstInstruction()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -614,18 +616,18 @@ class TranslatedBlock extends TranslatedStmt {
|
||||
abstract class TranslatedHandler extends TranslatedStmt {
|
||||
override Handler stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 1 and result = getBlock() }
|
||||
override TranslatedElement getChild(int id) { id = 1 and result = this.getBlock() }
|
||||
|
||||
override Instruction getFirstInstruction() { result = getInstruction(CatchTag()) }
|
||||
override Instruction getFirstInstruction() { result = this.getInstruction(CatchTag()) }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getBlock() and result = getParent().getChildSuccessor(this)
|
||||
child = this.getBlock() and result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getExceptionSuccessorInstruction() {
|
||||
// A throw from within a `catch` block flows to the handler for the parent of
|
||||
// the `try`.
|
||||
result = getParent().getParent().getExceptionSuccessorInstruction()
|
||||
result = this.getParent().getParent().getExceptionSuccessorInstruction()
|
||||
}
|
||||
|
||||
TranslatedStmt getBlock() { result = getTranslatedStmt(stmt.getBlock()) }
|
||||
@@ -647,23 +649,23 @@ class TranslatedCatchByTypeHandler extends TranslatedHandler {
|
||||
override TranslatedElement getChild(int id) {
|
||||
result = super.getChild(id)
|
||||
or
|
||||
id = 0 and result = getParameter()
|
||||
id = 0 and result = this.getParameter()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
result = super.getChildSuccessor(child)
|
||||
or
|
||||
child = getParameter() and result = getBlock().getFirstInstruction()
|
||||
child = this.getParameter() and result = this.getBlock().getFirstInstruction()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = CatchTag() and
|
||||
(
|
||||
kind instanceof GotoEdge and
|
||||
result = getParameter().getFirstInstruction()
|
||||
result = this.getParameter().getFirstInstruction()
|
||||
or
|
||||
kind instanceof ExceptionEdge and
|
||||
result = getParent().(TranslatedTryStmt).getNextHandler(this)
|
||||
result = this.getParent().(TranslatedTryStmt).getNextHandler(this)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -692,7 +694,7 @@ class TranslatedCatchAnyHandler extends TranslatedHandler {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = CatchTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = getBlock().getFirstInstruction()
|
||||
result = this.getBlock().getFirstInstruction()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -700,19 +702,19 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
|
||||
override IfStmt stmt;
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if hasInitialization()
|
||||
then result = getInitialization().getFirstInstruction()
|
||||
else result = getFirstConditionInstruction()
|
||||
if this.hasInitialization()
|
||||
then result = this.getInitialization().getFirstInstruction()
|
||||
else result = this.getFirstConditionInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = getInitialization()
|
||||
id = 0 and result = this.getInitialization()
|
||||
or
|
||||
id = 1 and result = getCondition()
|
||||
id = 1 and result = this.getCondition()
|
||||
or
|
||||
id = 2 and result = getThen()
|
||||
id = 2 and result = this.getThen()
|
||||
or
|
||||
id = 3 and result = getElse()
|
||||
id = 3 and result = this.getElse()
|
||||
}
|
||||
|
||||
private predicate hasInitialization() { exists(stmt.getInitialization()) }
|
||||
@@ -726,7 +728,7 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
|
||||
}
|
||||
|
||||
private Instruction getFirstConditionInstruction() {
|
||||
result = getCondition().getFirstInstruction()
|
||||
result = this.getCondition().getFirstInstruction()
|
||||
}
|
||||
|
||||
private TranslatedStmt getThen() { result = getTranslatedStmt(stmt.getThen()) }
|
||||
@@ -738,23 +740,23 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
|
||||
child = getCondition() and
|
||||
result = getThen().getFirstInstruction()
|
||||
child = this.getCondition() and
|
||||
result = this.getThen().getFirstInstruction()
|
||||
}
|
||||
|
||||
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
|
||||
child = getCondition() and
|
||||
if hasElse()
|
||||
then result = getElse().getFirstInstruction()
|
||||
else result = getParent().getChildSuccessor(this)
|
||||
child = this.getCondition() and
|
||||
if this.hasElse()
|
||||
then result = this.getElse().getFirstInstruction()
|
||||
else result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getInitialization() and
|
||||
result = getFirstConditionInstruction()
|
||||
child = this.getInitialization() and
|
||||
result = this.getFirstConditionInstruction()
|
||||
or
|
||||
(child = getThen() or child = getElse()) and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
(child = this.getThen() or child = this.getElse()) and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
@@ -772,17 +774,17 @@ abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
|
||||
final TranslatedStmt getBody() { result = getTranslatedStmt(stmt.getStmt()) }
|
||||
|
||||
final Instruction getFirstConditionInstruction() {
|
||||
if hasCondition()
|
||||
then result = getCondition().getFirstInstruction()
|
||||
else result = getBody().getFirstInstruction()
|
||||
if this.hasCondition()
|
||||
then result = this.getCondition().getFirstInstruction()
|
||||
else result = this.getBody().getFirstInstruction()
|
||||
}
|
||||
|
||||
final predicate hasCondition() { exists(stmt.getCondition()) }
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = getCondition()
|
||||
id = 0 and result = this.getCondition()
|
||||
or
|
||||
id = 1 and result = getBody()
|
||||
id = 1 and result = this.getBody()
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
@@ -792,31 +794,31 @@ abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
final override Instruction getChildTrueSuccessor(TranslatedCondition child) {
|
||||
child = getCondition() and result = getBody().getFirstInstruction()
|
||||
child = this.getCondition() and result = this.getBody().getFirstInstruction()
|
||||
}
|
||||
|
||||
final override Instruction getChildFalseSuccessor(TranslatedCondition child) {
|
||||
child = getCondition() and result = getParent().getChildSuccessor(this)
|
||||
child = this.getCondition() and result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
}
|
||||
|
||||
class TranslatedWhileStmt extends TranslatedLoop {
|
||||
TranslatedWhileStmt() { stmt instanceof WhileStmt }
|
||||
|
||||
override Instruction getFirstInstruction() { result = getFirstConditionInstruction() }
|
||||
override Instruction getFirstInstruction() { result = this.getFirstConditionInstruction() }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getBody() and result = getFirstConditionInstruction()
|
||||
child = this.getBody() and result = this.getFirstConditionInstruction()
|
||||
}
|
||||
}
|
||||
|
||||
class TranslatedDoStmt extends TranslatedLoop {
|
||||
TranslatedDoStmt() { stmt instanceof DoStmt }
|
||||
|
||||
override Instruction getFirstInstruction() { result = getBody().getFirstInstruction() }
|
||||
override Instruction getFirstInstruction() { result = this.getBody().getFirstInstruction() }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getBody() and result = getFirstConditionInstruction()
|
||||
child = this.getBody() and result = this.getFirstConditionInstruction()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -824,13 +826,13 @@ class TranslatedForStmt extends TranslatedLoop {
|
||||
override ForStmt stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = getInitialization()
|
||||
id = 0 and result = this.getInitialization()
|
||||
or
|
||||
id = 1 and result = getCondition()
|
||||
id = 1 and result = this.getCondition()
|
||||
or
|
||||
id = 2 and result = getUpdate()
|
||||
id = 2 and result = this.getUpdate()
|
||||
or
|
||||
id = 3 and result = getBody()
|
||||
id = 3 and result = this.getBody()
|
||||
}
|
||||
|
||||
private TranslatedStmt getInitialization() {
|
||||
@@ -844,23 +846,23 @@ class TranslatedForStmt extends TranslatedLoop {
|
||||
private predicate hasUpdate() { exists(stmt.getUpdate()) }
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if hasInitialization()
|
||||
then result = getInitialization().getFirstInstruction()
|
||||
else result = getFirstConditionInstruction()
|
||||
if this.hasInitialization()
|
||||
then result = this.getInitialization().getFirstInstruction()
|
||||
else result = this.getFirstConditionInstruction()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getInitialization() and
|
||||
result = getFirstConditionInstruction()
|
||||
child = this.getInitialization() and
|
||||
result = this.getFirstConditionInstruction()
|
||||
or
|
||||
(
|
||||
child = getBody() and
|
||||
if hasUpdate()
|
||||
then result = getUpdate().getFirstInstruction()
|
||||
else result = getFirstConditionInstruction()
|
||||
child = this.getBody() and
|
||||
if this.hasUpdate()
|
||||
then result = this.getUpdate().getFirstInstruction()
|
||||
else result = this.getFirstConditionInstruction()
|
||||
)
|
||||
or
|
||||
child = getUpdate() and result = getFirstConditionInstruction()
|
||||
child = this.getUpdate() and result = this.getFirstConditionInstruction()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -875,39 +877,39 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
|
||||
override RangeBasedForStmt stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = getRangeVariableDeclStmt()
|
||||
id = 0 and result = this.getRangeVariableDeclStmt()
|
||||
or
|
||||
// Note: `__begin` and `__end` are declared by the same `DeclStmt`
|
||||
id = 1 and result = getBeginEndVariableDeclStmt()
|
||||
id = 1 and result = this.getBeginEndVariableDeclStmt()
|
||||
or
|
||||
id = 2 and result = getCondition()
|
||||
id = 2 and result = this.getCondition()
|
||||
or
|
||||
id = 3 and result = getUpdate()
|
||||
id = 3 and result = this.getUpdate()
|
||||
or
|
||||
id = 4 and result = getVariableDeclStmt()
|
||||
id = 4 and result = this.getVariableDeclStmt()
|
||||
or
|
||||
id = 5 and result = getBody()
|
||||
id = 5 and result = this.getBody()
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
result = getRangeVariableDeclStmt().getFirstInstruction()
|
||||
result = this.getRangeVariableDeclStmt().getFirstInstruction()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getRangeVariableDeclStmt() and
|
||||
result = getBeginEndVariableDeclStmt().getFirstInstruction()
|
||||
child = this.getRangeVariableDeclStmt() and
|
||||
result = this.getBeginEndVariableDeclStmt().getFirstInstruction()
|
||||
or
|
||||
child = getBeginEndVariableDeclStmt() and
|
||||
result = getCondition().getFirstInstruction()
|
||||
child = this.getBeginEndVariableDeclStmt() and
|
||||
result = this.getCondition().getFirstInstruction()
|
||||
or
|
||||
child = getVariableDeclStmt() and
|
||||
result = getBody().getFirstInstruction()
|
||||
child = this.getVariableDeclStmt() and
|
||||
result = this.getBody().getFirstInstruction()
|
||||
or
|
||||
child = getBody() and
|
||||
result = getUpdate().getFirstInstruction()
|
||||
child = this.getBody() and
|
||||
result = this.getUpdate().getFirstInstruction()
|
||||
or
|
||||
child = getUpdate() and
|
||||
result = getCondition().getFirstInstruction()
|
||||
child = this.getUpdate() and
|
||||
result = this.getCondition().getFirstInstruction()
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
@@ -917,11 +919,11 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
|
||||
child = getCondition() and result = getVariableDeclStmt().getFirstInstruction()
|
||||
child = this.getCondition() and result = this.getVariableDeclStmt().getFirstInstruction()
|
||||
}
|
||||
|
||||
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
|
||||
child = getCondition() and result = getParent().getChildSuccessor(this)
|
||||
child = this.getCondition() and result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
private TranslatedDeclStmt getRangeVariableDeclStmt() {
|
||||
@@ -961,7 +963,7 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
|
||||
class TranslatedJumpStmt extends TranslatedStmt {
|
||||
override JumpStmt stmt;
|
||||
|
||||
override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
|
||||
override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
@@ -996,22 +998,22 @@ class TranslatedSwitchStmt extends TranslatedStmt {
|
||||
result = getTranslatedExpr(stmt.getExpr().getFullyConverted())
|
||||
}
|
||||
|
||||
private Instruction getFirstExprInstruction() { result = getExpr().getFirstInstruction() }
|
||||
private Instruction getFirstExprInstruction() { result = this.getExpr().getFirstInstruction() }
|
||||
|
||||
private TranslatedStmt getBody() { result = getTranslatedStmt(stmt.getStmt()) }
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if hasInitialization()
|
||||
then result = getInitialization().getFirstInstruction()
|
||||
else result = getFirstExprInstruction()
|
||||
if this.hasInitialization()
|
||||
then result = this.getInitialization().getFirstInstruction()
|
||||
else result = this.getFirstExprInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = getInitialization()
|
||||
id = 0 and result = this.getInitialization()
|
||||
or
|
||||
id = 1 and result = getExpr()
|
||||
id = 1 and result = this.getExpr()
|
||||
or
|
||||
id = 2 and result = getBody()
|
||||
id = 2 and result = this.getBody()
|
||||
}
|
||||
|
||||
private predicate hasInitialization() { exists(stmt.getInitialization()) }
|
||||
@@ -1029,7 +1031,7 @@ class TranslatedSwitchStmt extends TranslatedStmt {
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = SwitchBranchTag() and
|
||||
operandTag instanceof ConditionOperandTag and
|
||||
result = getExpr().getResult()
|
||||
result = this.getExpr().getResult()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
@@ -1043,15 +1045,15 @@ class TranslatedSwitchStmt extends TranslatedStmt {
|
||||
not stmt.hasDefaultCase() and
|
||||
tag = SwitchBranchTag() and
|
||||
kind instanceof DefaultEdge and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getInitialization() and result = getFirstExprInstruction()
|
||||
child = this.getInitialization() and result = this.getFirstExprInstruction()
|
||||
or
|
||||
child = getExpr() and result = getInstruction(SwitchBranchTag())
|
||||
child = this.getExpr() and result = this.getInstruction(SwitchBranchTag())
|
||||
or
|
||||
child = getBody() and result = getParent().getChildSuccessor(this)
|
||||
child = this.getBody() and result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1063,9 +1065,9 @@ class TranslatedAsmStmt extends TranslatedStmt {
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if exists(getChild(0))
|
||||
then result = getChild(0).getFirstInstruction()
|
||||
else result = getInstruction(AsmTag())
|
||||
if exists(this.getChild(0))
|
||||
then result = this.getChild(0).getFirstInstruction()
|
||||
else result = this.getInstruction(AsmTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
@@ -1078,7 +1080,7 @@ class TranslatedAsmStmt extends TranslatedStmt {
|
||||
exists(int index |
|
||||
tag = AsmTag() and
|
||||
operandTag = asmOperand(index) and
|
||||
result = getChild(index).getResult()
|
||||
result = this.getChild(index).getResult()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1092,16 +1094,16 @@ class TranslatedAsmStmt extends TranslatedStmt {
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = AsmTag() and
|
||||
result = getParent().getChildSuccessor(this) and
|
||||
result = this.getParent().getChildSuccessor(this) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
exists(int index |
|
||||
child = getChild(index) and
|
||||
if exists(getChild(index + 1))
|
||||
then result = getChild(index + 1).getFirstInstruction()
|
||||
else result = getInstruction(AsmTag())
|
||||
child = this.getChild(index) and
|
||||
if exists(this.getChild(index + 1))
|
||||
then result = this.getChild(index + 1).getFirstInstruction()
|
||||
else result = this.getInstruction(AsmTag())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,9 @@ predicate isInfeasibleInstructionSuccessor(Instruction instr, EdgeKind kind) {
|
||||
conditionValue = getConstantValue(instr.(ConditionalBranchInstruction).getCondition()) and
|
||||
if conditionValue = 0 then kind instanceof TrueEdge else kind instanceof FalseEdge
|
||||
)
|
||||
or
|
||||
instr.getSuccessor(kind) instanceof UnreachedInstruction and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
@@ -41,7 +44,9 @@ class ReachableBlock extends IRBlockBase {
|
||||
* An instruction that is contained in a reachable block.
|
||||
*/
|
||||
class ReachableInstruction extends Instruction {
|
||||
ReachableInstruction() { this.getBlock() instanceof ReachableBlock }
|
||||
ReachableInstruction() {
|
||||
this.getBlock() instanceof ReachableBlock and not this instanceof UnreachedInstruction
|
||||
}
|
||||
}
|
||||
|
||||
module Graph {
|
||||
|
||||
@@ -77,4 +77,16 @@ class IRPropertyProvider extends TIRPropertyProvider {
|
||||
* Gets the value of the property named `key` for the specified operand.
|
||||
*/
|
||||
string getOperandProperty(Operand operand, string key) { none() }
|
||||
|
||||
/**
|
||||
* Holds if the instruction `instr` should be included when printing
|
||||
* the IR instructions.
|
||||
*/
|
||||
predicate shouldPrintInstruction(Instruction instr) { any() }
|
||||
|
||||
/**
|
||||
* Holds if the operand `operand` should be included when printing the an
|
||||
* instruction's operand list.
|
||||
*/
|
||||
predicate shouldPrintOperand(Operand operand) { any() }
|
||||
}
|
||||
|
||||
@@ -45,7 +45,9 @@ class IRFunction extends IRFunctionBase {
|
||||
* Gets the block containing the entry point of this function.
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock getEntryBlock() { result.getFirstInstruction() = getEnterFunctionInstruction() }
|
||||
final IRBlock getEntryBlock() {
|
||||
result.getFirstInstruction() = this.getEnterFunctionInstruction()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all instructions in this function.
|
||||
|
||||
@@ -39,12 +39,12 @@ class IRVariable extends TIRVariable {
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
*/
|
||||
final Language::Type getType() { getLanguageType().hasType(result, false) }
|
||||
final Language::Type getType() { this.getLanguageType().hasType(result, false) }
|
||||
|
||||
/**
|
||||
* Gets the language-neutral type of the variable.
|
||||
*/
|
||||
final IRType getIRType() { result = getLanguageType().getIRType() }
|
||||
final IRType getIRType() { result = this.getLanguageType().getIRType() }
|
||||
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
@@ -58,7 +58,7 @@ class IRVariable extends TIRVariable {
|
||||
Language::AST getAst() { none() }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated Language::AST getAST() { result = getAst() }
|
||||
deprecated Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
/**
|
||||
* Gets an identifier string for the variable. This identifier is unique
|
||||
@@ -69,7 +69,7 @@ class IRVariable extends TIRVariable {
|
||||
/**
|
||||
* Gets the source location of this variable.
|
||||
*/
|
||||
final Language::Location getLocation() { result = getAst().getLocation() }
|
||||
final Language::Location getLocation() { result = this.getAst().getLocation() }
|
||||
|
||||
/**
|
||||
* Gets the IR for the function that references this variable.
|
||||
@@ -91,15 +91,15 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
|
||||
|
||||
IRUserVariable() { this = TIRUserVariable(var, type, func) }
|
||||
|
||||
final override string toString() { result = getVariable().toString() }
|
||||
final override string toString() { result = this.getVariable().toString() }
|
||||
|
||||
final override Language::AST getAst() { result = var }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = getAst() }
|
||||
deprecated override Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = getVariable().toString() + " " + getVariable().getLocation().toString()
|
||||
result = this.getVariable().toString() + " " + this.getVariable().getLocation().toString()
|
||||
}
|
||||
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
@@ -166,9 +166,9 @@ class IRGeneratedVariable extends IRVariable {
|
||||
final override Language::AST getAst() { result = ast }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = getAst() }
|
||||
deprecated override Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
override string toString() { result = getBaseString() + getLocationString() }
|
||||
override string toString() { result = this.getBaseString() + this.getLocationString() }
|
||||
|
||||
override string getUniqueId() { none() }
|
||||
|
||||
@@ -272,7 +272,7 @@ class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
|
||||
final override predicate isReadOnly() { any() }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal)
|
||||
result = "String: " + this.getLocationString() + "=" + Language::getStringLiteralText(literal)
|
||||
}
|
||||
|
||||
final override string getBaseString() { result = "#string" }
|
||||
@@ -303,7 +303,8 @@ class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitial
|
||||
final Language::Variable getVariable() { result = var }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = "Init: " + getVariable().toString() + " " + getVariable().getLocation().toString()
|
||||
result =
|
||||
"Init: " + this.getVariable().toString() + " " + this.getVariable().getLocation().toString()
|
||||
}
|
||||
|
||||
final override string getBaseString() { result = "#init:" + var.toString() + ":" }
|
||||
@@ -332,5 +333,5 @@ class IRParameter extends IRAutomaticVariable {
|
||||
* An IR variable representing a positional parameter.
|
||||
*/
|
||||
class IRPositionalParameter extends IRParameter, IRAutomaticUserVariable {
|
||||
final override int getIndex() { result = getVariable().(Language::Parameter).getIndex() }
|
||||
final override int getIndex() { result = this.getVariable().(Language::Parameter).getIndex() }
|
||||
}
|
||||
|
||||
@@ -42,6 +42,14 @@ private predicate shouldPrintFunction(Language::Declaration decl) {
|
||||
exists(PrintIRConfiguration config | config.shouldPrintFunction(decl))
|
||||
}
|
||||
|
||||
private predicate shouldPrintInstruction(Instruction i) {
|
||||
exists(IRPropertyProvider provider | provider.shouldPrintInstruction(i))
|
||||
}
|
||||
|
||||
private predicate shouldPrintOperand(Operand operand) {
|
||||
exists(IRPropertyProvider provider | provider.shouldPrintOperand(operand))
|
||||
}
|
||||
|
||||
private string getAdditionalInstructionProperty(Instruction instr, string key) {
|
||||
exists(IRPropertyProvider provider | result = provider.getInstructionProperty(instr, key))
|
||||
}
|
||||
@@ -84,7 +92,9 @@ private string getOperandPropertyString(Operand operand) {
|
||||
private newtype TPrintableIRNode =
|
||||
TPrintableIRFunction(IRFunction irFunc) { shouldPrintFunction(irFunc.getFunction()) } or
|
||||
TPrintableIRBlock(IRBlock block) { shouldPrintFunction(block.getEnclosingFunction()) } or
|
||||
TPrintableInstruction(Instruction instr) { shouldPrintFunction(instr.getEnclosingFunction()) }
|
||||
TPrintableInstruction(Instruction instr) {
|
||||
shouldPrintInstruction(instr) and shouldPrintFunction(instr.getEnclosingFunction())
|
||||
}
|
||||
|
||||
/**
|
||||
* A node to be emitted in the IR graph.
|
||||
@@ -127,13 +137,13 @@ abstract private class PrintableIRNode extends TPrintableIRNode {
|
||||
* Gets the value of the node property with the specified key.
|
||||
*/
|
||||
string getProperty(string key) {
|
||||
key = "semmle.label" and result = getLabel()
|
||||
key = "semmle.label" and result = this.getLabel()
|
||||
or
|
||||
key = "semmle.order" and result = getOrder().toString()
|
||||
key = "semmle.order" and result = this.getOrder().toString()
|
||||
or
|
||||
key = "semmle.graphKind" and result = getGraphKind()
|
||||
key = "semmle.graphKind" and result = this.getGraphKind()
|
||||
or
|
||||
key = "semmle.forceText" and forceText() and result = "true"
|
||||
key = "semmle.forceText" and this.forceText() and result = "true"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +188,7 @@ private class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
|
||||
|
||||
PrintableIRBlock() { this = TPrintableIRBlock(block) }
|
||||
|
||||
override string toString() { result = getLabel() }
|
||||
override string toString() { result = this.getLabel() }
|
||||
|
||||
override Language::Location getLocation() { result = block.getLocation() }
|
||||
|
||||
@@ -223,7 +233,7 @@ private class PrintableInstruction extends PrintableIRNode, TPrintableInstructio
|
||||
|
|
||||
resultString = instr.getResultString() and
|
||||
operationString = instr.getOperationString() and
|
||||
operandsString = getOperandsString() and
|
||||
operandsString = this.getOperandsString() and
|
||||
columnWidths(block, resultWidth, operationWidth) and
|
||||
result =
|
||||
resultString + getPaddingString(resultWidth - resultString.length()) + " = " +
|
||||
@@ -252,7 +262,8 @@ private class PrintableInstruction extends PrintableIRNode, TPrintableInstructio
|
||||
private string getOperandsString() {
|
||||
result =
|
||||
concat(Operand operand |
|
||||
operand = instr.getAnOperand()
|
||||
operand = instr.getAnOperand() and
|
||||
shouldPrintOperand(operand)
|
||||
|
|
||||
operand.getDumpString() + getOperandPropertyString(operand), ", "
|
||||
order by
|
||||
|
||||
@@ -7,17 +7,19 @@ private import internal.ValueNumberingImports
|
||||
class ValueNumber extends TValueNumber {
|
||||
final string toString() { result = "GVN" }
|
||||
|
||||
final string getDebugString() { result = strictconcat(getAnInstruction().getResultId(), ", ") }
|
||||
final string getDebugString() {
|
||||
result = strictconcat(this.getAnInstruction().getResultId(), ", ")
|
||||
}
|
||||
|
||||
final Language::Location getLocation() {
|
||||
if
|
||||
exists(Instruction i |
|
||||
i = getAnInstruction() and not i.getLocation() instanceof Language::UnknownLocation
|
||||
i = this.getAnInstruction() and not i.getLocation() instanceof Language::UnknownLocation
|
||||
)
|
||||
then
|
||||
result =
|
||||
min(Language::Location l |
|
||||
l = getAnInstruction().getLocation() and not l instanceof Language::UnknownLocation
|
||||
l = this.getAnInstruction().getLocation() and not l instanceof Language::UnknownLocation
|
||||
|
|
||||
l
|
||||
order by
|
||||
@@ -40,7 +42,7 @@ class ValueNumber extends TValueNumber {
|
||||
final Instruction getExampleInstruction() {
|
||||
result =
|
||||
min(Instruction instr |
|
||||
instr = getAnInstruction()
|
||||
instr = this.getAnInstruction()
|
||||
|
|
||||
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
|
||||
)
|
||||
|
||||
@@ -7,7 +7,7 @@ private import AliasConfigurationImports
|
||||
class Allocation extends IRAutomaticVariable {
|
||||
VariableAddressInstruction getABaseInstruction() { result.getIRVariable() = this }
|
||||
|
||||
final string getAllocationString() { result = toString() }
|
||||
final string getAllocationString() { result = this.toString() }
|
||||
|
||||
predicate alwaysEscapes() {
|
||||
// An automatic variable only escapes if its address is taken and escapes.
|
||||
|
||||
@@ -34,9 +34,13 @@ private module Cached {
|
||||
|
||||
cached
|
||||
predicate hasUnreachedInstructionCached(IRFunction irFunc) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
exists(OldIR::Instruction oldInstruction |
|
||||
irFunc = oldInstruction.getEnclosingIRFunction() and
|
||||
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _)
|
||||
(
|
||||
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _)
|
||||
or
|
||||
oldInstruction.getOpcode() instanceof Opcode::Unreached
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -366,21 +370,19 @@ private module Cached {
|
||||
then
|
||||
result = getChi(getOldInstruction(instruction)) and
|
||||
kind instanceof GotoEdge
|
||||
else (
|
||||
else
|
||||
exists(OldInstruction oldInstruction |
|
||||
oldInstruction = getOldInstruction(instruction) and
|
||||
(
|
||||
oldInstruction = getOldInstruction(instruction)
|
||||
or
|
||||
instruction = getChi(oldInstruction)
|
||||
) and
|
||||
(
|
||||
if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind)
|
||||
then result = unreachedInstruction(instruction.getEnclosingIRFunction())
|
||||
else result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(OldInstruction oldInstruction |
|
||||
instruction = getChi(oldInstruction) and
|
||||
result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
|
||||
@@ -75,7 +75,7 @@ class MemoryLocation extends TMemoryLocation {
|
||||
final predicate canReuseSsa() { canReuseSsaForVariable(var) }
|
||||
|
||||
/** DEPRECATED: Alias for canReuseSsa */
|
||||
deprecated predicate canReuseSSA() { canReuseSsa() }
|
||||
deprecated predicate canReuseSSA() { this.canReuseSsa() }
|
||||
}
|
||||
|
||||
predicate canReuseSsaForOldResult(Instruction instr) { none() }
|
||||
|
||||
@@ -7,6 +7,9 @@ predicate isInfeasibleInstructionSuccessor(Instruction instr, EdgeKind kind) {
|
||||
conditionValue = getConstantValue(instr.(ConditionalBranchInstruction).getCondition()) and
|
||||
if conditionValue = 0 then kind instanceof TrueEdge else kind instanceof FalseEdge
|
||||
)
|
||||
or
|
||||
instr.getSuccessor(kind) instanceof UnreachedInstruction and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
@@ -41,7 +44,9 @@ class ReachableBlock extends IRBlockBase {
|
||||
* An instruction that is contained in a reachable block.
|
||||
*/
|
||||
class ReachableInstruction extends Instruction {
|
||||
ReachableInstruction() { this.getBlock() instanceof ReachableBlock }
|
||||
ReachableInstruction() {
|
||||
this.getBlock() instanceof ReachableBlock and not this instanceof UnreachedInstruction
|
||||
}
|
||||
}
|
||||
|
||||
module Graph {
|
||||
|
||||
@@ -62,14 +62,14 @@ class GVN extends TValueNumber {
|
||||
|
||||
final string toString() { result = "GVN" }
|
||||
|
||||
final string getDebugString() { result = strictconcat(getAnExpr().toString(), ", ") }
|
||||
final string getDebugString() { result = strictconcat(this.getAnExpr().toString(), ", ") }
|
||||
|
||||
final Location getLocation() {
|
||||
if exists(Expr e | e = getAnExpr() and not e.getLocation() instanceof UnknownLocation)
|
||||
if exists(Expr e | e = this.getAnExpr() and not e.getLocation() instanceof UnknownLocation)
|
||||
then
|
||||
result =
|
||||
min(Location l |
|
||||
l = getAnExpr().getLocation() and not l instanceof UnknownLocation
|
||||
l = this.getAnExpr().getLocation() and not l instanceof UnknownLocation
|
||||
|
|
||||
l
|
||||
order by
|
||||
@@ -102,13 +102,13 @@ class GVN extends TValueNumber {
|
||||
}
|
||||
|
||||
/** Gets an expression that has this GVN. */
|
||||
Expr getAnExpr() { result = getAnUnconvertedExpr() }
|
||||
Expr getAnExpr() { result = this.getAnUnconvertedExpr() }
|
||||
|
||||
/** Gets an expression that has this GVN. */
|
||||
Expr getAnUnconvertedExpr() { result = getAnInstruction().getUnconvertedResultExpression() }
|
||||
Expr getAnUnconvertedExpr() { result = this.getAnInstruction().getUnconvertedResultExpression() }
|
||||
|
||||
/** Gets an expression that has this GVN. */
|
||||
Expr getAConvertedExpr() { result = getAnInstruction().getConvertedResultExpression() }
|
||||
Expr getAConvertedExpr() { result = this.getAnInstruction().getConvertedResultExpression() }
|
||||
}
|
||||
|
||||
/** Gets the global value number of expression `e`. */
|
||||
|
||||
@@ -208,10 +208,10 @@ class CppType extends TCppType {
|
||||
string toString() { none() }
|
||||
|
||||
/** Gets a string used in IR dumps */
|
||||
string getDumpString() { result = toString() }
|
||||
string getDumpString() { result = this.toString() }
|
||||
|
||||
/** Gets the size of the type in bytes, if known. */
|
||||
final int getByteSize() { result = getIRType().getByteSize() }
|
||||
final int getByteSize() { result = this.getIRType().getByteSize() }
|
||||
|
||||
/**
|
||||
* Gets the `IRType` that represents this `CppType`. Many different `CppType`s can map to a single
|
||||
@@ -232,7 +232,7 @@ class CppType extends TCppType {
|
||||
*/
|
||||
final predicate hasUnspecifiedType(Type type, boolean isGLValue) {
|
||||
exists(Type specifiedType |
|
||||
hasType(specifiedType, isGLValue) and
|
||||
this.hasType(specifiedType, isGLValue) and
|
||||
type = specifiedType.getUnspecifiedType()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -206,7 +206,34 @@ private predicate deconstructSizeExpr(Expr sizeExpr, Expr lengthExpr, int sizeof
|
||||
}
|
||||
|
||||
/** A `Function` that is a call target of an allocation. */
|
||||
private signature class CallAllocationExprTarget extends Function;
|
||||
private signature class CallAllocationExprTarget extends Function {
|
||||
/**
|
||||
* Gets the index of the input pointer argument to be reallocated, if
|
||||
* this is a `realloc` function.
|
||||
*/
|
||||
int getReallocPtrArg();
|
||||
|
||||
/**
|
||||
* Gets the index of the argument for the allocation size, if any. The actual
|
||||
* allocation size is the value of this argument multiplied by the result of
|
||||
* `getSizeMult()`, in bytes.
|
||||
*/
|
||||
int getSizeArg();
|
||||
|
||||
/**
|
||||
* Gets the index of an argument that multiplies the allocation size given
|
||||
* by `getSizeArg`, if any.
|
||||
*/
|
||||
int getSizeMult();
|
||||
|
||||
/**
|
||||
* Holds if this allocation requires a
|
||||
* corresponding deallocation of some sort (most do, but `alloca` for example
|
||||
* does not). If it is unclear, we default to no (for example a placement `new`
|
||||
* allocation may or may not require a corresponding `delete`).
|
||||
*/
|
||||
predicate requiresDealloc();
|
||||
}
|
||||
|
||||
/**
|
||||
* This module abstracts over the type of allocation call-targets and provides a
|
||||
@@ -220,118 +247,68 @@ private signature class CallAllocationExprTarget extends Function;
|
||||
* function using various heuristics.
|
||||
*/
|
||||
private module CallAllocationExprBase<CallAllocationExprTarget Target> {
|
||||
/** A module that contains the collection of member-predicates required on `Target`. */
|
||||
signature module Param {
|
||||
/**
|
||||
* Gets the index of the input pointer argument to be reallocated, if
|
||||
* this is a `realloc` function.
|
||||
*/
|
||||
int getReallocPtrArg(Target target);
|
||||
|
||||
/**
|
||||
* Gets the index of the argument for the allocation size, if any. The actual
|
||||
* allocation size is the value of this argument multiplied by the result of
|
||||
* `getSizeMult()`, in bytes.
|
||||
*/
|
||||
int getSizeArg(Target target);
|
||||
|
||||
/**
|
||||
* Gets the index of an argument that multiplies the allocation size given
|
||||
* by `getSizeArg`, if any.
|
||||
*/
|
||||
int getSizeMult(Target target);
|
||||
|
||||
/**
|
||||
* Holds if this allocation requires a
|
||||
* corresponding deallocation of some sort (most do, but `alloca` for example
|
||||
* does not). If it is unclear, we default to no (for example a placement `new`
|
||||
* allocation may or may not require a corresponding `delete`).
|
||||
*/
|
||||
predicate requiresDealloc(Target target);
|
||||
}
|
||||
|
||||
/**
|
||||
* A module that abstracts over a collection of predicates in
|
||||
* the `Param` module). This should really be member-predicates
|
||||
* on `CallAllocationExprTarget`, but we cannot yet write this in QL.
|
||||
* An allocation expression that is a function call, such as call to `malloc`.
|
||||
*/
|
||||
module With<Param P> {
|
||||
private import P
|
||||
class CallAllocationExprImpl instanceof FunctionCall {
|
||||
Target target;
|
||||
|
||||
/**
|
||||
* An allocation expression that is a function call, such as call to `malloc`.
|
||||
*/
|
||||
class CallAllocationExprImpl instanceof FunctionCall {
|
||||
Target target;
|
||||
|
||||
CallAllocationExprImpl() {
|
||||
target = this.getTarget() and
|
||||
// realloc(ptr, 0) only frees the pointer
|
||||
not (
|
||||
exists(getReallocPtrArg(target)) and
|
||||
this.getArgument(getSizeArg(target)).getValue().toInt() = 0
|
||||
) and
|
||||
// these are modeled directly (and more accurately), avoid duplication
|
||||
not exists(NewOrNewArrayExpr new | new.getAllocatorCall() = this)
|
||||
}
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
Expr getSizeExprImpl() {
|
||||
exists(Expr sizeExpr | sizeExpr = super.getArgument(getSizeArg(target)) |
|
||||
if exists(getSizeMult(target))
|
||||
then result = sizeExpr
|
||||
else
|
||||
exists(Expr lengthExpr |
|
||||
deconstructSizeExpr(sizeExpr, lengthExpr, _) and
|
||||
result = lengthExpr
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
int getSizeMultImpl() {
|
||||
// malloc with multiplier argument that is a constant
|
||||
result = super.getArgument(getSizeMult(target)).getValue().toInt()
|
||||
or
|
||||
// malloc with no multiplier argument
|
||||
not exists(getSizeMult(target)) and
|
||||
deconstructSizeExpr(super.getArgument(getSizeArg(target)), _, result)
|
||||
}
|
||||
|
||||
int getSizeBytesImpl() {
|
||||
result = this.getSizeExprImpl().getValue().toInt() * this.getSizeMultImpl()
|
||||
}
|
||||
|
||||
Expr getReallocPtrImpl() { result = super.getArgument(getReallocPtrArg(target)) }
|
||||
|
||||
Type getAllocatedElementTypeImpl() {
|
||||
result =
|
||||
super.getFullyConverted().getType().stripTopLevelSpecifiers().(PointerType).getBaseType() and
|
||||
not result instanceof VoidType
|
||||
}
|
||||
|
||||
predicate requiresDeallocImpl() { requiresDealloc(target) }
|
||||
CallAllocationExprImpl() {
|
||||
target = this.getTarget() and
|
||||
// realloc(ptr, 0) only frees the pointer
|
||||
not (
|
||||
exists(target.getReallocPtrArg()) and
|
||||
this.getArgument(target.getSizeArg()).getValue().toInt() = 0
|
||||
) and
|
||||
// these are modeled directly (and more accurately), avoid duplication
|
||||
not exists(NewOrNewArrayExpr new | new.getAllocatorCall() = this)
|
||||
}
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
Expr getSizeExprImpl() {
|
||||
exists(Expr sizeExpr | sizeExpr = super.getArgument(target.getSizeArg()) |
|
||||
if exists(target.getSizeMult())
|
||||
then result = sizeExpr
|
||||
else
|
||||
exists(Expr lengthExpr |
|
||||
deconstructSizeExpr(sizeExpr, lengthExpr, _) and
|
||||
result = lengthExpr
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
int getSizeMultImpl() {
|
||||
// malloc with multiplier argument that is a constant
|
||||
result = super.getArgument(target.getSizeMult()).getValue().toInt()
|
||||
or
|
||||
// malloc with no multiplier argument
|
||||
not exists(target.getSizeMult()) and
|
||||
deconstructSizeExpr(super.getArgument(target.getSizeArg()), _, result)
|
||||
}
|
||||
|
||||
int getSizeBytesImpl() {
|
||||
result = this.getSizeExprImpl().getValue().toInt() * this.getSizeMultImpl()
|
||||
}
|
||||
|
||||
Expr getReallocPtrImpl() { result = super.getArgument(target.getReallocPtrArg()) }
|
||||
|
||||
Type getAllocatedElementTypeImpl() {
|
||||
result =
|
||||
super.getFullyConverted().getType().stripTopLevelSpecifiers().(PointerType).getBaseType() and
|
||||
not result instanceof VoidType
|
||||
}
|
||||
|
||||
predicate requiresDeallocImpl() { target.requiresDealloc() }
|
||||
}
|
||||
}
|
||||
|
||||
private module CallAllocationExpr {
|
||||
private module Param implements CallAllocationExprBase<AllocationFunction>::Param {
|
||||
int getReallocPtrArg(AllocationFunction f) { result = f.getReallocPtrArg() }
|
||||
|
||||
int getSizeArg(AllocationFunction f) { result = f.getSizeArg() }
|
||||
|
||||
int getSizeMult(AllocationFunction f) { result = f.getSizeMult() }
|
||||
|
||||
predicate requiresDealloc(AllocationFunction f) { f.requiresDealloc() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A class that provides the implementation of `AllocationExpr` for an allocation
|
||||
* that calls an `AllocationFunction`.
|
||||
*/
|
||||
private class Base =
|
||||
CallAllocationExprBase<AllocationFunction>::With<Param>::CallAllocationExprImpl;
|
||||
private class Base = CallAllocationExprBase<AllocationFunction>::CallAllocationExprImpl;
|
||||
|
||||
class CallAllocationExpr extends AllocationExpr, Base {
|
||||
override Expr getSizeExpr() { result = super.getSizeExprImpl() }
|
||||
@@ -437,7 +414,7 @@ private module HeuristicAllocation {
|
||||
int sizeArg;
|
||||
|
||||
HeuristicAllocationFunctionByName() {
|
||||
Function.super.getName().matches("%alloc%") and
|
||||
Function.super.getName().matches(["%alloc%", "%Alloc%"]) and
|
||||
Function.super.getUnspecifiedType() instanceof PointerType and
|
||||
sizeArg = unique( | | getAnUnsignedParameter(this))
|
||||
}
|
||||
@@ -452,22 +429,11 @@ private module HeuristicAllocation {
|
||||
override predicate requiresDealloc() { none() }
|
||||
}
|
||||
|
||||
private module Param implements CallAllocationExprBase<HeuristicAllocationFunction>::Param {
|
||||
int getReallocPtrArg(HeuristicAllocationFunction f) { result = f.getReallocPtrArg() }
|
||||
|
||||
int getSizeArg(HeuristicAllocationFunction f) { result = f.getSizeArg() }
|
||||
|
||||
int getSizeMult(HeuristicAllocationFunction f) { result = f.getSizeMult() }
|
||||
|
||||
predicate requiresDealloc(HeuristicAllocationFunction f) { f.requiresDealloc() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A class that provides the implementation of `AllocationExpr` for an allocation
|
||||
* that calls an `HeuristicAllocationFunction`.
|
||||
*/
|
||||
private class Base =
|
||||
CallAllocationExprBase<HeuristicAllocationFunction>::With<Param>::CallAllocationExprImpl;
|
||||
private class Base = CallAllocationExprBase<HeuristicAllocationFunction>::CallAllocationExprImpl;
|
||||
|
||||
private class CallAllocationExpr extends HeuristicAllocationExpr, Base {
|
||||
override Expr getSizeExpr() { result = super.getSizeExprImpl() }
|
||||
|
||||
@@ -13,19 +13,19 @@ private class StandardDeallocationFunction extends DeallocationFunction {
|
||||
int freedArg;
|
||||
|
||||
StandardDeallocationFunction() {
|
||||
hasGlobalOrStdOrBslName([
|
||||
this.hasGlobalOrStdOrBslName([
|
||||
// --- C library allocation
|
||||
"free", "realloc"
|
||||
]) and
|
||||
freedArg = 0
|
||||
or
|
||||
hasGlobalName([
|
||||
this.hasGlobalName([
|
||||
// --- OpenSSL memory allocation
|
||||
"CRYPTO_free", "CRYPTO_secure_free"
|
||||
]) and
|
||||
freedArg = 0
|
||||
or
|
||||
hasGlobalOrStdName([
|
||||
this.hasGlobalOrStdName([
|
||||
// --- Windows Memory Management for Windows Drivers
|
||||
"ExFreePoolWithTag", "ExDeleteTimer", "IoFreeMdl", "IoFreeWorkItem", "IoFreeErrorLogEntry",
|
||||
"MmFreeContiguousMemory", "MmFreeContiguousMemorySpecifyCache", "MmFreeNonCachedMemory",
|
||||
@@ -44,7 +44,7 @@ private class StandardDeallocationFunction extends DeallocationFunction {
|
||||
]) and
|
||||
freedArg = 0
|
||||
or
|
||||
hasGlobalOrStdName([
|
||||
this.hasGlobalOrStdName([
|
||||
// --- Windows Memory Management for Windows Drivers
|
||||
"ExFreeToLookasideListEx", "ExFreeToPagedLookasideList", "ExFreeToNPagedLookasideList",
|
||||
// --- NetBSD pool manager
|
||||
@@ -52,7 +52,7 @@ private class StandardDeallocationFunction extends DeallocationFunction {
|
||||
]) and
|
||||
freedArg = 1
|
||||
or
|
||||
hasGlobalOrStdName(["HeapFree", "HeapReAlloc"]) and
|
||||
this.hasGlobalOrStdName(["HeapFree", "HeapReAlloc"]) and
|
||||
freedArg = 2
|
||||
}
|
||||
|
||||
@@ -65,9 +65,9 @@ private class StandardDeallocationFunction extends DeallocationFunction {
|
||||
private class CallDeallocationExpr extends DeallocationExpr, FunctionCall {
|
||||
DeallocationFunction target;
|
||||
|
||||
CallDeallocationExpr() { target = getTarget() }
|
||||
CallDeallocationExpr() { target = this.getTarget() }
|
||||
|
||||
override Expr getFreedExpr() { result = getArgument(target.getFreedArg()) }
|
||||
override Expr getFreedExpr() { result = this.getArgument(target.getFreedArg()) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,7 +76,7 @@ private class CallDeallocationExpr extends DeallocationExpr, FunctionCall {
|
||||
private class DeleteDeallocationExpr extends DeallocationExpr, DeleteExpr {
|
||||
DeleteDeallocationExpr() { this instanceof DeleteExpr }
|
||||
|
||||
override Expr getFreedExpr() { result = getExpr() }
|
||||
override Expr getFreedExpr() { result = this.getExpr() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,5 +85,5 @@ private class DeleteDeallocationExpr extends DeallocationExpr, DeleteExpr {
|
||||
private class DeleteArrayDeallocationExpr extends DeallocationExpr, DeleteArrayExpr {
|
||||
DeleteArrayDeallocationExpr() { this instanceof DeleteArrayExpr }
|
||||
|
||||
override Expr getFreedExpr() { result = getExpr() }
|
||||
override Expr getFreedExpr() { result = this.getExpr() }
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@ import semmle.code.cpp.models.interfaces.Taint
|
||||
*/
|
||||
private class ConversionConstructorModel extends Constructor, TaintFunction {
|
||||
ConversionConstructorModel() {
|
||||
strictcount(Parameter p | p = getAParameter() and not p.hasInitializer()) = 1 and
|
||||
not hasSpecifier("explicit")
|
||||
strictcount(Parameter p | p = this.getAParameter() and not p.hasInitializer()) = 1 and
|
||||
not this.hasSpecifier("explicit")
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
|
||||
@@ -15,10 +15,10 @@ private class Printf extends FormattingFunction, AliasFunction {
|
||||
Printf() {
|
||||
this instanceof TopLevelFunction and
|
||||
(
|
||||
hasGlobalOrStdOrBslName(["printf", "wprintf"]) or
|
||||
hasGlobalName(["printf_s", "wprintf_s", "g_printf"])
|
||||
this.hasGlobalOrStdOrBslName(["printf", "wprintf"]) or
|
||||
this.hasGlobalName(["printf_s", "wprintf_s", "g_printf"])
|
||||
) and
|
||||
not exists(getDefinition().getFile().getRelativePath())
|
||||
not exists(this.getDefinition().getFile().getRelativePath())
|
||||
}
|
||||
|
||||
override int getFormatParameterIndex() { result = 0 }
|
||||
@@ -39,10 +39,10 @@ private class Fprintf extends FormattingFunction {
|
||||
Fprintf() {
|
||||
this instanceof TopLevelFunction and
|
||||
(
|
||||
hasGlobalOrStdOrBslName(["fprintf", "fwprintf"]) or
|
||||
hasGlobalName("g_fprintf")
|
||||
this.hasGlobalOrStdOrBslName(["fprintf", "fwprintf"]) or
|
||||
this.hasGlobalName("g_fprintf")
|
||||
) and
|
||||
not exists(getDefinition().getFile().getRelativePath())
|
||||
not exists(this.getDefinition().getFile().getRelativePath())
|
||||
}
|
||||
|
||||
override int getFormatParameterIndex() { result = 1 }
|
||||
@@ -57,12 +57,12 @@ private class Sprintf extends FormattingFunction {
|
||||
Sprintf() {
|
||||
this instanceof TopLevelFunction and
|
||||
(
|
||||
hasGlobalOrStdOrBslName([
|
||||
this.hasGlobalOrStdOrBslName([
|
||||
"sprintf", // sprintf(dst, format, args...)
|
||||
"wsprintf" // wsprintf(dst, format, args...)
|
||||
])
|
||||
or
|
||||
hasGlobalName([
|
||||
this.hasGlobalName([
|
||||
"_sprintf_l", // _sprintf_l(dst, format, locale, args...)
|
||||
"__swprintf_l", // __swprintf_l(dst, format, locale, args...)
|
||||
"g_strdup_printf", // g_strdup_printf(format, ...)
|
||||
@@ -70,24 +70,26 @@ private class Sprintf extends FormattingFunction {
|
||||
"__builtin___sprintf_chk" // __builtin___sprintf_chk(dst, flag, os, format, ...)
|
||||
])
|
||||
) and
|
||||
not exists(getDefinition().getFile().getRelativePath())
|
||||
not exists(this.getDefinition().getFile().getRelativePath())
|
||||
}
|
||||
|
||||
override int getFormatParameterIndex() {
|
||||
hasName("g_strdup_printf") and result = 0
|
||||
this.hasName("g_strdup_printf") and result = 0
|
||||
or
|
||||
hasName("__builtin___sprintf_chk") and result = 3
|
||||
this.hasName("__builtin___sprintf_chk") and result = 3
|
||||
or
|
||||
not getName() = ["g_strdup_printf", "__builtin___sprintf_chk"] and
|
||||
not this.getName() = ["g_strdup_printf", "__builtin___sprintf_chk"] and
|
||||
result = 1
|
||||
}
|
||||
|
||||
override int getOutputParameterIndex(boolean isStream) {
|
||||
not hasName("g_strdup_printf") and result = 0 and isStream = false
|
||||
not this.hasName("g_strdup_printf") and result = 0 and isStream = false
|
||||
}
|
||||
|
||||
override int getFirstFormatArgumentIndex() {
|
||||
if hasName("__builtin___sprintf_chk") then result = 4 else result = getNumberOfParameters()
|
||||
if this.hasName("__builtin___sprintf_chk")
|
||||
then result = 4
|
||||
else result = this.getNumberOfParameters()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,46 +100,46 @@ private class SnprintfImpl extends Snprintf {
|
||||
SnprintfImpl() {
|
||||
this instanceof TopLevelFunction and
|
||||
(
|
||||
hasGlobalOrStdOrBslName([
|
||||
this.hasGlobalOrStdOrBslName([
|
||||
"snprintf", // C99 defines snprintf
|
||||
"swprintf" // The s version of wide-char printf is also always the n version
|
||||
])
|
||||
or
|
||||
// Microsoft has _snprintf as well as several other variations
|
||||
hasGlobalName([
|
||||
this.hasGlobalName([
|
||||
"sprintf_s", "snprintf_s", "swprintf_s", "_snprintf", "_snprintf_s", "_snprintf_l",
|
||||
"_snprintf_s_l", "_snwprintf", "_snwprintf_s", "_snwprintf_l", "_snwprintf_s_l",
|
||||
"_sprintf_s_l", "_swprintf_l", "_swprintf_s_l", "g_snprintf", "wnsprintf",
|
||||
"__builtin___snprintf_chk"
|
||||
])
|
||||
) and
|
||||
not exists(getDefinition().getFile().getRelativePath())
|
||||
not exists(this.getDefinition().getFile().getRelativePath())
|
||||
}
|
||||
|
||||
override int getFormatParameterIndex() {
|
||||
if getName().matches("%\\_l")
|
||||
then result = getFirstFormatArgumentIndex() - 2
|
||||
else result = getFirstFormatArgumentIndex() - 1
|
||||
if this.getName().matches("%\\_l")
|
||||
then result = this.getFirstFormatArgumentIndex() - 2
|
||||
else result = this.getFirstFormatArgumentIndex() - 1
|
||||
}
|
||||
|
||||
override int getOutputParameterIndex(boolean isStream) { result = 0 and isStream = false }
|
||||
|
||||
override int getFirstFormatArgumentIndex() {
|
||||
exists(string name |
|
||||
name = getQualifiedName() and
|
||||
name = this.getQualifiedName() and
|
||||
(
|
||||
name = "__builtin___snprintf_chk" and
|
||||
result = 5
|
||||
or
|
||||
name != "__builtin___snprintf_chk" and
|
||||
result = getNumberOfParameters()
|
||||
result = this.getNumberOfParameters()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate returnsFullFormatLength() {
|
||||
hasName(["snprintf", "g_snprintf", "__builtin___snprintf_chk", "snprintf_s"]) and
|
||||
not exists(getDefinition().getFile().getRelativePath())
|
||||
this.hasName(["snprintf", "g_snprintf", "__builtin___snprintf_chk", "snprintf_s"]) and
|
||||
not exists(this.getDefinition().getFile().getRelativePath())
|
||||
}
|
||||
|
||||
override int getSizeParameterIndex() { result = 1 }
|
||||
@@ -149,15 +151,15 @@ private class SnprintfImpl extends Snprintf {
|
||||
private class StringCchPrintf extends FormattingFunction {
|
||||
StringCchPrintf() {
|
||||
this instanceof TopLevelFunction and
|
||||
hasGlobalName([
|
||||
this.hasGlobalName([
|
||||
"StringCchPrintf", "StringCchPrintfEx", "StringCchPrintf_l", "StringCchPrintf_lEx",
|
||||
"StringCbPrintf", "StringCbPrintfEx", "StringCbPrintf_l", "StringCbPrintf_lEx"
|
||||
]) and
|
||||
not exists(getDefinition().getFile().getRelativePath())
|
||||
not exists(this.getDefinition().getFile().getRelativePath())
|
||||
}
|
||||
|
||||
override int getFormatParameterIndex() {
|
||||
if getName().matches("%Ex") then result = 5 else result = 2
|
||||
if this.getName().matches("%Ex") then result = 5 else result = 2
|
||||
}
|
||||
|
||||
override int getOutputParameterIndex(boolean isStream) { result = 0 and isStream = false }
|
||||
@@ -171,8 +173,8 @@ private class StringCchPrintf extends FormattingFunction {
|
||||
private class Syslog extends FormattingFunction {
|
||||
Syslog() {
|
||||
this instanceof TopLevelFunction and
|
||||
hasGlobalName("syslog") and
|
||||
not exists(getDefinition().getFile().getRelativePath())
|
||||
this.hasGlobalName("syslog") and
|
||||
not exists(this.getDefinition().getFile().getRelativePath())
|
||||
}
|
||||
|
||||
override int getFormatParameterIndex() { result = 1 }
|
||||
|
||||
@@ -13,7 +13,7 @@ import semmle.code.cpp.models.interfaces.Taint
|
||||
*/
|
||||
private class StrdupFunction extends AllocationFunction, ArrayFunction, DataFlowFunction {
|
||||
StrdupFunction() {
|
||||
hasGlobalName([
|
||||
this.hasGlobalName([
|
||||
// --- C library allocation
|
||||
"strdup", // strdup(str)
|
||||
"strdupa", // strdupa(str) - returns stack allocated buffer
|
||||
@@ -33,7 +33,7 @@ private class StrdupFunction extends AllocationFunction, ArrayFunction, DataFlow
|
||||
output.isReturnValueDeref()
|
||||
}
|
||||
|
||||
override predicate requiresDealloc() { not hasGlobalName("strdupa") }
|
||||
override predicate requiresDealloc() { not this.hasGlobalName("strdupa") }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -41,7 +41,7 @@ private class StrdupFunction extends AllocationFunction, ArrayFunction, DataFlow
|
||||
*/
|
||||
private class StrndupFunction extends AllocationFunction, ArrayFunction, DataFlowFunction {
|
||||
StrndupFunction() {
|
||||
hasGlobalName([
|
||||
this.hasGlobalName([
|
||||
// -- C library allocation
|
||||
"strndup", // strndup(str, maxlen)
|
||||
"strndupa" // strndupa(str, maxlen) -- returns stack allocated buffer
|
||||
@@ -60,5 +60,5 @@ private class StrndupFunction extends AllocationFunction, ArrayFunction, DataFlo
|
||||
output.isReturnValueDeref()
|
||||
}
|
||||
|
||||
override predicate requiresDealloc() { not hasGlobalName("strndupa") }
|
||||
override predicate requiresDealloc() { not this.hasGlobalName("strndupa") }
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import semmle.code.cpp.models.interfaces.Taint
|
||||
import semmle.code.cpp.models.interfaces.ArrayFunction
|
||||
|
||||
private class Strftime extends TaintFunction, ArrayFunction {
|
||||
Strftime() { hasGlobalName("strftime") }
|
||||
Strftime() { this.hasGlobalName("strftime") }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
(
|
||||
|
||||
@@ -16,7 +16,7 @@ private class StrsetFunction extends ArrayFunction, DataFlowFunction, AliasFunct
|
||||
SideEffectFunction
|
||||
{
|
||||
StrsetFunction() {
|
||||
hasGlobalName([
|
||||
this.hasGlobalName([
|
||||
"strset", "_strset", "_strset_l", "_wcsset", "_wcsset_l", "_mbsset", "_mbsset_l",
|
||||
"_mbsnbset", "_mbsnbset_l", "_strnset", "_strnset_l", "_wcsnset", "_wcsnset_l", "_mbsnset",
|
||||
"_mbsnset_l"
|
||||
|
||||
@@ -10,12 +10,12 @@ private class SystemFunction extends CommandExecutionFunction, ArrayFunction, Al
|
||||
SideEffectFunction
|
||||
{
|
||||
SystemFunction() {
|
||||
hasGlobalOrStdName("system") or // system(command)
|
||||
hasGlobalName("popen") or // popen(command, mode)
|
||||
this.hasGlobalOrStdName("system") or // system(command)
|
||||
this.hasGlobalName("popen") or // popen(command, mode)
|
||||
// Windows variants
|
||||
hasGlobalName("_popen") or // _popen(command, mode)
|
||||
hasGlobalName("_wpopen") or // _wpopen(command, mode)
|
||||
hasGlobalName("_wsystem") // _wsystem(command)
|
||||
this.hasGlobalName("_popen") or // _popen(command, mode)
|
||||
this.hasGlobalName("_wpopen") or // _wpopen(command, mode)
|
||||
this.hasGlobalName("_wsystem") // _wsystem(command)
|
||||
}
|
||||
|
||||
override predicate hasCommandArgument(FunctionInput input) { input.isParameterDeref(0) }
|
||||
@@ -33,8 +33,8 @@ private class SystemFunction extends CommandExecutionFunction, ArrayFunction, Al
|
||||
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||
|
||||
override predicate hasOnlySpecificWriteSideEffects() {
|
||||
hasGlobalOrStdName("system") or
|
||||
hasGlobalName("_wsystem")
|
||||
this.hasGlobalOrStdName("system") or
|
||||
this.hasGlobalName("_wsystem")
|
||||
}
|
||||
|
||||
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||
|
||||
@@ -96,7 +96,7 @@ abstract class AllocationFunction extends Function {
|
||||
*/
|
||||
class OperatorNewAllocationFunction extends AllocationFunction {
|
||||
OperatorNewAllocationFunction() {
|
||||
hasGlobalName([
|
||||
this.hasGlobalName([
|
||||
"operator new", // operator new(bytes, ...)
|
||||
"operator new[]" // operator new[](bytes, ...)
|
||||
])
|
||||
@@ -104,15 +104,15 @@ class OperatorNewAllocationFunction extends AllocationFunction {
|
||||
|
||||
override int getSizeArg() { result = 0 }
|
||||
|
||||
override predicate requiresDealloc() { not exists(getPlacementArgument()) }
|
||||
override predicate requiresDealloc() { not exists(this.getPlacementArgument()) }
|
||||
|
||||
/**
|
||||
* Gets the position of the placement pointer if this is a placement
|
||||
* `operator new` function.
|
||||
*/
|
||||
int getPlacementArgument() {
|
||||
getNumberOfParameters() = 2 and
|
||||
getParameter(1).getType() instanceof VoidPointerType and
|
||||
this.getNumberOfParameters() = 2 and
|
||||
this.getParameter(1).getType() instanceof VoidPointerType and
|
||||
result = 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ abstract class DeallocationFunction extends Function {
|
||||
*/
|
||||
class OperatorDeleteDeallocationFunction extends DeallocationFunction {
|
||||
OperatorDeleteDeallocationFunction() {
|
||||
hasGlobalName([
|
||||
this.hasGlobalName([
|
||||
"operator delete", // operator delete(pointer, ...)
|
||||
"operator delete[]" // operator delete[](pointer, ...)
|
||||
])
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user