mirror of
https://github.com/github/codeql.git
synced 2026-04-27 09:45:15 +02:00
Merge branch 'python-UBV' of https://github.com/sim4n6/codeql-pun into python-UBV
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
|
||||
|
||||
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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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.
|
||||
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.
|
||||
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
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplCommon
|
||||
private import codeql.util.Unit
|
||||
|
||||
module ProductFlow {
|
||||
@@ -287,9 +290,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 +322,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 +418,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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
)
|
||||
@@ -998,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
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
@@ -127,13 +127,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 +178,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 +223,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()) + " = " +
|
||||
|
||||
@@ -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
|
||||
) {
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
@@ -127,13 +127,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 +178,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 +223,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()) + " = " +
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
@@ -127,13 +127,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 +178,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 +223,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()) + " = " +
|
||||
|
||||
@@ -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, ...)
|
||||
])
|
||||
|
||||
@@ -57,7 +57,7 @@ abstract class FormattingFunction extends ArrayFunction, TaintFunction {
|
||||
*/
|
||||
Type getFormatCharType() {
|
||||
result =
|
||||
stripTopLevelSpecifiersOnly(stripTopLevelSpecifiersOnly(getParameter(getFormatParameterIndex())
|
||||
stripTopLevelSpecifiersOnly(stripTopLevelSpecifiersOnly(this.getParameter(this.getFormatParameterIndex())
|
||||
.getType()
|
||||
.getUnderlyingType()).(PointerType).getBaseType())
|
||||
}
|
||||
@@ -67,10 +67,10 @@ abstract class FormattingFunction extends ArrayFunction, TaintFunction {
|
||||
* `char` or `wchar_t`.
|
||||
*/
|
||||
Type getDefaultCharType() {
|
||||
isMicrosoft() and
|
||||
result = getFormatCharType()
|
||||
this.isMicrosoft() and
|
||||
result = this.getFormatCharType()
|
||||
or
|
||||
not isMicrosoft() and
|
||||
not this.isMicrosoft() and
|
||||
result instanceof PlainCharType
|
||||
}
|
||||
|
||||
@@ -80,10 +80,10 @@ abstract class FormattingFunction extends ArrayFunction, TaintFunction {
|
||||
* which is correct for a particular function.
|
||||
*/
|
||||
Type getNonDefaultCharType() {
|
||||
getDefaultCharType().getSize() = 1 and
|
||||
result = getWideCharType()
|
||||
this.getDefaultCharType().getSize() = 1 and
|
||||
result = this.getWideCharType()
|
||||
or
|
||||
not getDefaultCharType().getSize() = 1 and
|
||||
not this.getDefaultCharType().getSize() = 1 and
|
||||
result instanceof PlainCharType
|
||||
}
|
||||
|
||||
@@ -94,10 +94,10 @@ abstract class FormattingFunction extends ArrayFunction, TaintFunction {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
Type getWideCharType() {
|
||||
result = getFormatCharType() and
|
||||
result = this.getFormatCharType() and
|
||||
result.getSize() > 1
|
||||
or
|
||||
not getFormatCharType().getSize() > 1 and
|
||||
not this.getFormatCharType().getSize() > 1 and
|
||||
result = getAFormatterWideTypeOrDefault() // may have more than one result
|
||||
}
|
||||
|
||||
@@ -120,14 +120,14 @@ abstract class FormattingFunction extends ArrayFunction, TaintFunction {
|
||||
* the first format specifier in the format string.
|
||||
*/
|
||||
int getFirstFormatArgumentIndex() {
|
||||
result = getNumberOfParameters() and
|
||||
result = this.getNumberOfParameters() and
|
||||
// the formatting function either has a definition in the snapshot, or all
|
||||
// `DeclarationEntry`s agree on the number of parameters (otherwise we don't
|
||||
// really know the correct number)
|
||||
(
|
||||
hasDefinition()
|
||||
this.hasDefinition()
|
||||
or
|
||||
forall(FunctionDeclarationEntry fde | fde = getADeclarationEntry() |
|
||||
forall(FunctionDeclarationEntry fde | fde = this.getADeclarationEntry() |
|
||||
result = fde.getNumberOfParameters()
|
||||
)
|
||||
)
|
||||
@@ -139,30 +139,30 @@ abstract class FormattingFunction extends ArrayFunction, TaintFunction {
|
||||
int getSizeParameterIndex() { none() }
|
||||
|
||||
override predicate hasArrayWithNullTerminator(int bufParam) {
|
||||
bufParam = getFormatParameterIndex()
|
||||
bufParam = this.getFormatParameterIndex()
|
||||
}
|
||||
|
||||
override predicate hasArrayWithVariableSize(int bufParam, int countParam) {
|
||||
bufParam = getOutputParameterIndex(false) and
|
||||
countParam = getSizeParameterIndex()
|
||||
bufParam = this.getOutputParameterIndex(false) and
|
||||
countParam = this.getSizeParameterIndex()
|
||||
}
|
||||
|
||||
override predicate hasArrayWithUnknownSize(int bufParam) {
|
||||
bufParam = getOutputParameterIndex(false) and
|
||||
not exists(getSizeParameterIndex())
|
||||
bufParam = this.getOutputParameterIndex(false) and
|
||||
not exists(this.getSizeParameterIndex())
|
||||
}
|
||||
|
||||
override predicate hasArrayInput(int bufParam) { bufParam = getFormatParameterIndex() }
|
||||
override predicate hasArrayInput(int bufParam) { bufParam = this.getFormatParameterIndex() }
|
||||
|
||||
override predicate hasArrayOutput(int bufParam) { bufParam = getOutputParameterIndex(false) }
|
||||
override predicate hasArrayOutput(int bufParam) { bufParam = this.getOutputParameterIndex(false) }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
exists(int arg |
|
||||
arg = getFormatParameterIndex() or
|
||||
arg >= getFirstFormatArgumentIndex()
|
||||
arg = this.getFormatParameterIndex() or
|
||||
arg >= this.getFirstFormatArgumentIndex()
|
||||
|
|
||||
(input.isParameterDeref(arg) or input.isParameter(arg)) and
|
||||
output.isParameterDeref(getOutputParameterIndex(_))
|
||||
output.isParameterDeref(this.getOutputParameterIndex(_))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
113
cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/RangeAnalysis.qll
Normal file
113
cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/RangeAnalysis.qll
Normal file
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
* Provides an AST-based interface to the relative range analysis, which tracks bounds of the form
|
||||
* `a <= b + delta` for expressions `a` and `b` and an integer offset `delta`.
|
||||
*/
|
||||
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysis
|
||||
private import cpp
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.controlflow.IRGuards
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExpr
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExprSpecific
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.Bound as IRBound
|
||||
private import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
|
||||
/**
|
||||
* Holds if e is bounded by `b + delta`. The bound is an upper bound if
|
||||
* `upper` is true, and can be traced back to a guard represented by `reason`.
|
||||
*/
|
||||
predicate bounded(Expr e, Bound b, float delta, boolean upper, Reason reason) {
|
||||
exists(SemanticExprConfig::Expr semExpr |
|
||||
semExpr.getUnconverted().getUnconvertedResultExpression() = e
|
||||
|
|
||||
semBounded(semExpr, b, delta, upper, reason)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if e is bounded by `b + delta`. The bound is an upper bound if
|
||||
* `upper` is true, and can be traced back to a guard represented by `reason`.
|
||||
* The `Expr` may be a conversion.
|
||||
*/
|
||||
predicate convertedBounded(Expr e, Bound b, float delta, boolean upper, Reason reason) {
|
||||
exists(SemanticExprConfig::Expr semExpr |
|
||||
semExpr.getConverted().getConvertedResultExpression() = e
|
||||
|
|
||||
semBounded(semExpr, b, delta, upper, reason)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A reason for an inferred bound. This can either be `CondReason` if the bound
|
||||
* is due to a specific condition, or `NoReason` if the bound is inferred
|
||||
* without going through a bounding condition.
|
||||
*/
|
||||
class Reason instanceof SemReason {
|
||||
/** Gets a string representation of this reason */
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A reason for an inferred bound that indicates that the bound is inferred
|
||||
* without going through a bounding condition.
|
||||
*/
|
||||
class NoReason extends Reason instanceof SemNoReason {
|
||||
override string toString() { result = "NoReason" }
|
||||
}
|
||||
|
||||
/** A reason for an inferred bound pointing to a condition. */
|
||||
class CondReason extends Reason instanceof SemCondReason {
|
||||
override string toString() { result = SemCondReason.super.toString() }
|
||||
|
||||
/** Gets the guard condition that caused the inferred bound */
|
||||
GuardCondition getCond() {
|
||||
result = super.getCond().(IRGuardCondition).getUnconvertedResultExpression()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A bound that may be inferred for an expression plus/minus an integer delta.
|
||||
*/
|
||||
class Bound instanceof IRBound::Bound {
|
||||
/** Gets a string representation of this bound. */
|
||||
string toString() { none() }
|
||||
|
||||
/** Gets an expression that equals this bound. */
|
||||
Expr getAnExpr() { none() }
|
||||
|
||||
/** Gets an expression that equals this bound plus `delta`. */
|
||||
Expr getAnExpr(int delta) { none() }
|
||||
|
||||
/** Gets a representative locaiton for this bound */
|
||||
Location getLocation() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The bound that corresponds to the integer 0. This is used to represent all
|
||||
* integer bounds as bounds are always accompanied by an added integer delta.
|
||||
*/
|
||||
class ZeroBound extends Bound instanceof IRBound::ZeroBound {
|
||||
override string toString() { result = "0" }
|
||||
|
||||
override Expr getAnExpr(int delta) {
|
||||
result = super.getInstruction(delta).getUnconvertedResultExpression()
|
||||
}
|
||||
|
||||
override Location getLocation() { result instanceof UnknownDefaultLocation }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bound corresponding to the value of an `Instruction`.
|
||||
*/
|
||||
class ValueNumberBound extends Bound instanceof IRBound::ValueNumberBound {
|
||||
override string toString() { result = "ValueNumberBound" }
|
||||
|
||||
override Expr getAnExpr(int delta) {
|
||||
result = super.getInstruction(delta).getUnconvertedResultExpression()
|
||||
}
|
||||
|
||||
override Location getLocation() { result = IRBound::ValueNumberBound.super.getLocation() }
|
||||
|
||||
/** Gets the value number that equals this bound. */
|
||||
GVN getValueNumber() { result = super.getValueNumber() }
|
||||
}
|
||||
@@ -87,7 +87,7 @@ class SemIntegerLiteralExpr extends SemNumericLiteralExpr {
|
||||
final int getIntValue() { Specific::integerLiteral(this, _, result) }
|
||||
|
||||
final override float getApproximateFloatValue() {
|
||||
result = getIntValue()
|
||||
result = this.getIntValue()
|
||||
or
|
||||
Specific::largeIntegerLiteral(this, _, result)
|
||||
}
|
||||
@@ -124,13 +124,13 @@ class SemBinaryExpr extends SemKnownExpr {
|
||||
|
||||
/** Holds if `a` and `b` are the two operands, in either order. */
|
||||
final predicate hasOperands(SemExpr a, SemExpr b) {
|
||||
a = getLeftOperand() and b = getRightOperand()
|
||||
a = this.getLeftOperand() and b = this.getRightOperand()
|
||||
or
|
||||
a = getRightOperand() and b = getLeftOperand()
|
||||
a = this.getRightOperand() and b = this.getLeftOperand()
|
||||
}
|
||||
|
||||
/** Gets the two operands. */
|
||||
final SemExpr getAnOperand() { result = getLeftOperand() or result = getRightOperand() }
|
||||
final SemExpr getAnOperand() { result = this.getLeftOperand() or result = this.getRightOperand() }
|
||||
}
|
||||
|
||||
/** An expression that performs and ordered comparison of two operands. */
|
||||
@@ -154,8 +154,8 @@ class SemRelationalExpr extends SemBinaryExpr {
|
||||
*/
|
||||
final SemExpr getLesserOperand() {
|
||||
if opcode instanceof Opcode::CompareLT or opcode instanceof Opcode::CompareLE
|
||||
then result = getLeftOperand()
|
||||
else result = getRightOperand()
|
||||
then result = this.getLeftOperand()
|
||||
else result = this.getRightOperand()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -167,8 +167,8 @@ class SemRelationalExpr extends SemBinaryExpr {
|
||||
*/
|
||||
final SemExpr getGreaterOperand() {
|
||||
if opcode instanceof Opcode::CompareGT or opcode instanceof Opcode::CompareGE
|
||||
then result = getLeftOperand()
|
||||
else result = getRightOperand()
|
||||
then result = this.getLeftOperand()
|
||||
else result = this.getRightOperand()
|
||||
}
|
||||
|
||||
/** Holds if this comparison returns `false` if the two operands are equal. */
|
||||
@@ -280,11 +280,11 @@ class SemLoadExpr extends SemNullaryExpr {
|
||||
}
|
||||
|
||||
class SemSsaLoadExpr extends SemLoadExpr {
|
||||
SemSsaLoadExpr() { exists(getDef()) }
|
||||
SemSsaLoadExpr() { exists(this.getDef()) }
|
||||
}
|
||||
|
||||
class SemNonSsaLoadExpr extends SemLoadExpr {
|
||||
SemNonSsaLoadExpr() { not exists(getDef()) }
|
||||
SemNonSsaLoadExpr() { not exists(this.getDef()) }
|
||||
}
|
||||
|
||||
class SemStoreExpr extends SemUnaryExpr {
|
||||
|
||||
@@ -59,7 +59,7 @@ class SemSsaReadPositionBlock extends SemSsaReadPosition {
|
||||
|
||||
SemBasicBlock getBlock() { result = block }
|
||||
|
||||
SemExpr getAnExpr() { result = getBlock().getAnExpr() }
|
||||
SemExpr getAnExpr() { result = this.getBlock().getAnExpr() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,7 +38,7 @@ class SemType extends TSemType {
|
||||
* Gets a string that uniquely identifies this `SemType`. This string is often the same as the
|
||||
* result of `SemType.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.
|
||||
@@ -132,7 +132,7 @@ class SemIntegerType extends SemNumericType {
|
||||
final predicate isSigned() { signed = true }
|
||||
|
||||
/** Holds if this integer type is unsigned. */
|
||||
final predicate isUnsigned() { not isSigned() }
|
||||
final predicate isUnsigned() { not this.isSigned() }
|
||||
// Don't override `getByteSize()` here. The optimizer seems to generate better code when this is
|
||||
// overridden only in the leaf classes.
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ abstract class Bound extends TBound {
|
||||
abstract Instruction getInstruction(int delta);
|
||||
|
||||
/** Gets an expression that equals this bound. */
|
||||
Instruction getInstruction() { result = getInstruction(0) }
|
||||
Instruction getInstruction() { result = this.getInstruction(0) }
|
||||
|
||||
abstract Location getLocation();
|
||||
}
|
||||
|
||||
@@ -120,13 +120,6 @@ module ModulusAnalysis<DeltaSig D, BoundSig<D> Bounds, UtilSig<D> U> {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `rix` is the number of input edges to `phi`.
|
||||
*/
|
||||
private predicate maxPhiInputRank(SemSsaPhiNode phi, int rix) {
|
||||
rix = max(int r | rankedPhiInput(phi, _, _, r))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the remainder of `val` modulo `mod`.
|
||||
*
|
||||
@@ -322,20 +315,4 @@ module ModulusAnalysis<DeltaSig D, BoundSig<D> Bounds, UtilSig<D> U> {
|
||||
semExprModulus(rarg, b, val, mod) and isLeft = false
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `inp` is an input to `phi` along `edge` and this input has index `r`
|
||||
* in an arbitrary 1-based numbering of the input edges to `phi`.
|
||||
*/
|
||||
private predicate rankedPhiInput(
|
||||
SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, int r
|
||||
) {
|
||||
edge.phiInput(phi, inp) and
|
||||
edge =
|
||||
rank[r](SemSsaReadPositionPhiInputEdge e |
|
||||
e.phiInput(phi, _)
|
||||
|
|
||||
e order by e.getOrigBlock().getUniqueId()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,6 +109,6 @@ module Public {
|
||||
/** Gets the condition that is the reason for the bound. */
|
||||
SemGuard getCond() { this = TSemCondReason(result) }
|
||||
|
||||
override string toString() { result = getCond().toString() }
|
||||
override string toString() { result = this.getCond().toString() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,7 +277,7 @@ module RangeStage<
|
||||
*/
|
||||
private class SafeCastExpr extends ConvertOrBoxExpr {
|
||||
SafeCastExpr() {
|
||||
conversionCannotOverflow(getTrackedType(pragma[only_bind_into](getOperand())),
|
||||
conversionCannotOverflow(getTrackedType(pragma[only_bind_into](this.getOperand())),
|
||||
pragma[only_bind_out](getTrackedType(this)))
|
||||
}
|
||||
}
|
||||
@@ -536,7 +536,7 @@ module RangeStage<
|
||||
/** Gets the condition that is the reason for the bound. */
|
||||
SemGuard getCond() { this = TSemCondReason(result) }
|
||||
|
||||
override string toString() { result = getCond().toString() }
|
||||
override string toString() { result = this.getCond().toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -877,6 +877,22 @@ module RangeStage<
|
||||
)
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate boundedPhiRankStep(
|
||||
SemSsaPhiNode phi, SemBound b, D::Delta delta, boolean upper, boolean fromBackEdge,
|
||||
D::Delta origdelta, SemReason reason, int rix
|
||||
) {
|
||||
exists(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge |
|
||||
Utils::rankedPhiInput(phi, inp, edge, rix) and
|
||||
boundedPhiCandValidForEdge(phi, b, delta, upper, fromBackEdge, origdelta, reason, inp, edge)
|
||||
|
|
||||
if rix = 1
|
||||
then any()
|
||||
else boundedPhiRankStep(phi, b, delta, upper, fromBackEdge, origdelta, reason, rix - 1)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `b + delta` is a valid bound for `phi`.
|
||||
* - `upper = true` : `phi <= b + delta`
|
||||
@@ -886,8 +902,9 @@ module RangeStage<
|
||||
SemSsaPhiNode phi, SemBound b, D::Delta delta, boolean upper, boolean fromBackEdge,
|
||||
D::Delta origdelta, SemReason reason
|
||||
) {
|
||||
forex(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge | edge.phiInput(phi, inp) |
|
||||
boundedPhiCandValidForEdge(phi, b, delta, upper, fromBackEdge, origdelta, reason, inp, edge)
|
||||
exists(int r |
|
||||
Utils::maxPhiInputRank(phi, r) and
|
||||
boundedPhiRankStep(phi, b, delta, upper, fromBackEdge, origdelta, reason, r)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -138,3 +138,26 @@ module RangeUtil<Range::DeltaSig D, Range::LangSig<D> Lang> implements Range::Ut
|
||||
not exists(Lang::getAlternateTypeForSsaVariable(var)) and result = var.getType()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `rix` is the number of input edges to `phi`.
|
||||
*/
|
||||
predicate maxPhiInputRank(SemSsaPhiNode phi, int rix) {
|
||||
rix = max(int r | rankedPhiInput(phi, _, _, r))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `inp` is an input to `phi` along `edge` and this input has index `r`
|
||||
* in an arbitrary 1-based numbering of the input edges to `phi`.
|
||||
*/
|
||||
predicate rankedPhiInput(
|
||||
SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, int r
|
||||
) {
|
||||
edge.phiInput(phi, inp) and
|
||||
edge =
|
||||
rank[r](SemSsaReadPositionPhiInputEdge e |
|
||||
e.phiInput(phi, _)
|
||||
|
|
||||
e order by e.getOrigBlock().getUniqueId()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ class Sign extends TSign {
|
||||
* Gets a possible sign after subtracting an expression with sign `s` from an expression
|
||||
* that has this sign.
|
||||
*/
|
||||
Sign sub(Sign s) { result = add(s.neg()) }
|
||||
Sign sub(Sign s) { result = this.add(s.neg()) }
|
||||
|
||||
/**
|
||||
* Gets a possible sign after multiplying an expression with sign `s` to an expression
|
||||
@@ -231,37 +231,37 @@ class Sign extends TSign {
|
||||
or
|
||||
op instanceof Opcode::Store and result = this
|
||||
or
|
||||
op instanceof Opcode::AddOne and result = inc()
|
||||
op instanceof Opcode::AddOne and result = this.inc()
|
||||
or
|
||||
op instanceof Opcode::SubOne and result = dec()
|
||||
op instanceof Opcode::SubOne and result = this.dec()
|
||||
or
|
||||
op instanceof Opcode::Negate and result = neg()
|
||||
op instanceof Opcode::Negate and result = this.neg()
|
||||
or
|
||||
op instanceof Opcode::BitComplement and result = bitnot()
|
||||
op instanceof Opcode::BitComplement and result = this.bitnot()
|
||||
}
|
||||
|
||||
/** Perform `op` on this sign and sign `s`. */
|
||||
Sign applyBinaryOp(Sign s, Opcode op) {
|
||||
op instanceof Opcode::Add and result = add(s)
|
||||
op instanceof Opcode::Add and result = this.add(s)
|
||||
or
|
||||
op instanceof Opcode::Sub and result = sub(s)
|
||||
op instanceof Opcode::Sub and result = this.sub(s)
|
||||
or
|
||||
op instanceof Opcode::Mul and result = mul(s)
|
||||
op instanceof Opcode::Mul and result = this.mul(s)
|
||||
or
|
||||
op instanceof Opcode::Div and result = div(s)
|
||||
op instanceof Opcode::Div and result = this.div(s)
|
||||
or
|
||||
op instanceof Opcode::Rem and result = rem(s)
|
||||
op instanceof Opcode::Rem and result = this.rem(s)
|
||||
or
|
||||
op instanceof Opcode::BitAnd and result = bitand(s)
|
||||
op instanceof Opcode::BitAnd and result = this.bitand(s)
|
||||
or
|
||||
op instanceof Opcode::BitOr and result = bitor(s)
|
||||
op instanceof Opcode::BitOr and result = this.bitor(s)
|
||||
or
|
||||
op instanceof Opcode::BitXor and result = bitxor(s)
|
||||
op instanceof Opcode::BitXor and result = this.bitxor(s)
|
||||
or
|
||||
op instanceof Opcode::ShiftLeft and result = lshift(s)
|
||||
op instanceof Opcode::ShiftLeft and result = this.lshift(s)
|
||||
or
|
||||
op instanceof Opcode::ShiftRight and result = rshift(s)
|
||||
op instanceof Opcode::ShiftRight and result = this.rshift(s)
|
||||
or
|
||||
op instanceof Opcode::ShiftRightUnsigned and result = urshift(s)
|
||||
op instanceof Opcode::ShiftRightUnsigned and result = this.urshift(s)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ class SystemFunction extends FunctionWithWrappers instanceof CommandExecutionFun
|
||||
*/
|
||||
class VarargsExecFunctionCall extends FunctionCall {
|
||||
VarargsExecFunctionCall() {
|
||||
getTarget()
|
||||
this.getTarget()
|
||||
.hasGlobalName([
|
||||
"execl", "execle", "execlp",
|
||||
// Windows
|
||||
@@ -40,7 +40,7 @@ class VarargsExecFunctionCall extends FunctionCall {
|
||||
|
||||
/** Whether the last argument to the function is an environment pointer */
|
||||
predicate hasEnvironmentArgument() {
|
||||
getTarget().hasGlobalName(["execle", "_execle", "_execlpe", "_wexecle", "_wexeclpe"])
|
||||
this.getTarget().hasGlobalName(["execle", "_execle", "_execlpe", "_wexecle", "_wexeclpe"])
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,25 +49,27 @@ class VarargsExecFunctionCall extends FunctionCall {
|
||||
*/
|
||||
Expr getCommandArgument(int idx) {
|
||||
exists(int underlyingIdx |
|
||||
result = getArgument(underlyingIdx) and
|
||||
underlyingIdx > getCommandIdx() and
|
||||
result = this.getArgument(underlyingIdx) and
|
||||
underlyingIdx > this.getCommandIdx() and
|
||||
(
|
||||
underlyingIdx < getNumberOfArguments() - 1 or
|
||||
not hasEnvironmentArgument()
|
||||
underlyingIdx < this.getNumberOfArguments() - 1 or
|
||||
not this.hasEnvironmentArgument()
|
||||
) and
|
||||
idx = underlyingIdx - getCommandIdx() - 1
|
||||
idx = underlyingIdx - this.getCommandIdx() - 1
|
||||
)
|
||||
}
|
||||
|
||||
/** The expression denoting the program to execute */
|
||||
Expr getCommand() { result = getArgument(getCommandIdx()) }
|
||||
Expr getCommand() { result = this.getArgument(this.getCommandIdx()) }
|
||||
|
||||
/**
|
||||
* The index of the command. The spawn variants start with a mode, whereas
|
||||
* all the other ones start with the command.
|
||||
*/
|
||||
private int getCommandIdx() {
|
||||
if getTarget().getName().matches(["\\_spawn%", "\\_wspawn%"]) then result = 1 else result = 0
|
||||
if this.getTarget().getName().matches(["\\_spawn%", "\\_wspawn%"])
|
||||
then result = 1
|
||||
else result = 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +80,7 @@ class VarargsExecFunctionCall extends FunctionCall {
|
||||
*/
|
||||
class ArrayExecFunctionCall extends FunctionCall {
|
||||
ArrayExecFunctionCall() {
|
||||
getTarget()
|
||||
this.getTarget()
|
||||
.hasGlobalName([
|
||||
"execv", "execvp", "execvpe", "execve", "fexecve",
|
||||
// Windows variants
|
||||
@@ -89,17 +91,19 @@ class ArrayExecFunctionCall extends FunctionCall {
|
||||
}
|
||||
|
||||
/** The argument with the array of command arguments */
|
||||
Expr getArrayArgument() { result = getArgument(getCommandIdx() + 1) }
|
||||
Expr getArrayArgument() { result = this.getArgument(this.getCommandIdx() + 1) }
|
||||
|
||||
/** The expression denoting the program to execute */
|
||||
Expr getCommand() { result = getArgument(getCommandIdx()) }
|
||||
Expr getCommand() { result = this.getArgument(this.getCommandIdx()) }
|
||||
|
||||
/**
|
||||
* The index of the command. The spawn variants start with a mode, whereas
|
||||
* all the other ones start with the command.
|
||||
*/
|
||||
private int getCommandIdx() {
|
||||
if getTarget().getName().matches(["\\_spawn%", "\\_wspawn%"]) then result = 1 else result = 0
|
||||
if this.getTarget().getName().matches(["\\_spawn%", "\\_wspawn%"])
|
||||
then result = 1
|
||||
else result = 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -564,9 +564,9 @@ abstract deprecated library class DataSensitiveCallExpr extends Expr {
|
||||
* Searches backwards from `getSrc()` to `src`.
|
||||
*/
|
||||
predicate flowsFrom(Element src, boolean allowFromArg) {
|
||||
src = getSrc() and allowFromArg = true
|
||||
src = this.getSrc() and allowFromArg = true
|
||||
or
|
||||
exists(Element other, boolean allowOtherFromArg | flowsFrom(other, allowOtherFromArg) |
|
||||
exists(Element other, boolean allowOtherFromArg | this.flowsFrom(other, allowOtherFromArg) |
|
||||
exists(boolean otherFromArg | betweenFunctionsValueMoveToStatic(src, other, otherFromArg) |
|
||||
otherFromArg = true and allowOtherFromArg = true and allowFromArg = true
|
||||
or
|
||||
@@ -582,10 +582,10 @@ abstract deprecated library class DataSensitiveCallExpr extends Expr {
|
||||
|
||||
/** Call through a function pointer. */
|
||||
deprecated library class DataSensitiveExprCall extends DataSensitiveCallExpr, ExprCall {
|
||||
override Expr getSrc() { result = getExpr() }
|
||||
override Expr getSrc() { result = this.getExpr() }
|
||||
|
||||
override Function resolve() {
|
||||
exists(FunctionAccess fa | flowsFrom(fa, true) | result = fa.getTarget())
|
||||
exists(FunctionAccess fa | this.flowsFrom(fa, true) | result = fa.getTarget())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -594,16 +594,16 @@ deprecated library class DataSensitiveOverriddenFunctionCall extends DataSensiti
|
||||
FunctionCall
|
||||
{
|
||||
DataSensitiveOverriddenFunctionCall() {
|
||||
exists(getTarget().(VirtualFunction).getAnOverridingFunction())
|
||||
exists(this.getTarget().(VirtualFunction).getAnOverridingFunction())
|
||||
}
|
||||
|
||||
override Expr getSrc() { result = getQualifier() }
|
||||
override Expr getSrc() { result = this.getQualifier() }
|
||||
|
||||
override MemberFunction resolve() {
|
||||
exists(NewExpr new |
|
||||
flowsFrom(new, true) and
|
||||
this.flowsFrom(new, true) and
|
||||
memberFunctionFromNewExpr(new, result) and
|
||||
result.overrides*(getTarget().(VirtualFunction))
|
||||
result.overrides*(this.getTarget().(VirtualFunction))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,10 +284,10 @@ deprecated class GVN extends GvnBase {
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = exampleExpr().toString() }
|
||||
string toString() { result = this.exampleExpr().toString() }
|
||||
|
||||
/** Gets the primary location of this element. */
|
||||
Location getLocation() { result = exampleExpr().getLocation() }
|
||||
Location getLocation() { result = this.exampleExpr().getLocation() }
|
||||
}
|
||||
|
||||
private predicate analyzableIntConst(Expr e) {
|
||||
|
||||
@@ -282,10 +282,10 @@ class HashCons extends HCBase {
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = exampleExpr().toString() }
|
||||
string toString() { result = this.exampleExpr().toString() }
|
||||
|
||||
/** Gets the primary location of this element. */
|
||||
Location getLocation() { result = exampleExpr().getLocation() }
|
||||
Location getLocation() { result = this.exampleExpr().getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,7 +24,7 @@ class ClassPointerType extends @derivedtype {
|
||||
|
||||
Class getBaseType() { derivedtypes(this, _, _, result) }
|
||||
|
||||
string toString() { result = getBaseType().toString() + "*" }
|
||||
string toString() { result = this.getBaseType().toString() + "*" }
|
||||
}
|
||||
|
||||
class DefinedMemberFunction extends @function {
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
## 0.6.1
|
||||
|
||||
### New Queries
|
||||
|
||||
* A new query `cpp/double-free` has been added. The query finds possible cases of deallocating the same pointer twice. The precision of the query has been set to "medium".
|
||||
* The query `cpp/use-after-free` has been modernized and assigned the precision "medium". The query finds cases of where a pointer is dereferenced after its memory has been deallocated.
|
||||
|
||||
## 0.6.0
|
||||
|
||||
### New Queries
|
||||
|
||||
@@ -118,7 +118,7 @@ class FOpenReachability extends StackVariableReachabilityExt {
|
||||
override predicate isBarrier(
|
||||
ControlFlowNode source, ControlFlowNode node, ControlFlowNode next, StackVariable v
|
||||
) {
|
||||
isSource(source, v) and
|
||||
this.isSource(source, v) and
|
||||
next = node.getASuccessor() and
|
||||
// the file (stored in any variable `v0`) opened at `source` is closed or
|
||||
// assigned to a global at node, or NULL checked on the edge node -> next.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user