Merge branch 'main' into aeisenberg/update-analyzing-databases

This commit is contained in:
Andrew Eisenberg
2022-09-21 14:40:27 -07:00
committed by GitHub
1528 changed files with 36538 additions and 11771 deletions

View File

@@ -197,7 +197,7 @@ jobs:
- name: Prepare test files - name: Prepare test files
shell: bash shell: bash
run: | run: |
echo "import ruby select count(File f)" > "test.ql" echo "import codeql.ruby.AST select count(File f)" > "test.ql"
echo "| 4 |" > "test.expected" echo "| 4 |" > "test.expected"
echo 'name: sample-tests echo 'name: sample-tests
version: 0.0.0 version: 0.0.0

View File

@@ -4,6 +4,8 @@ on:
pull_request: pull_request:
paths: paths:
- "swift/**" - "swift/**"
- "misc/bazel/**"
- "*.bazel*"
- .github/workflows/swift-codegen.yml - .github/workflows/swift-codegen.yml
- .github/actions/fetch-codeql/action.yml - .github/actions/fetch-codeql/action.yml
branches: branches:

View File

@@ -4,6 +4,8 @@ on:
pull_request: pull_request:
paths: paths:
- "swift/**" - "swift/**"
- "misc/bazel/**"
- "*.bazel*"
- .github/workflows/swift-integration-tests.yml - .github/workflows/swift-integration-tests.yml
- .github/actions/fetch-codeql/action.yml - .github/actions/fetch-codeql/action.yml
- codeql-workspace.yml - codeql-workspace.yml
@@ -30,6 +32,14 @@ jobs:
- name: Build Swift extractor - name: Build Swift extractor
run: | run: |
bazel run //swift:create-extractor-pack bazel run //swift:create-extractor-pack
- name: Get Swift version
id: get_swift_version
run: |
VERSION=$(bazel run //swift/extractor -- --version | sed -ne 's/.*version \(\S*\).*/\1/p')
echo "::set-output name=version::$VERSION"
- uses: swift-actions/setup-swift@v1
with:
swift-version: "${{steps.get_swift_version.outputs.version}}"
- name: Run integration tests - name: Run integration tests
run: | run: |
python integration-tests/runner.py python integration-tests/runner.py

View File

@@ -4,6 +4,8 @@ on:
pull_request: pull_request:
paths: paths:
- "swift/**" - "swift/**"
- "misc/bazel/**"
- "*.bazel*"
- .github/workflows/swift-qltest.yml - .github/workflows/swift-qltest.yml
- .github/actions/fetch-codeql/action.yml - .github/actions/fetch-codeql/action.yml
- codeql-workspace.yml - codeql-workspace.yml

View File

@@ -30,6 +30,8 @@
# Bazel (excluding BUILD.bazel files) # Bazel (excluding BUILD.bazel files)
WORKSPACE.bazel @github/codeql-ci-reviewers WORKSPACE.bazel @github/codeql-ci-reviewers
.bazelversion @github/codeql-ci-reviewers
.bazelrc @github/codeql-ci-reviewers
**/*.bzl @github/codeql-ci-reviewers **/*.bzl @github/codeql-ci-reviewers
# Documentation etc # Documentation etc

View File

@@ -17,6 +17,10 @@
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll",
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll",
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll",
"cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll",
"cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll",
"cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll",
"cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll",
@@ -37,6 +41,7 @@
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll", "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll",
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll", "cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll",
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll",
"cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll", "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll", "ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll",
@@ -48,6 +53,9 @@
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll",
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking3/TaintTrackingImpl.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking3/TaintTrackingImpl.qll",
"cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
"cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll",
"cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking3/TaintTrackingImpl.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking3/TaintTrackingImpl.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking3/TaintTrackingImpl.qll",
@@ -68,15 +76,17 @@
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll", "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll",
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll", "cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll",
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll",
"cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll", "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplConsistency.qll", "ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplConsistency.qll",
"swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplConsistency.qll" "swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplConsistency.qll"
], ],
"DataFlow Java/C# Flow Summaries": [ "DataFlow Java/C#/Ruby/Python/Swift Flow Summaries": [
"java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll", "java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll", "ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll",
"swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImpl.qll" "swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImpl.qll"
], ],
"SsaReadPosition Java/C#": [ "SsaReadPosition Java/C#": [
@@ -532,7 +542,7 @@
"java/ql/lib/semmle/code/java/dataflow/internal/AccessPathSyntax.qll", "java/ql/lib/semmle/code/java/dataflow/internal/AccessPathSyntax.qll",
"javascript/ql/lib/semmle/javascript/frameworks/data/internal/AccessPathSyntax.qll", "javascript/ql/lib/semmle/javascript/frameworks/data/internal/AccessPathSyntax.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/AccessPathSyntax.qll", "ruby/ql/lib/codeql/ruby/dataflow/internal/AccessPathSyntax.qll",
"python/ql/lib/semmle/python/frameworks/data/internal/AccessPathSyntax.qll", "python/ql/lib/semmle/python/dataflow/new/internal/AccessPathSyntax.qll",
"swift/ql/lib/codeql/swift/dataflow/internal/AccessPathSyntax.qll" "swift/ql/lib/codeql/swift/dataflow/internal/AccessPathSyntax.qll"
], ],
"IncompleteUrlSubstringSanitization": [ "IncompleteUrlSubstringSanitization": [

View File

@@ -1,3 +1,5 @@
## 0.3.5
## 0.3.4 ## 0.3.4
### Deprecated APIs ### Deprecated APIs

View File

@@ -0,0 +1,5 @@
---
category: deprecated
---
* Some classes/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
The old name still exists as a deprecated alias.

View File

@@ -0,0 +1 @@
## 0.3.5

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 0.3.4 lastReleaseVersion: 0.3.5

View File

@@ -1,5 +1,5 @@
import semmle.code.cpp.ir.dataflow.DataFlow import experimental.semmle.code.cpp.ir.dataflow.DataFlow
import semmle.code.cpp.ir.dataflow.DataFlow2 import experimental.semmle.code.cpp.ir.dataflow.DataFlow2
module ProductFlow { module ProductFlow {
abstract class Configuration extends string { abstract class Configuration extends string {
@@ -11,14 +11,43 @@ module ProductFlow {
* *
* `source1` and `source2` must belong to the same callable. * `source1` and `source2` must belong to the same callable.
*/ */
abstract predicate isSourcePair(DataFlow::Node source1, DataFlow::Node source2); predicate isSourcePair(DataFlow::Node source1, DataFlow::Node source2) { none() }
/**
* Holds if `(source1, source2)` is a relevant data flow source with initial states `state1`
* and `state2`, respectively.
*
* `source1` and `source2` must belong to the same callable.
*/
predicate isSourcePair(
DataFlow::Node source1, string state1, DataFlow::Node source2, string state2
) {
state1 = "" and
state2 = "" and
this.isSourcePair(source1, source2)
}
/** /**
* Holds if `(sink1, sink2)` is a relevant data flow sink. * Holds if `(sink1, sink2)` is a relevant data flow sink.
* *
* `sink1` and `sink2` must belong to the same callable. * `sink1` and `sink2` must belong to the same callable.
*/ */
abstract predicate isSinkPair(DataFlow::Node sink1, DataFlow::Node sink2); predicate isSinkPair(DataFlow::Node sink1, DataFlow::Node sink2) { none() }
/**
* Holds if `(sink1, sink2)` is a relevant data flow sink with final states `state1`
* and `state2`, respectively.
*
* `sink1` and `sink2` must belong to the same callable.
*/
predicate isSinkPair(
DataFlow::Node sink1, DataFlow::FlowState state1, DataFlow::Node sink2,
DataFlow::FlowState state2
) {
state1 = "" and
state2 = "" and
this.isSinkPair(sink1, sink2)
}
predicate hasFlowPath( predicate hasFlowPath(
DataFlow::PathNode source1, DataFlow2::PathNode source2, DataFlow::PathNode sink1, DataFlow::PathNode source1, DataFlow2::PathNode source2, DataFlow::PathNode sink1,
@@ -34,28 +63,28 @@ module ProductFlow {
class Conf1 extends DataFlow::Configuration { class Conf1 extends DataFlow::Configuration {
Conf1() { this = "Conf1" } Conf1() { this = "Conf1" }
override predicate isSource(DataFlow::Node source) { override predicate isSource(DataFlow::Node source, string state) {
exists(Configuration conf | conf.isSourcePair(source, _)) exists(Configuration conf | conf.isSourcePair(source, state, _, _))
} }
override predicate isSink(DataFlow::Node sink) { override predicate isSink(DataFlow::Node sink, string state) {
exists(Configuration conf | conf.isSinkPair(sink, _)) exists(Configuration conf | conf.isSinkPair(sink, state, _, _))
} }
} }
class Conf2 extends DataFlow2::Configuration { class Conf2 extends DataFlow2::Configuration {
Conf2() { this = "Conf2" } Conf2() { this = "Conf2" }
override predicate isSource(DataFlow::Node source) { override predicate isSource(DataFlow::Node source, string state) {
exists(Configuration conf, DataFlow::Node source1 | exists(Configuration conf, DataFlow::Node source1 |
conf.isSourcePair(source1, source) and conf.isSourcePair(source1, _, source, state) and
any(Conf1 c).hasFlow(source1, _) any(Conf1 c).hasFlow(source1, _)
) )
} }
override predicate isSink(DataFlow::Node sink) { override predicate isSink(DataFlow::Node sink, string state) {
exists(Configuration conf, DataFlow::Node sink1 | exists(Configuration conf, DataFlow::Node sink1 |
conf.isSinkPair(sink1, sink) and any(Conf1 c).hasFlow(_, sink1) conf.isSinkPair(sink1, _, sink, state) and any(Conf1 c).hasFlow(_, sink1)
) )
} }
} }
@@ -65,7 +94,7 @@ module ProductFlow {
Configuration conf, DataFlow::PathNode source1, DataFlow2::PathNode source2, Configuration conf, DataFlow::PathNode source1, DataFlow2::PathNode source2,
DataFlow::PathNode node1, DataFlow2::PathNode node2 DataFlow::PathNode node1, DataFlow2::PathNode node2
) { ) {
conf.isSourcePair(node1.getNode(), node2.getNode()) and conf.isSourcePair(node1.getNode(), _, node2.getNode(), _) and
node1 = source1 and node1 = source1 and
node2 = source2 node2 = source2
or or
@@ -128,7 +157,7 @@ module ProductFlow {
) { ) {
exists(DataFlow::PathNode mid1, DataFlow2::PathNode mid2 | exists(DataFlow::PathNode mid1, DataFlow2::PathNode mid2 |
reachableInterprocEntry(conf, source1, source2, mid1, mid2) and reachableInterprocEntry(conf, source1, source2, mid1, mid2) and
conf.isSinkPair(sink1.getNode(), sink2.getNode()) and conf.isSinkPair(sink1.getNode(), _, sink2.getNode(), _) and
localPathStep1*(mid1, sink1) and localPathStep1*(mid1, sink1) and
localPathStep2*(mid2, sink2) localPathStep2*(mid2, sink2)
) )

View File

@@ -172,7 +172,12 @@ abstract class Configuration extends DataFlow::Configuration {
} }
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) { override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and (
this.isSink(node) or
this.isSink(node, _) or
this.isAdditionalTaintStep(node, _) or
this.isAdditionalTaintStep(node, _, _, _)
) and
defaultImplicitTaintRead(node, c) defaultImplicitTaintRead(node, c)
} }

View File

@@ -172,7 +172,12 @@ abstract class Configuration extends DataFlow::Configuration {
} }
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) { override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and (
this.isSink(node) or
this.isSink(node, _) or
this.isAdditionalTaintStep(node, _) or
this.isAdditionalTaintStep(node, _, _, _)
) and
defaultImplicitTaintRead(node, c) defaultImplicitTaintRead(node, c)
} }

View File

@@ -172,7 +172,12 @@ abstract class Configuration extends DataFlow::Configuration {
} }
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) { override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and (
this.isSink(node) or
this.isSink(node, _) or
this.isAdditionalTaintStep(node, _) or
this.isAdditionalTaintStep(node, _, _, _)
) and
defaultImplicitTaintRead(node, c) defaultImplicitTaintRead(node, c)
} }

View File

@@ -28,6 +28,10 @@ private newtype TBound =
i.(LoadInstruction).getSourceAddress() instanceof FieldAddressInstruction i.(LoadInstruction).getSourceAddress() instanceof FieldAddressInstruction
or or
i.getAUse() instanceof ArgumentOperand i.getAUse() instanceof ArgumentOperand
or
i instanceof PointerArithmeticInstruction
or
i.getAUse() instanceof AddressOperand
) )
} }

View File

@@ -178,11 +178,11 @@ class SemRelationalExpr extends SemBinaryExpr {
} }
class SemAddExpr extends SemBinaryExpr { class SemAddExpr extends SemBinaryExpr {
SemAddExpr() { opcode instanceof Opcode::Add } SemAddExpr() { opcode instanceof Opcode::Add or opcode instanceof Opcode::PointerAdd }
} }
class SemSubExpr extends SemBinaryExpr { class SemSubExpr extends SemBinaryExpr {
SemSubExpr() { opcode instanceof Opcode::Sub } SemSubExpr() { opcode instanceof Opcode::Sub or opcode instanceof Opcode::PointerSub }
} }
class SemMulExpr extends SemBinaryExpr { class SemMulExpr extends SemBinaryExpr {

View File

@@ -65,10 +65,18 @@ module Opcode {
override string toString() { result = "Add" } override string toString() { result = "Add" }
} }
class PointerAdd extends Opcode, TPointerAdd {
override string toString() { result = "PointerAdd" }
}
class Sub extends Opcode, TSub { class Sub extends Opcode, TSub {
override string toString() { result = "Sub" } override string toString() { result = "Sub" }
} }
class PointerSub extends Opcode, TPointerSub {
override string toString() { result = "PointerSub" }
}
class Mul extends Opcode, TMul { class Mul extends Opcode, TMul {
override string toString() { result = "Mul" } override string toString() { result = "Mul" }
} }

View File

@@ -223,7 +223,9 @@ private SemGuard boundFlowCond(
else resultIsStrict = testIsTrue.booleanNot() else resultIsStrict = testIsTrue.booleanNot()
) and ) and
( (
if getTrackedTypeForSsaVariable(v) instanceof SemIntegerType if
getTrackedTypeForSsaVariable(v) instanceof SemIntegerType or
getTrackedTypeForSsaVariable(v) instanceof SemAddressType
then then
upper = true and strengthen = -1 upper = true and strengthen = -1
or or

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all name: codeql/cpp-all
version: 0.3.5-dev version: 0.3.6-dev
groups: cpp groups: cpp
dbscheme: semmlecode.cpp.dbscheme dbscheme: semmlecode.cpp.dbscheme
extractor: cpp extractor: cpp

View File

@@ -1,2 +1,2 @@
private import SSAConstruction as SSA private import SSAConstruction as Ssa
import SSA::SsaConsistency import Ssa::SsaConsistency

View File

@@ -1135,7 +1135,7 @@ deprecated module SSAConsistency = SsaConsistency;
* These predicates are all just aliases for predicates defined in the `Cached` module. This ensures * These predicates are all just aliases for predicates defined in the `Cached` module. This ensures
* that all of SSA construction will be evaluated in the same stage. * that all of SSA construction will be evaluated in the same stage.
*/ */
module SSA { module Ssa {
class MemoryLocation = Alias::MemoryLocation; class MemoryLocation = Alias::MemoryLocation;
predicate hasPhiInstruction = Cached::hasPhiInstructionCached/2; predicate hasPhiInstruction = Cached::hasPhiInstructionCached/2;
@@ -1144,3 +1144,6 @@ module SSA {
predicate hasUnreachedInstruction = Cached::hasUnreachedInstructionCached/1; predicate hasUnreachedInstruction = Cached::hasUnreachedInstructionCached/1;
} }
/** DEPRECATED: Alias for Ssa */
deprecated module SSA = Ssa;

View File

@@ -20,24 +20,24 @@ newtype TInstruction =
IRConstruction::Raw::hasInstruction(tag1, tag2) IRConstruction::Raw::hasInstruction(tag1, tag2)
} or } or
TUnaliasedSsaPhiInstruction( TUnaliasedSsaPhiInstruction(
TRawInstruction blockStartInstr, UnaliasedSsa::SSA::MemoryLocation memoryLocation TRawInstruction blockStartInstr, UnaliasedSsa::Ssa::MemoryLocation memoryLocation
) { ) {
UnaliasedSsa::SSA::hasPhiInstruction(blockStartInstr, memoryLocation) UnaliasedSsa::Ssa::hasPhiInstruction(blockStartInstr, memoryLocation)
} or } or
TUnaliasedSsaChiInstruction(TRawInstruction primaryInstruction) { none() } or TUnaliasedSsaChiInstruction(TRawInstruction primaryInstruction) { none() } or
TUnaliasedSsaUnreachedInstruction(IRFunctionBase irFunc) { TUnaliasedSsaUnreachedInstruction(IRFunctionBase irFunc) {
UnaliasedSsa::SSA::hasUnreachedInstruction(irFunc) UnaliasedSsa::Ssa::hasUnreachedInstruction(irFunc)
} or } or
TAliasedSsaPhiInstruction( TAliasedSsaPhiInstruction(
TRawInstruction blockStartInstr, AliasedSsa::SSA::MemoryLocation memoryLocation TRawInstruction blockStartInstr, AliasedSsa::Ssa::MemoryLocation memoryLocation
) { ) {
AliasedSsa::SSA::hasPhiInstruction(blockStartInstr, memoryLocation) AliasedSsa::Ssa::hasPhiInstruction(blockStartInstr, memoryLocation)
} or } or
TAliasedSsaChiInstruction(TRawInstruction primaryInstruction) { TAliasedSsaChiInstruction(TRawInstruction primaryInstruction) {
AliasedSsa::SSA::hasChiInstruction(primaryInstruction) AliasedSsa::Ssa::hasChiInstruction(primaryInstruction)
} or } or
TAliasedSsaUnreachedInstruction(IRFunctionBase irFunc) { TAliasedSsaUnreachedInstruction(IRFunctionBase irFunc) {
AliasedSsa::SSA::hasUnreachedInstruction(irFunc) AliasedSsa::Ssa::hasUnreachedInstruction(irFunc)
} }
/** /**
@@ -50,7 +50,7 @@ module UnaliasedSsaInstructions {
class TPhiInstruction = TUnaliasedSsaPhiInstruction; class TPhiInstruction = TUnaliasedSsaPhiInstruction;
TPhiInstruction phiInstruction( TPhiInstruction phiInstruction(
TRawInstruction blockStartInstr, UnaliasedSsa::SSA::MemoryLocation memoryLocation TRawInstruction blockStartInstr, UnaliasedSsa::Ssa::MemoryLocation memoryLocation
) { ) {
result = TUnaliasedSsaPhiInstruction(blockStartInstr, memoryLocation) result = TUnaliasedSsaPhiInstruction(blockStartInstr, memoryLocation)
} }
@@ -83,7 +83,7 @@ module AliasedSsaInstructions {
class TPhiInstruction = TAliasedSsaPhiInstruction or TUnaliasedSsaPhiInstruction; class TPhiInstruction = TAliasedSsaPhiInstruction or TUnaliasedSsaPhiInstruction;
TPhiInstruction phiInstruction( TPhiInstruction phiInstruction(
TRawInstruction blockStartInstr, AliasedSsa::SSA::MemoryLocation memoryLocation TRawInstruction blockStartInstr, AliasedSsa::Ssa::MemoryLocation memoryLocation
) { ) {
result = TAliasedSsaPhiInstruction(blockStartInstr, memoryLocation) result = TAliasedSsaPhiInstruction(blockStartInstr, memoryLocation)
} }

View File

@@ -1,2 +1,2 @@
private import SSAConstruction as SSA private import SSAConstruction as Ssa
import SSA::SsaConsistency import Ssa::SsaConsistency

View File

@@ -1135,7 +1135,7 @@ deprecated module SSAConsistency = SsaConsistency;
* These predicates are all just aliases for predicates defined in the `Cached` module. This ensures * These predicates are all just aliases for predicates defined in the `Cached` module. This ensures
* that all of SSA construction will be evaluated in the same stage. * that all of SSA construction will be evaluated in the same stage.
*/ */
module SSA { module Ssa {
class MemoryLocation = Alias::MemoryLocation; class MemoryLocation = Alias::MemoryLocation;
predicate hasPhiInstruction = Cached::hasPhiInstructionCached/2; predicate hasPhiInstruction = Cached::hasPhiInstructionCached/2;
@@ -1144,3 +1144,6 @@ module SSA {
predicate hasUnreachedInstruction = Cached::hasUnreachedInstructionCached/1; predicate hasUnreachedInstruction = Cached::hasUnreachedInstructionCached/1;
} }
/** DEPRECATED: Alias for Ssa */
deprecated module SSA = Ssa;

View File

@@ -1,3 +1,5 @@
## 0.3.4
## 0.3.3 ## 0.3.3
### Minor Analysis Improvements ### Minor Analysis Improvements

View File

@@ -163,19 +163,46 @@ TGlobalAddress globalAddress(Instruction instr) {
result = globalAddress(instr.(PointerOffsetInstruction).getLeft()) result = globalAddress(instr.(PointerOffsetInstruction).getLeft())
} }
/** Gets a `StoreInstruction` that may be executed after executing `store`. */ /**
pragma[inline] * Gets a first `StoreInstruction` that writes to address `globalAddress` reachable
StoreInstruction getAStoreStrictlyAfter(StoreInstruction store) { * from `block`.
exists(IRBlock block, int index1, int index2 | */
block.getInstruction(index1) = store and StoreInstruction getFirstStore(IRBlock block, TGlobalAddress globalAddress) {
block.getInstruction(index2) = result and 1 = getStoreRank(result, block, globalAddress)
index2 > index1 or
not exists(getStoreRank(_, block, globalAddress)) and
result = getFirstStore(block.getASuccessor(), globalAddress)
}
/**
* Gets the rank of `store` in block `block` (i.e., a rank of `1` means that it is the
* first `store` to write to `globalAddress`, a rank of `2` means it's the second, etc.)
*/
int getStoreRank(StoreInstruction store, IRBlock block, TGlobalAddress globalAddress) {
blockStoresToAddress(block, _, store, globalAddress) and
store =
rank[result](StoreInstruction anotherStore, int i |
blockStoresToAddress(_, i, anotherStore, globalAddress)
|
anotherStore order by i
)
}
/**
* Gets a next subsequent `StoreInstruction` to write to `globalAddress`
* after `store` has done so.
*/
StoreInstruction getANextStoreTo(StoreInstruction store, TGlobalAddress globalAddress) {
exists(IRBlock block, int rnk |
rnk = getStoreRank(store, block, globalAddress) and
rnk + 1 = getStoreRank(result, block, globalAddress)
) )
or or
exists(IRBlock block1, IRBlock block2 | exists(IRBlock block, int rnk, IRBlock succ |
store.getBlock() = block1 and rnk = getStoreRank(store, block, globalAddress) and
result.getBlock() = block2 and not rnk + 1 = getStoreRank(_, block, globalAddress) and
block1.getASuccessor+() = block2 succ = block.getASuccessor() and
result = getFirstStore(succ, globalAddress)
) )
} }
@@ -192,7 +219,7 @@ predicate stackAddressEscapes(
stackPointerFlowsToUse(store.getSourceValue(), vai) stackPointerFlowsToUse(store.getSourceValue(), vai)
) and ) and
// Ensure there's no subsequent store that overrides the global address. // Ensure there's no subsequent store that overrides the global address.
not globalAddress = globalAddress(getAStoreStrictlyAfter(store).getDestinationAddress()) not exists(getANextStoreTo(store, globalAddress))
} }
predicate blockStoresToAddress( predicate blockStoresToAddress(

View File

@@ -19,7 +19,7 @@ import semmle.code.cpp.ir.dataflow.TaintTracking
import DataFlow::PathGraph import DataFlow::PathGraph
/** /**
* Taint flow from user input to a buffer write. * A taint flow configuration for flow from user input to a buffer write.
*/ */
class ToBufferConfiguration extends TaintTracking::Configuration { class ToBufferConfiguration extends TaintTracking::Configuration {
ToBufferConfiguration() { this = "ToBufferConfiguration" } ToBufferConfiguration() { this = "ToBufferConfiguration" }

View File

@@ -21,7 +21,7 @@ import semmle.code.cpp.dataflow.TaintTracking
import DataFlow::PathGraph import DataFlow::PathGraph
/** /**
* Taint flow from a sensitive expression to a `FileWrite` sink. * A taint flow configuration for flow from a sensitive expression to a `FileWrite` sink.
*/ */
class FromSensitiveConfiguration extends TaintTracking::Configuration { class FromSensitiveConfiguration extends TaintTracking::Configuration {
FromSensitiveConfiguration() { this = "FromSensitiveConfiguration" } FromSensitiveConfiguration() { this = "FromSensitiveConfiguration" }
@@ -29,6 +29,10 @@ class FromSensitiveConfiguration extends TaintTracking::Configuration {
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof SensitiveExpr } override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof SensitiveExpr }
override predicate isSink(DataFlow::Node sink) { any(FileWrite w).getASource() = sink.asExpr() } override predicate isSink(DataFlow::Node sink) { any(FileWrite w).getASource() = sink.asExpr() }
override predicate isSanitizer(DataFlow::Node node) {
node.asExpr().getUnspecifiedType() instanceof IntegralType
}
} }
/** /**

View File

@@ -217,7 +217,8 @@ class Encrypted extends Expr {
} }
/** /**
* Taint flow from a sensitive expression. * A taint flow configuration for flow from a sensitive expression to a network
* operation or encryption operation.
*/ */
class FromSensitiveConfiguration extends TaintTracking::Configuration { class FromSensitiveConfiguration extends TaintTracking::Configuration {
FromSensitiveConfiguration() { this = "FromSensitiveConfiguration" } FromSensitiveConfiguration() { this = "FromSensitiveConfiguration" }
@@ -234,6 +235,10 @@ class FromSensitiveConfiguration extends TaintTracking::Configuration {
// flow through encryption functions to the return value (in case we can reach other sinks) // flow through encryption functions to the return value (in case we can reach other sinks)
node2.asExpr().(Encrypted).(FunctionCall).getAnArgument() = node1.asExpr() node2.asExpr().(Encrypted).(FunctionCall).getAnArgument() = node1.asExpr()
} }
override predicate isSanitizer(DataFlow::Node node) {
node.asExpr().getUnspecifiedType() instanceof IntegralType
}
} }
from from

View File

@@ -13,14 +13,8 @@
import cpp import cpp
import semmle.code.cpp.security.SensitiveExprs import semmle.code.cpp.security.SensitiveExprs
import semmle.code.cpp.security.TaintTracking import semmle.code.cpp.dataflow.TaintTracking
import TaintedWithPath import DataFlow::PathGraph
class UserInputIsSensitiveExpr extends SecurityOptions {
override predicate isUserInput(Expr expr, string cause) {
expr instanceof SensitiveExpr and cause = "sensitive information"
}
}
class SqliteFunctionCall extends FunctionCall { class SqliteFunctionCall extends FunctionCall {
SqliteFunctionCall() { this.getTarget().getName().matches("sqlite%") } SqliteFunctionCall() { this.getTarget().getName().matches("sqlite%") }
@@ -34,25 +28,51 @@ predicate sqlite_encryption_used() {
any(FunctionCall fc).getTarget().getName().matches("sqlite%\\_key\\_%") any(FunctionCall fc).getTarget().getName().matches("sqlite%\\_key\\_%")
} }
class Configuration extends TaintTrackingConfiguration { /**
override predicate isSource(Expr source) { * Gets a field of the class `c`, or of another class contained in `c`.
super.isSource(source) and source instanceof SensitiveExpr */
Field getRecField(Class c) {
result = c.getAField() or
result = getRecField(c.getAField().getUnspecifiedType().stripType())
}
/**
* A taint flow configuration for flow from a sensitive expression to a `SqliteFunctionCall` sink.
*/
class FromSensitiveConfiguration extends TaintTracking::Configuration {
FromSensitiveConfiguration() { this = "FromSensitiveConfiguration" }
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof SensitiveExpr }
override predicate isSink(DataFlow::Node sink) {
any(SqliteFunctionCall c).getASource() = sink.asExpr() and
not sqlite_encryption_used()
} }
override predicate isSink(Element taintedArg) { override predicate isSanitizer(DataFlow::Node node) {
exists(SqliteFunctionCall sqliteCall | node.asExpr().getUnspecifiedType() instanceof IntegralType
taintedArg = sqliteCall.getASource() and }
not sqlite_encryption_used()
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet content) {
// flow out from fields at the sink (only).
this.isSink(node) and
// constrain `content` to a field inside the node.
exists(Class c |
node.asExpr().getUnspecifiedType().stripType() = c and
content.(DataFlow::FieldContent).getField() = getRecField(c)
) )
or
// any default implicit reads
super.allowImplicitRead(node, content)
} }
} }
from from
SensitiveExpr taintSource, Expr taintedArg, SqliteFunctionCall sqliteCall, PathNode sourceNode, FromSensitiveConfiguration config, SensitiveExpr sensitive, DataFlow::PathNode source,
PathNode sinkNode DataFlow::PathNode sink, SqliteFunctionCall sqliteCall
where where
taintedWithPath(taintSource, taintedArg, sourceNode, sinkNode) and config.hasFlowPath(source, sink) and
taintedArg = sqliteCall.getASource() source.getNode().asExpr() = sensitive and
select sqliteCall, sourceNode, sinkNode, sqliteCall.getASource() = sink.getNode().asExpr()
"This SQLite call may store $@ in a non-encrypted SQLite database", taintSource, select sqliteCall, source, sink, "This SQLite call may store $@ in a non-encrypted SQLite database",
"sensitive information" sensitive, "sensitive information"

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Modernizations from "Cleartext storage of sensitive information in buffer" (`cpp/cleartext-storage-buffer`) have been ported to the "Cleartext storage of sensitive information in file" (`cpp/cleartext-storage-file`), "Cleartext transmission of sensitive information" (`cpp/cleartext-transmission`) and "Cleartext storage of sensitive information in an SQLite database" (`cpp/cleartext-storage-database`) queries. These changes may result in more correct results and fewer false positive results from these queries.

View File

@@ -0,0 +1 @@
## 0.3.4

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 0.3.3 lastReleaseVersion: 0.3.4

View File

@@ -0,0 +1,26 @@
void *malloc(unsigned);
unsigned get_size();
void write_data(const unsigned char*, const unsigned char*);
int main(int argc, char* argv[]) {
unsigned size = get_size();
{
unsigned char *begin = (unsigned char*)malloc(size);
if(!begin) return -1;
unsigned char* end = begin + size;
write_data(begin, end);
*end = '\0'; // BAD: Out-of-bounds write
}
{
unsigned char *begin = (unsigned char*)malloc(size);
if(!begin) return -1;
unsigned char* end = begin + size;
write_data(begin, end);
*(end - 1) = '\0'; // GOOD: writing to the last byte
}
}

View File

@@ -0,0 +1,31 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>The program performs an out-of-bounds read or write operation. In addition to causing program instability, techniques exist which may allow an attacker to use this vulnerability to execute arbitrary code.</p>
</overview>
<recommendation>
<p>Ensure that pointer dereferences are properly guarded to ensure that they cannot be used to read or write past the end of the allocation.</p>
</recommendation>
<example>
<p>The first example allocates a buffer of size <code>size</code> and creates a local variable that stores the location that is one byte past the end of the allocation.
This local variable is then dereferenced which results in an out-of-bounds write.
The second example subtracts one from the <code>end</code> variable before dereferencing it. This subtraction ensures that the write correctly updates the final byte of the allocation.</p>
<sample src="InvalidPointerDeref.cpp" />
</example>
<references>
<li>CERT C Coding Standard:
<a href="https://wiki.sei.cmu.edu/confluence/display/c/ARR30-C.+Do+not+form+or+use+out-of-bounds+pointers+or+array+subscripts">ARR30-C. Do not form or use out-of-bounds pointers or array subscripts</a>.</li>
<li>
OWASP:
<a href="https://owasp.org/www-community/vulnerabilities/Buffer_Overflow">Buffer Overflow</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,360 @@
/**
* @name Invalid pointer dereference
* @description Dereferencing a pointer that points past it allocation is undefined behavior
* and may lead to security vulnerabilities.
* @kind path-problem
* @problem.severity error
* @precision high
* @id cpp/invalid-pointer-deref
* @tags reliability
* security
* external/cwe/cwe-119
* external/cwe/cwe-125
* external/cwe/cwe-193
* external/cwe/cwe-787
*/
import cpp
import experimental.semmle.code.cpp.dataflow.ProductFlow
import experimental.semmle.code.cpp.ir.dataflow.DataFlow3
import experimental.semmle.code.cpp.semantic.analysis.RangeAnalysis
import experimental.semmle.code.cpp.semantic.SemanticBound
import experimental.semmle.code.cpp.semantic.SemanticExprSpecific
import semmle.code.cpp.ir.IR
pragma[nomagic]
Instruction getABoundIn(SemBound b, IRFunction func) {
result = b.getExpr(0) and
result.getEnclosingIRFunction() = func
}
/**
* Holds if `i <= b + delta`.
*/
pragma[nomagic]
predicate bounded(Instruction i, Instruction b, int delta) {
exists(SemBound bound, IRFunction func |
semBounded(getSemanticExpr(i), bound, delta, true, _) and
b = getABoundIn(bound, func) and
i.getEnclosingIRFunction() = func
)
}
/**
* Holds if the combination of `n` and `state` represents an appropriate
* source for the expression `e` suitable for use-use flow.
*/
private predicate hasSizeImpl(Expr e, DataFlow::Node n, string state) {
// The simple case: If the size is a variable access with no qualifier we can just use the
// dataflow node for that expression and no state.
exists(VariableAccess va |
va = e and
not va instanceof FieldAccess and
n.asConvertedExpr() = va.getFullyConverted() and
state = "0"
)
or
// If the size is a choice between two expressions we allow both to be nodes representing the size.
exists(ConditionalExpr cond | cond = e | hasSizeImpl([cond.getThen(), cond.getElse()], n, state))
or
// If the size is an expression plus a constant, we pick the dataflow node of the expression and
// remember the constant in the state.
exists(Expr const, Expr nonconst |
e.(AddExpr).hasOperands(const, nonconst) and
state = const.getValue() and
hasSizeImpl(nonconst, n, _)
)
or
exists(Expr const, Expr nonconst |
e.(SubExpr).hasOperands(const, nonconst) and
state = "-" + const.getValue() and
hasSizeImpl(nonconst, n, _)
)
}
/**
* Holds if `(n, state)` pair represents the source of flow for the size
* expression associated with `alloc`.
*/
predicate hasSize(AllocationExpr alloc, DataFlow::Node n, string state) {
hasSizeImpl(alloc.getSizeExpr(), n, state)
}
/**
* A product-flow configuration for flow from an (allocation, size) pair to a
* pointer-arithmetic operation that is non-strictly upper-bounded by `allocation + size`.
*
* The goal of this query is to find patterns such as:
* ```cpp
* 1. char* begin = (char*)malloc(size);
* 2. char* end = begin + size;
* 3. for(int *p = begin; p <= end; p++) {
* 4. use(*p);
* 5. }
* ```
*
* We do this by splitting the task up into two configurations:
* 1. `AllocToInvalidPointerConf` find flow from `malloc(size)` to `begin + size`, and
* 2. `InvalidPointerToDerefConf` finds flow from `begin + size` to an `end` (on line 3).
*
* Finally, the range-analysis library will find a load from (or store to) an address that
* is non-strictly upper-bounded by `end` (which in this case is `*p`).
*/
class AllocToInvalidPointerConf extends ProductFlow::Configuration {
AllocToInvalidPointerConf() { this = "AllocToInvalidPointerConf" }
override predicate isSourcePair(
DataFlow::Node source1, string state1, DataFlow::Node source2, string state2
) {
// In the case of an allocation like
// ```cpp
// malloc(size + 1);
// ```
// we use `state2` to remember that there was an offset (in this case an offset of `1`) added
// to the size of the allocation. This state is then checked in `isSinkPair`.
state1 = "" and
hasSize(source1.asConvertedExpr(), source2, state2)
}
override predicate isSinkPair(
DataFlow::Node sink1, DataFlow::FlowState state1, DataFlow::Node sink2,
DataFlow::FlowState state2
) {
state1 = "" and
// We check that the delta computed by the range analysis matches the
// state value that we set in `isSourcePair`.
exists(int delta |
isSinkImpl(_, sink1, sink2, delta) and
state2 = delta.toString()
)
}
}
pragma[nomagic]
predicate pointerAddInstructionHasOperands(
PointerAddInstruction pai, Instruction left, Instruction right
) {
pai.getLeft() = left and
pai.getRight() = right
}
/**
* Holds if `pai` is non-strictly upper bounded by `sink2 + delta` and `sink1` is the
* left operand of the pointer-arithmetic operation.
*
* For example in,
* ```cpp
* char* end = p + (size + 1);
* ```
* We will have:
* - `pai` is `p + (size + 1)`,
* - `sink1` is `p`
* - `sink2` is `size`
* - `delta` is `1`.
*/
pragma[nomagic]
predicate pointerAddInstructionHasBounds(
PointerAddInstruction pai, DataFlow::Node sink1, Instruction sink2, int delta
) {
exists(Instruction right |
pointerAddInstructionHasOperands(pai, sink1.asInstruction(), right) and
bounded(right, sink2, delta)
)
}
/**
* Holds if `pai` is non-strictly upper bounded by `sink2 + delta` and `sink1` is the
* left operand of the pointer-arithmetic operation.
*
* See `pointerAddInstructionHasBounds` for an example.
*/
predicate isSinkImpl(
PointerAddInstruction pai, DataFlow::Node sink1, DataFlow::Node sink2, int delta
) {
pointerAddInstructionHasBounds(pai, sink1, sink2.asInstruction(), delta)
}
/**
* Holds if `sink` is a sink for `InvalidPointerToDerefConf` and `i` is a `StoreInstruction` that
* writes to an address that non-strictly upper-bounds `sink`, or `i` is a `LoadInstruction` that
* reads from an address that non-strictly upper-bounds `sink`.
*/
predicate isInvalidPointerDerefSink(DataFlow::Node sink, Instruction i, string operation) {
exists(AddressOperand addr, int delta |
bounded(addr.getDef(), sink.asInstruction(), delta) and
delta >= 0 and
i.getAnOperand() = addr
|
i instanceof StoreInstruction and
operation = "write"
or
i instanceof LoadInstruction and
operation = "read"
)
}
/**
* A configuration to track flow from a pointer-arithmetic operation found
* by `AllocToInvalidPointerConf` to a dereference of the pointer.
*/
class InvalidPointerToDerefConf extends DataFlow3::Configuration {
InvalidPointerToDerefConf() { this = "InvalidPointerToDerefConf" }
override predicate isSource(DataFlow::Node source) { invalidPointerToDerefSource(_, source, _) }
override predicate isSink(DataFlow::Node sink) { isInvalidPointerDerefSink(sink, _, _) }
}
/**
* Holds if `pai` is a pointer-arithmetic operation and `source` is a dataflow node with a
* pointer-value that is non-strictly upper bounded by `pai + delta`.
*
* For example, if `pai` is a pointer-arithmetic operation `p + size` in an expression such
* as `(p + size) + 1` and `source` is the node representing `(p + size) + 1`. In this
* case `delta` is 1.
*/
predicate invalidPointerToDerefSource(
PointerArithmeticInstruction pai, DataFlow::Node source, int delta
) {
exists(ProductFlow::Configuration conf, DataFlow::PathNode p, DataFlow::Node sink1 |
p.getNode() = sink1 and
conf.hasFlowPath(_, _, p, _) and
isSinkImpl(pai, sink1, _, _) and
bounded(source.asInstruction(), pai, delta) and
delta >= 0
)
}
newtype TMergedPathNode =
// The path nodes computed by the first projection of `AllocToInvalidPointerConf`
TPathNode1(DataFlow::PathNode p) or
// The path nodes computed by `InvalidPointerToDerefConf`
TPathNode3(DataFlow3::PathNode p) or
// The read/write that uses the invalid pointer identified by `InvalidPointerToDerefConf`.
// This one is needed because the sink identified by `InvalidPointerToDerefConf` is the
// pointer, but we want to raise an alert at the dereference.
TPathNodeSink(Instruction i) {
exists(DataFlow::Node n |
any(InvalidPointerToDerefConf conf).hasFlow(_, n) and
isInvalidPointerDerefSink(n, i, _)
)
}
class MergedPathNode extends TMergedPathNode {
string toString() { none() }
final DataFlow::PathNode asPathNode1() { this = TPathNode1(result) }
final DataFlow3::PathNode asPathNode3() { this = TPathNode3(result) }
final Instruction asSinkNode() { this = TPathNodeSink(result) }
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
none()
}
}
class PathNode1 extends MergedPathNode, TPathNode1 {
override string toString() {
exists(DataFlow::PathNode p |
this = TPathNode1(p) and
result = p.toString()
)
}
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.asPathNode1().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
}
class PathNode3 extends MergedPathNode, TPathNode3 {
override string toString() {
exists(DataFlow3::PathNode p |
this = TPathNode3(p) and
result = p.toString()
)
}
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.asPathNode3().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
}
class PathSinkNode extends MergedPathNode, TPathNodeSink {
override string toString() {
exists(Instruction i |
this = TPathNodeSink(i) and
result = i.toString()
)
}
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.asSinkNode()
.getLocation()
.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
}
query predicate edges(MergedPathNode node1, MergedPathNode node2) {
node1.asPathNode1().getASuccessor() = node2.asPathNode1()
or
joinOn1(_, node1.asPathNode1(), node2.asPathNode3())
or
node1.asPathNode3().getASuccessor() = node2.asPathNode3()
or
joinOn2(node1.asPathNode3(), node2.asSinkNode(), _)
}
/**
* Holds if `p1` is a sink of `AllocToInvalidPointerConf` and `p2` is a source
* of `InvalidPointerToDerefConf`, and they are connected through `pai`.
*/
predicate joinOn1(PointerArithmeticInstruction pai, DataFlow::PathNode p1, DataFlow3::PathNode p2) {
isSinkImpl(pai, p1.getNode(), _, _) and
invalidPointerToDerefSource(pai, p2.getNode(), _)
}
/**
* Holds if `p1` is a sink of `InvalidPointerToDerefConf` and `i` is the instruction
* that dereferences `p1`. The string `operation` describes whether the `i` is
* a `StoreInstruction` or `LoadInstruction`.
*/
predicate joinOn2(DataFlow3::PathNode p1, Instruction i, string operation) {
isInvalidPointerDerefSink(p1.getNode(), i, operation)
}
predicate hasFlowPath(
MergedPathNode source1, MergedPathNode sink, DataFlow3::PathNode source3,
PointerArithmeticInstruction pai, string operation
) {
exists(
AllocToInvalidPointerConf conf1, InvalidPointerToDerefConf conf2, DataFlow3::PathNode sink3,
DataFlow::PathNode sink1
|
conf1.hasFlowPath(source1.asPathNode1(), _, sink1, _) and
joinOn1(pai, sink1, source3) and
conf2.hasFlowPath(source3, sink3) and
joinOn2(sink3, sink.asSinkNode(), operation)
)
}
from
MergedPathNode source, MergedPathNode sink, int k, string kstr, DataFlow3::PathNode source3,
PointerArithmeticInstruction pai, string operation, Expr offset, DataFlow::Node n
where
hasFlowPath(source, sink, source3, pai, operation) and
invalidPointerToDerefSource(pai, source3.getNode(), k) and
offset = pai.getRight().getUnconvertedResultExpression() and
n = source.asPathNode1().getNode() and
if k = 0 then kstr = "" else kstr = " + " + k
select sink, source, sink,
"This " + operation + " might be out of bounds, as the pointer might be equal to $@ + $@" + kstr +
".", n, n.toString(), offset, offset.toString()

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries name: codeql/cpp-queries
version: 0.3.4-dev version: 0.3.5-dev
groups: groups:
- cpp - cpp
- queries - queries

View File

@@ -20,10 +20,12 @@
| test.cpp:62:10:62:13 | Load: iter | test.cpp:60:17:60:17 | ValueNumberBound | 0 | false | NoReason | file://:0:0:0:0 | file://:0:0:0:0 | | test.cpp:62:10:62:13 | Load: iter | test.cpp:60:17:60:17 | ValueNumberBound | 0 | false | NoReason | file://:0:0:0:0 | file://:0:0:0:0 |
| test.cpp:62:10:62:13 | Load: iter | test.cpp:60:17:60:17 | ValueNumberBound | 3 | true | CompareLT: ... < ... | test.cpp:61:32:61:51 | test.cpp:61:32:61:51 | | test.cpp:62:10:62:13 | Load: iter | test.cpp:60:17:60:17 | ValueNumberBound | 3 | true | CompareLT: ... < ... | test.cpp:61:32:61:51 | test.cpp:61:32:61:51 |
| test.cpp:62:10:62:13 | Load: iter | test.cpp:61:39:61:51 | ValueNumberBound | -1 | true | CompareLT: ... < ... | test.cpp:61:32:61:51 | test.cpp:61:32:61:51 | | test.cpp:62:10:62:13 | Load: iter | test.cpp:61:39:61:51 | ValueNumberBound | -1 | true | CompareLT: ... < ... | test.cpp:61:32:61:51 | test.cpp:61:32:61:51 |
| test.cpp:62:10:62:13 | Load: iter | test.cpp:61:48:61:50 | ValueNumberBound | -1 | true | CompareLT: ... < ... | test.cpp:61:32:61:51 | test.cpp:61:32:61:51 |
| test.cpp:67:10:67:13 | Load: iter | test.cpp:60:17:60:17 | ValueNumberBound | 0 | false | NoReason | file://:0:0:0:0 | file://:0:0:0:0 | | test.cpp:67:10:67:13 | Load: iter | test.cpp:60:17:60:17 | ValueNumberBound | 0 | false | NoReason | file://:0:0:0:0 | file://:0:0:0:0 |
| test.cpp:67:10:67:13 | Load: iter | test.cpp:60:17:60:17 | ValueNumberBound | 3 | true | CompareLT: ... < ... | test.cpp:66:32:66:41 | test.cpp:66:32:66:41 | | test.cpp:67:10:67:13 | Load: iter | test.cpp:60:17:60:17 | ValueNumberBound | 3 | true | CompareLT: ... < ... | test.cpp:66:32:66:41 | test.cpp:66:32:66:41 |
| test.cpp:67:10:67:13 | Load: iter | test.cpp:61:32:61:35 | ValueNumberBound | -1 | true | CompareLT: ... < ... | test.cpp:66:32:66:41 | test.cpp:66:32:66:41 | | test.cpp:67:10:67:13 | Load: iter | test.cpp:61:32:61:35 | ValueNumberBound | -1 | true | CompareLT: ... < ... | test.cpp:66:32:66:41 | test.cpp:66:32:66:41 |
| test.cpp:67:10:67:13 | Load: iter | test.cpp:61:39:61:51 | ValueNumberBound | -1 | true | CompareLT: ... < ... | test.cpp:66:32:66:41 | test.cpp:66:32:66:41 | | test.cpp:67:10:67:13 | Load: iter | test.cpp:61:39:61:51 | ValueNumberBound | -1 | true | CompareLT: ... < ... | test.cpp:66:32:66:41 | test.cpp:66:32:66:41 |
| test.cpp:67:10:67:13 | Load: iter | test.cpp:61:48:61:50 | ValueNumberBound | -1 | true | CompareLT: ... < ... | test.cpp:66:32:66:41 | test.cpp:66:32:66:41 |
| test.cpp:77:12:77:12 | Load: i | file://:0:0:0:0 | 0 | 0 | false | NoReason | file://:0:0:0:0 | file://:0:0:0:0 | | test.cpp:77:12:77:12 | Load: i | file://:0:0:0:0 | 0 | 0 | false | NoReason | file://:0:0:0:0 | file://:0:0:0:0 |
| test.cpp:77:12:77:12 | Load: i | test.cpp:72:15:72:15 | ValueNumberBound | -1 | true | CompareLT: ... < ... | test.cpp:76:20:76:24 | test.cpp:76:20:76:24 | | test.cpp:77:12:77:12 | Load: i | test.cpp:72:15:72:15 | ValueNumberBound | -1 | true | CompareLT: ... < ... | test.cpp:76:20:76:24 | test.cpp:76:20:76:24 |
| test.cpp:77:12:77:12 | Load: i | test.cpp:72:22:72:22 | ValueNumberBound | -1 | true | CompareLT: ... < ... | test.cpp:76:20:76:24 | test.cpp:76:20:76:24 | | test.cpp:77:12:77:12 | Load: i | test.cpp:72:22:72:22 | ValueNumberBound | -1 | true | CompareLT: ... < ... | test.cpp:76:20:76:24 | test.cpp:76:20:76:24 |

View File

@@ -1,2 +1,2 @@
| test.cpp:19:19:19:24 | call to malloc | test.cpp:18:17:18:20 | size | test.cpp:26:18:26:23 | string | test.cpp:26:31:26:39 | (size_t)... | | test.cpp:19:19:19:24 | call to malloc | test.cpp:18:17:18:20 | size | test.cpp:26:18:26:23 | Load | test.cpp:26:31:26:39 | Convert |
| test.cpp:19:19:19:24 | call to malloc | test.cpp:18:17:18:20 | size | test.cpp:30:18:30:23 | string | test.cpp:30:31:30:39 | (size_t)... | | test.cpp:19:19:19:24 | call to malloc | test.cpp:18:17:18:20 | size | test.cpp:30:18:30:23 | Load | test.cpp:30:31:30:39 | Convert |

View File

@@ -1,23 +1,20 @@
| test.cpp:4:17:4:22 | call to malloc | test.cpp:4:24:4:27 | size | test.cpp:10:9:10:11 | arr | test.cpp:4:24:4:27 | size | | test.cpp:4:17:4:22 | call to malloc | test.cpp:4:24:4:27 | size | test.cpp:10:9:10:11 | Load | test.cpp:5:25:5:28 | Load |
| test.cpp:4:17:4:22 | call to malloc | test.cpp:4:24:4:27 | size | test.cpp:10:9:10:11 | arr | test.cpp:4:24:4:27 | size | | test.cpp:4:17:4:22 | call to malloc | test.cpp:4:24:4:27 | size | test.cpp:10:9:10:11 | Load | test.cpp:9:26:9:29 | Load |
| test.cpp:4:17:4:22 | call to malloc | test.cpp:4:24:4:27 | size | test.cpp:10:9:10:11 | arr | test.cpp:5:25:5:28 | size | | test.cpp:4:17:4:22 | call to malloc | test.cpp:5:25:5:28 | size | test.cpp:10:9:10:11 | Load | test.cpp:5:25:5:28 | Load |
| test.cpp:4:17:4:22 | call to malloc | test.cpp:4:24:4:27 | size | test.cpp:10:9:10:11 | arr | test.cpp:5:25:5:28 | size | | test.cpp:4:17:4:22 | call to malloc | test.cpp:5:25:5:28 | size | test.cpp:10:9:10:11 | Load | test.cpp:9:26:9:29 | Load |
| test.cpp:4:17:4:22 | call to malloc | test.cpp:4:24:4:27 | size | test.cpp:10:9:10:11 | arr | test.cpp:9:26:9:29 | size | | test.cpp:4:17:4:22 | call to malloc | test.cpp:9:26:9:29 | size | test.cpp:10:9:10:11 | Load | test.cpp:9:26:9:29 | Load |
| test.cpp:4:17:4:22 | call to malloc | test.cpp:5:25:5:28 | size | test.cpp:10:9:10:11 | arr | test.cpp:5:25:5:28 | size | | test.cpp:22:13:22:18 | call to malloc | test.cpp:21:16:21:19 | size | test.cpp:35:13:35:13 | Load | test.cpp:30:29:30:32 | Load |
| test.cpp:4:17:4:22 | call to malloc | test.cpp:5:25:5:28 | size | test.cpp:10:9:10:11 | arr | test.cpp:5:25:5:28 | size | | test.cpp:22:13:22:18 | call to malloc | test.cpp:21:16:21:19 | size | test.cpp:35:13:35:13 | Load | test.cpp:34:30:34:33 | Load |
| test.cpp:4:17:4:22 | call to malloc | test.cpp:5:25:5:28 | size | test.cpp:10:9:10:11 | arr | test.cpp:9:26:9:29 | size | | test.cpp:22:13:22:18 | call to malloc | test.cpp:21:16:21:19 | size | test.cpp:45:13:45:13 | Load | test.cpp:40:29:40:32 | Load |
| test.cpp:4:17:4:22 | call to malloc | test.cpp:9:26:9:29 | size | test.cpp:10:9:10:11 | arr | test.cpp:9:26:9:29 | size | | test.cpp:22:13:22:18 | call to malloc | test.cpp:21:16:21:19 | size | test.cpp:45:13:45:13 | Load | test.cpp:44:30:44:33 | Load |
| test.cpp:4:17:4:22 | call to malloc | test.cpp:9:26:9:29 | size | test.cpp:10:9:10:11 | arr | test.cpp:9:26:9:29 | size | | test.cpp:56:13:56:18 | call to malloc | test.cpp:55:16:55:19 | size | test.cpp:63:13:63:13 | Load | test.cpp:55:5:55:19 | Store |
| test.cpp:56:13:56:18 | call to malloc | test.cpp:55:16:55:19 | size | test.cpp:63:13:63:13 | p | test.cpp:55:5:55:19 | Store | | test.cpp:56:13:56:18 | call to malloc | test.cpp:55:16:55:19 | size | test.cpp:63:13:63:13 | Load | test.cpp:55:5:55:19 | Store |
| test.cpp:56:13:56:18 | call to malloc | test.cpp:55:16:55:19 | size | test.cpp:63:13:63:13 | p | test.cpp:55:16:55:19 | size | | test.cpp:56:13:56:18 | call to malloc | test.cpp:55:16:55:19 | size | test.cpp:63:13:63:13 | Load | test.cpp:55:16:55:19 | Load |
| test.cpp:56:13:56:18 | call to malloc | test.cpp:55:16:55:19 | size | test.cpp:63:13:63:13 | p | test.cpp:55:16:55:19 | size | | test.cpp:56:13:56:18 | call to malloc | test.cpp:55:16:55:19 | size | test.cpp:63:13:63:13 | Load | test.cpp:56:20:56:23 | Load |
| test.cpp:56:13:56:18 | call to malloc | test.cpp:55:16:55:19 | size | test.cpp:63:13:63:13 | p | test.cpp:56:20:56:23 | size | | test.cpp:56:13:56:18 | call to malloc | test.cpp:55:16:55:19 | size | test.cpp:63:13:63:13 | Load | test.cpp:58:29:58:32 | Load |
| test.cpp:56:13:56:18 | call to malloc | test.cpp:56:20:56:23 | size | test.cpp:63:13:63:13 | p | test.cpp:56:20:56:23 | size | | test.cpp:56:13:56:18 | call to malloc | test.cpp:55:16:55:19 | size | test.cpp:63:13:63:13 | Load | test.cpp:62:30:62:33 | Load |
| test.cpp:56:13:56:18 | call to malloc | test.cpp:56:20:56:23 | size | test.cpp:63:13:63:13 | p | test.cpp:56:20:56:23 | size | | test.cpp:56:13:56:18 | call to malloc | test.cpp:58:29:58:32 | size | test.cpp:63:13:63:13 | Load | test.cpp:58:29:58:32 | Load |
| test.cpp:56:13:56:18 | call to malloc | test.cpp:58:29:58:32 | size | test.cpp:63:13:63:13 | p | test.cpp:58:29:58:32 | size | | test.cpp:56:13:56:18 | call to malloc | test.cpp:62:30:62:33 | size | test.cpp:63:13:63:13 | Load | test.cpp:62:30:62:33 | Load |
| test.cpp:56:13:56:18 | call to malloc | test.cpp:58:29:58:32 | size | test.cpp:63:13:63:13 | p | test.cpp:58:29:58:32 | size | | test.cpp:70:14:70:19 | call to malloc | test.cpp:69:17:69:20 | size | test.cpp:83:14:83:14 | Load | test.cpp:82:31:82:34 | Load |
| test.cpp:56:13:56:18 | call to malloc | test.cpp:62:30:62:33 | size | test.cpp:63:13:63:13 | p | test.cpp:62:30:62:33 | size | | test.cpp:70:14:70:19 | call to malloc | test.cpp:69:17:69:20 | size | test.cpp:93:14:93:14 | Load | test.cpp:88:30:88:33 | Load |
| test.cpp:56:13:56:18 | call to malloc | test.cpp:62:30:62:33 | size | test.cpp:63:13:63:13 | p | test.cpp:62:30:62:33 | size | | test.cpp:70:14:70:19 | call to malloc | test.cpp:69:17:69:20 | size | test.cpp:93:14:93:14 | Load | test.cpp:92:31:92:34 | Load |
| test.cpp:70:14:70:19 | call to malloc | test.cpp:69:17:69:20 | size | test.cpp:83:14:83:14 | p | test.cpp:82:31:82:34 | size |
| test.cpp:70:14:70:19 | call to malloc | test.cpp:69:17:69:20 | size | test.cpp:93:14:93:14 | p | test.cpp:88:30:88:33 | size |
| test.cpp:70:14:70:19 | call to malloc | test.cpp:69:17:69:20 | size | test.cpp:93:14:93:14 | p | test.cpp:92:31:92:34 | size |

View File

@@ -32,7 +32,7 @@ void test2(int size) {
} }
for (int i = 0; i <= arr.size; i++) { for (int i = 0; i <= arr.size; i++) {
arr.p[i] = i; // BAD [NOT DETECTED] arr.p[i] = i; // BAD
} }
} }
@@ -42,7 +42,7 @@ void test3_callee(array_t arr) {
} }
for (int i = 0; i <= arr.size; i++) { for (int i = 0; i <= arr.size; i++) {
arr.p[i] = i; // BAD [NOT DETECTED] arr.p[i] = i; // BAD
} }
} }

View File

@@ -0,0 +1,627 @@
edges
| test.cpp:4:15:4:20 | call to malloc | test.cpp:5:15:5:15 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | ... + ... |
| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | ... + ... |
| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | ... + ... |
| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | ... + ... |
| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | Store |
| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | Store |
| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | Store |
| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | Store |
| test.cpp:5:15:5:15 | Load | test.cpp:6:15:6:15 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:6:15:6:15 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:6:15:6:15 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:6:15:6:15 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:7:16:7:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:7:16:7:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:7:16:7:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:7:16:7:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:20 | ... + ... |
| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:20 | ... + ... |
| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:20 | ... + ... |
| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:20 | ... + ... |
| test.cpp:5:15:5:15 | Load | test.cpp:9:16:9:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:9:16:9:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:9:16:9:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:9:16:9:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:10:16:10:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:10:16:10:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:10:16:10:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:10:16:10:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:11:16:11:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:11:16:11:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:11:16:11:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:11:16:11:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:12:16:12:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:12:16:12:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:12:16:12:16 | Load |
| test.cpp:5:15:5:15 | Load | test.cpp:12:16:12:16 | Load |
| test.cpp:5:15:5:22 | ... + ... | test.cpp:5:15:5:22 | Store |
| test.cpp:5:15:5:22 | ... + ... | test.cpp:5:15:5:22 | Store |
| test.cpp:5:15:5:22 | ... + ... | test.cpp:6:14:6:15 | Load: * ... |
| test.cpp:5:15:5:22 | ... + ... | test.cpp:6:14:6:15 | Load: * ... |
| test.cpp:5:15:5:22 | ... + ... | test.cpp:6:15:6:15 | Load |
| test.cpp:5:15:5:22 | ... + ... | test.cpp:6:15:6:15 | Load |
| test.cpp:5:15:5:22 | ... + ... | test.cpp:7:16:7:16 | Load |
| test.cpp:5:15:5:22 | ... + ... | test.cpp:7:16:7:16 | Load |
| test.cpp:5:15:5:22 | ... + ... | test.cpp:8:14:8:21 | Load: * ... |
| test.cpp:5:15:5:22 | ... + ... | test.cpp:8:14:8:21 | Load: * ... |
| test.cpp:5:15:5:22 | ... + ... | test.cpp:8:16:8:16 | Load |
| test.cpp:5:15:5:22 | ... + ... | test.cpp:8:16:8:16 | Load |
| test.cpp:5:15:5:22 | ... + ... | test.cpp:9:16:9:16 | Load |
| test.cpp:5:15:5:22 | ... + ... | test.cpp:9:16:9:16 | Load |
| test.cpp:5:15:5:22 | ... + ... | test.cpp:10:16:10:16 | Load |
| test.cpp:5:15:5:22 | ... + ... | test.cpp:10:16:10:16 | Load |
| test.cpp:5:15:5:22 | ... + ... | test.cpp:11:16:11:16 | Load |
| test.cpp:5:15:5:22 | ... + ... | test.cpp:11:16:11:16 | Load |
| test.cpp:5:15:5:22 | ... + ... | test.cpp:12:16:12:16 | Load |
| test.cpp:5:15:5:22 | Store | test.cpp:6:14:6:15 | Load: * ... |
| test.cpp:5:15:5:22 | Store | test.cpp:6:14:6:15 | Load: * ... |
| test.cpp:5:15:5:22 | Store | test.cpp:6:15:6:15 | Load |
| test.cpp:5:15:5:22 | Store | test.cpp:6:15:6:15 | Load |
| test.cpp:5:15:5:22 | Store | test.cpp:7:16:7:16 | Load |
| test.cpp:5:15:5:22 | Store | test.cpp:7:16:7:16 | Load |
| test.cpp:5:15:5:22 | Store | test.cpp:8:14:8:21 | Load: * ... |
| test.cpp:5:15:5:22 | Store | test.cpp:8:14:8:21 | Load: * ... |
| test.cpp:5:15:5:22 | Store | test.cpp:8:16:8:16 | Load |
| test.cpp:5:15:5:22 | Store | test.cpp:8:16:8:16 | Load |
| test.cpp:5:15:5:22 | Store | test.cpp:9:16:9:16 | Load |
| test.cpp:5:15:5:22 | Store | test.cpp:9:16:9:16 | Load |
| test.cpp:5:15:5:22 | Store | test.cpp:10:16:10:16 | Load |
| test.cpp:5:15:5:22 | Store | test.cpp:10:16:10:16 | Load |
| test.cpp:5:15:5:22 | Store | test.cpp:11:16:11:16 | Load |
| test.cpp:5:15:5:22 | Store | test.cpp:11:16:11:16 | Load |
| test.cpp:5:15:5:22 | Store | test.cpp:12:16:12:16 | Load |
| test.cpp:6:15:6:15 | Load | test.cpp:6:14:6:15 | Load: * ... |
| test.cpp:6:15:6:15 | Load | test.cpp:6:14:6:15 | Load: * ... |
| test.cpp:6:15:6:15 | Load | test.cpp:7:16:7:16 | Load |
| test.cpp:6:15:6:15 | Load | test.cpp:7:16:7:16 | Load |
| test.cpp:6:15:6:15 | Load | test.cpp:8:14:8:21 | Load: * ... |
| test.cpp:6:15:6:15 | Load | test.cpp:8:14:8:21 | Load: * ... |
| test.cpp:6:15:6:15 | Load | test.cpp:8:16:8:16 | Load |
| test.cpp:6:15:6:15 | Load | test.cpp:8:16:8:16 | Load |
| test.cpp:6:15:6:15 | Load | test.cpp:9:16:9:16 | Load |
| test.cpp:6:15:6:15 | Load | test.cpp:9:16:9:16 | Load |
| test.cpp:6:15:6:15 | Load | test.cpp:10:16:10:16 | Load |
| test.cpp:6:15:6:15 | Load | test.cpp:10:16:10:16 | Load |
| test.cpp:6:15:6:15 | Load | test.cpp:11:16:11:16 | Load |
| test.cpp:6:15:6:15 | Load | test.cpp:11:16:11:16 | Load |
| test.cpp:6:15:6:15 | Load | test.cpp:12:16:12:16 | Load |
| test.cpp:7:16:7:16 | Load | test.cpp:6:14:6:15 | Load: * ... |
| test.cpp:7:16:7:16 | Load | test.cpp:6:14:6:15 | Load: * ... |
| test.cpp:7:16:7:16 | Load | test.cpp:8:14:8:21 | Load: * ... |
| test.cpp:7:16:7:16 | Load | test.cpp:8:14:8:21 | Load: * ... |
| test.cpp:7:16:7:16 | Load | test.cpp:8:16:8:16 | Load |
| test.cpp:7:16:7:16 | Load | test.cpp:8:16:8:16 | Load |
| test.cpp:7:16:7:16 | Load | test.cpp:9:16:9:16 | Load |
| test.cpp:7:16:7:16 | Load | test.cpp:9:16:9:16 | Load |
| test.cpp:7:16:7:16 | Load | test.cpp:10:16:10:16 | Load |
| test.cpp:7:16:7:16 | Load | test.cpp:10:16:10:16 | Load |
| test.cpp:7:16:7:16 | Load | test.cpp:11:16:11:16 | Load |
| test.cpp:7:16:7:16 | Load | test.cpp:11:16:11:16 | Load |
| test.cpp:7:16:7:16 | Load | test.cpp:12:16:12:16 | Load |
| test.cpp:8:16:8:16 | Load | test.cpp:6:14:6:15 | Load: * ... |
| test.cpp:8:16:8:16 | Load | test.cpp:6:14:6:15 | Load: * ... |
| test.cpp:8:16:8:16 | Load | test.cpp:8:14:8:21 | Load: * ... |
| test.cpp:8:16:8:16 | Load | test.cpp:8:14:8:21 | Load: * ... |
| test.cpp:8:16:8:16 | Load | test.cpp:9:16:9:16 | Load |
| test.cpp:8:16:8:16 | Load | test.cpp:9:16:9:16 | Load |
| test.cpp:8:16:8:16 | Load | test.cpp:10:16:10:16 | Load |
| test.cpp:8:16:8:16 | Load | test.cpp:10:16:10:16 | Load |
| test.cpp:8:16:8:16 | Load | test.cpp:11:16:11:16 | Load |
| test.cpp:8:16:8:16 | Load | test.cpp:11:16:11:16 | Load |
| test.cpp:8:16:8:16 | Load | test.cpp:12:16:12:16 | Load |
| test.cpp:8:16:8:20 | ... + ... | test.cpp:8:14:8:21 | Load: * ... |
| test.cpp:8:16:8:20 | ... + ... | test.cpp:8:14:8:21 | Load: * ... |
| test.cpp:9:16:9:16 | Load | test.cpp:6:14:6:15 | Load: * ... |
| test.cpp:9:16:9:16 | Load | test.cpp:6:14:6:15 | Load: * ... |
| test.cpp:9:16:9:16 | Load | test.cpp:8:14:8:21 | Load: * ... |
| test.cpp:9:16:9:16 | Load | test.cpp:8:14:8:21 | Load: * ... |
| test.cpp:9:16:9:16 | Load | test.cpp:10:16:10:16 | Load |
| test.cpp:9:16:9:16 | Load | test.cpp:10:16:10:16 | Load |
| test.cpp:9:16:9:16 | Load | test.cpp:11:16:11:16 | Load |
| test.cpp:9:16:9:16 | Load | test.cpp:11:16:11:16 | Load |
| test.cpp:9:16:9:16 | Load | test.cpp:12:16:12:16 | Load |
| test.cpp:10:16:10:16 | Load | test.cpp:6:14:6:15 | Load: * ... |
| test.cpp:10:16:10:16 | Load | test.cpp:6:14:6:15 | Load: * ... |
| test.cpp:10:16:10:16 | Load | test.cpp:8:14:8:21 | Load: * ... |
| test.cpp:10:16:10:16 | Load | test.cpp:8:14:8:21 | Load: * ... |
| test.cpp:10:16:10:16 | Load | test.cpp:11:16:11:16 | Load |
| test.cpp:10:16:10:16 | Load | test.cpp:11:16:11:16 | Load |
| test.cpp:10:16:10:16 | Load | test.cpp:12:16:12:16 | Load |
| test.cpp:11:16:11:16 | Load | test.cpp:6:14:6:15 | Load: * ... |
| test.cpp:11:16:11:16 | Load | test.cpp:6:14:6:15 | Load: * ... |
| test.cpp:11:16:11:16 | Load | test.cpp:8:14:8:21 | Load: * ... |
| test.cpp:11:16:11:16 | Load | test.cpp:8:14:8:21 | Load: * ... |
| test.cpp:11:16:11:16 | Load | test.cpp:12:16:12:16 | Load |
| test.cpp:12:16:12:16 | Load | test.cpp:6:14:6:15 | Load: * ... |
| test.cpp:12:16:12:16 | Load | test.cpp:6:14:6:15 | Load: * ... |
| test.cpp:12:16:12:16 | Load | test.cpp:8:14:8:21 | Load: * ... |
| test.cpp:12:16:12:16 | Load | test.cpp:8:14:8:21 | Load: * ... |
| test.cpp:16:15:16:20 | call to malloc | test.cpp:17:15:17:15 | Load |
| test.cpp:17:15:17:15 | Load | test.cpp:17:15:17:22 | ... + ... |
| test.cpp:17:15:17:15 | Load | test.cpp:17:15:17:22 | ... + ... |
| test.cpp:17:15:17:15 | Load | test.cpp:17:15:17:22 | ... + ... |
| test.cpp:17:15:17:15 | Load | test.cpp:17:15:17:22 | ... + ... |
| test.cpp:17:15:17:15 | Load | test.cpp:20:16:20:20 | ... + ... |
| test.cpp:17:15:17:15 | Load | test.cpp:20:16:20:20 | ... + ... |
| test.cpp:17:15:17:15 | Load | test.cpp:20:16:20:20 | ... + ... |
| test.cpp:17:15:17:15 | Load | test.cpp:20:16:20:20 | ... + ... |
| test.cpp:17:15:17:22 | ... + ... | test.cpp:20:14:20:21 | Load: * ... |
| test.cpp:17:15:17:22 | ... + ... | test.cpp:20:14:20:21 | Load: * ... |
| test.cpp:20:16:20:20 | ... + ... | test.cpp:20:14:20:21 | Load: * ... |
| test.cpp:20:16:20:20 | ... + ... | test.cpp:20:14:20:21 | Load: * ... |
| test.cpp:28:15:28:20 | call to malloc | test.cpp:29:15:29:15 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | ... + ... |
| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | ... + ... |
| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | ... + ... |
| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | ... + ... |
| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | Store |
| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | Store |
| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | Store |
| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | Store |
| test.cpp:29:15:29:15 | Load | test.cpp:30:15:30:15 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:30:15:30:15 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:30:15:30:15 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:30:15:30:15 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:31:16:31:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:31:16:31:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:31:16:31:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:31:16:31:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:20 | ... + ... |
| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:20 | ... + ... |
| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:20 | ... + ... |
| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:20 | ... + ... |
| test.cpp:29:15:29:15 | Load | test.cpp:33:16:33:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:33:16:33:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:33:16:33:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:33:16:33:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:34:16:34:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:34:16:34:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:34:16:34:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:34:16:34:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:35:16:35:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:35:16:35:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:35:16:35:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:35:16:35:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:36:16:36:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:36:16:36:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:36:16:36:16 | Load |
| test.cpp:29:15:29:15 | Load | test.cpp:36:16:36:16 | Load |
| test.cpp:29:15:29:28 | ... + ... | test.cpp:29:15:29:28 | Store |
| test.cpp:29:15:29:28 | ... + ... | test.cpp:29:15:29:28 | Store |
| test.cpp:29:15:29:28 | ... + ... | test.cpp:30:14:30:15 | Load: * ... |
| test.cpp:29:15:29:28 | ... + ... | test.cpp:30:14:30:15 | Load: * ... |
| test.cpp:29:15:29:28 | ... + ... | test.cpp:30:15:30:15 | Load |
| test.cpp:29:15:29:28 | ... + ... | test.cpp:30:15:30:15 | Load |
| test.cpp:29:15:29:28 | ... + ... | test.cpp:31:16:31:16 | Load |
| test.cpp:29:15:29:28 | ... + ... | test.cpp:31:16:31:16 | Load |
| test.cpp:29:15:29:28 | ... + ... | test.cpp:32:14:32:21 | Load: * ... |
| test.cpp:29:15:29:28 | ... + ... | test.cpp:32:14:32:21 | Load: * ... |
| test.cpp:29:15:29:28 | ... + ... | test.cpp:32:16:32:16 | Load |
| test.cpp:29:15:29:28 | ... + ... | test.cpp:32:16:32:16 | Load |
| test.cpp:29:15:29:28 | ... + ... | test.cpp:33:16:33:16 | Load |
| test.cpp:29:15:29:28 | ... + ... | test.cpp:33:16:33:16 | Load |
| test.cpp:29:15:29:28 | ... + ... | test.cpp:34:16:34:16 | Load |
| test.cpp:29:15:29:28 | ... + ... | test.cpp:34:16:34:16 | Load |
| test.cpp:29:15:29:28 | ... + ... | test.cpp:35:16:35:16 | Load |
| test.cpp:29:15:29:28 | ... + ... | test.cpp:35:16:35:16 | Load |
| test.cpp:29:15:29:28 | ... + ... | test.cpp:36:16:36:16 | Load |
| test.cpp:29:15:29:28 | Store | test.cpp:30:14:30:15 | Load: * ... |
| test.cpp:29:15:29:28 | Store | test.cpp:30:14:30:15 | Load: * ... |
| test.cpp:29:15:29:28 | Store | test.cpp:30:15:30:15 | Load |
| test.cpp:29:15:29:28 | Store | test.cpp:30:15:30:15 | Load |
| test.cpp:29:15:29:28 | Store | test.cpp:31:16:31:16 | Load |
| test.cpp:29:15:29:28 | Store | test.cpp:31:16:31:16 | Load |
| test.cpp:29:15:29:28 | Store | test.cpp:32:14:32:21 | Load: * ... |
| test.cpp:29:15:29:28 | Store | test.cpp:32:14:32:21 | Load: * ... |
| test.cpp:29:15:29:28 | Store | test.cpp:32:16:32:16 | Load |
| test.cpp:29:15:29:28 | Store | test.cpp:32:16:32:16 | Load |
| test.cpp:29:15:29:28 | Store | test.cpp:33:16:33:16 | Load |
| test.cpp:29:15:29:28 | Store | test.cpp:33:16:33:16 | Load |
| test.cpp:29:15:29:28 | Store | test.cpp:34:16:34:16 | Load |
| test.cpp:29:15:29:28 | Store | test.cpp:34:16:34:16 | Load |
| test.cpp:29:15:29:28 | Store | test.cpp:35:16:35:16 | Load |
| test.cpp:29:15:29:28 | Store | test.cpp:35:16:35:16 | Load |
| test.cpp:29:15:29:28 | Store | test.cpp:36:16:36:16 | Load |
| test.cpp:30:15:30:15 | Load | test.cpp:30:14:30:15 | Load: * ... |
| test.cpp:30:15:30:15 | Load | test.cpp:30:14:30:15 | Load: * ... |
| test.cpp:30:15:30:15 | Load | test.cpp:31:16:31:16 | Load |
| test.cpp:30:15:30:15 | Load | test.cpp:31:16:31:16 | Load |
| test.cpp:30:15:30:15 | Load | test.cpp:32:14:32:21 | Load: * ... |
| test.cpp:30:15:30:15 | Load | test.cpp:32:14:32:21 | Load: * ... |
| test.cpp:30:15:30:15 | Load | test.cpp:32:16:32:16 | Load |
| test.cpp:30:15:30:15 | Load | test.cpp:32:16:32:16 | Load |
| test.cpp:30:15:30:15 | Load | test.cpp:33:16:33:16 | Load |
| test.cpp:30:15:30:15 | Load | test.cpp:33:16:33:16 | Load |
| test.cpp:30:15:30:15 | Load | test.cpp:34:16:34:16 | Load |
| test.cpp:30:15:30:15 | Load | test.cpp:34:16:34:16 | Load |
| test.cpp:30:15:30:15 | Load | test.cpp:35:16:35:16 | Load |
| test.cpp:30:15:30:15 | Load | test.cpp:35:16:35:16 | Load |
| test.cpp:30:15:30:15 | Load | test.cpp:36:16:36:16 | Load |
| test.cpp:31:16:31:16 | Load | test.cpp:30:14:30:15 | Load: * ... |
| test.cpp:31:16:31:16 | Load | test.cpp:30:14:30:15 | Load: * ... |
| test.cpp:31:16:31:16 | Load | test.cpp:32:14:32:21 | Load: * ... |
| test.cpp:31:16:31:16 | Load | test.cpp:32:14:32:21 | Load: * ... |
| test.cpp:31:16:31:16 | Load | test.cpp:32:16:32:16 | Load |
| test.cpp:31:16:31:16 | Load | test.cpp:32:16:32:16 | Load |
| test.cpp:31:16:31:16 | Load | test.cpp:33:16:33:16 | Load |
| test.cpp:31:16:31:16 | Load | test.cpp:33:16:33:16 | Load |
| test.cpp:31:16:31:16 | Load | test.cpp:34:16:34:16 | Load |
| test.cpp:31:16:31:16 | Load | test.cpp:34:16:34:16 | Load |
| test.cpp:31:16:31:16 | Load | test.cpp:35:16:35:16 | Load |
| test.cpp:31:16:31:16 | Load | test.cpp:35:16:35:16 | Load |
| test.cpp:31:16:31:16 | Load | test.cpp:36:16:36:16 | Load |
| test.cpp:32:16:32:16 | Load | test.cpp:30:14:30:15 | Load: * ... |
| test.cpp:32:16:32:16 | Load | test.cpp:30:14:30:15 | Load: * ... |
| test.cpp:32:16:32:16 | Load | test.cpp:32:14:32:21 | Load: * ... |
| test.cpp:32:16:32:16 | Load | test.cpp:32:14:32:21 | Load: * ... |
| test.cpp:32:16:32:16 | Load | test.cpp:33:16:33:16 | Load |
| test.cpp:32:16:32:16 | Load | test.cpp:33:16:33:16 | Load |
| test.cpp:32:16:32:16 | Load | test.cpp:34:16:34:16 | Load |
| test.cpp:32:16:32:16 | Load | test.cpp:34:16:34:16 | Load |
| test.cpp:32:16:32:16 | Load | test.cpp:35:16:35:16 | Load |
| test.cpp:32:16:32:16 | Load | test.cpp:35:16:35:16 | Load |
| test.cpp:32:16:32:16 | Load | test.cpp:36:16:36:16 | Load |
| test.cpp:32:16:32:20 | ... + ... | test.cpp:32:14:32:21 | Load: * ... |
| test.cpp:32:16:32:20 | ... + ... | test.cpp:32:14:32:21 | Load: * ... |
| test.cpp:33:16:33:16 | Load | test.cpp:30:14:30:15 | Load: * ... |
| test.cpp:33:16:33:16 | Load | test.cpp:30:14:30:15 | Load: * ... |
| test.cpp:33:16:33:16 | Load | test.cpp:32:14:32:21 | Load: * ... |
| test.cpp:33:16:33:16 | Load | test.cpp:32:14:32:21 | Load: * ... |
| test.cpp:33:16:33:16 | Load | test.cpp:34:16:34:16 | Load |
| test.cpp:33:16:33:16 | Load | test.cpp:34:16:34:16 | Load |
| test.cpp:33:16:33:16 | Load | test.cpp:35:16:35:16 | Load |
| test.cpp:33:16:33:16 | Load | test.cpp:35:16:35:16 | Load |
| test.cpp:33:16:33:16 | Load | test.cpp:36:16:36:16 | Load |
| test.cpp:34:16:34:16 | Load | test.cpp:30:14:30:15 | Load: * ... |
| test.cpp:34:16:34:16 | Load | test.cpp:30:14:30:15 | Load: * ... |
| test.cpp:34:16:34:16 | Load | test.cpp:32:14:32:21 | Load: * ... |
| test.cpp:34:16:34:16 | Load | test.cpp:32:14:32:21 | Load: * ... |
| test.cpp:34:16:34:16 | Load | test.cpp:35:16:35:16 | Load |
| test.cpp:34:16:34:16 | Load | test.cpp:35:16:35:16 | Load |
| test.cpp:34:16:34:16 | Load | test.cpp:36:16:36:16 | Load |
| test.cpp:35:16:35:16 | Load | test.cpp:30:14:30:15 | Load: * ... |
| test.cpp:35:16:35:16 | Load | test.cpp:30:14:30:15 | Load: * ... |
| test.cpp:35:16:35:16 | Load | test.cpp:32:14:32:21 | Load: * ... |
| test.cpp:35:16:35:16 | Load | test.cpp:32:14:32:21 | Load: * ... |
| test.cpp:35:16:35:16 | Load | test.cpp:36:16:36:16 | Load |
| test.cpp:36:16:36:16 | Load | test.cpp:30:14:30:15 | Load: * ... |
| test.cpp:36:16:36:16 | Load | test.cpp:30:14:30:15 | Load: * ... |
| test.cpp:36:16:36:16 | Load | test.cpp:32:14:32:21 | Load: * ... |
| test.cpp:36:16:36:16 | Load | test.cpp:32:14:32:21 | Load: * ... |
| test.cpp:40:15:40:20 | call to malloc | test.cpp:41:15:41:15 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | ... + ... |
| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | ... + ... |
| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | ... + ... |
| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | ... + ... |
| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | Store |
| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | Store |
| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | Store |
| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | Store |
| test.cpp:41:15:41:15 | Load | test.cpp:42:15:42:15 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:42:15:42:15 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:42:15:42:15 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:42:15:42:15 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:43:16:43:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:43:16:43:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:43:16:43:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:43:16:43:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:20 | ... + ... |
| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:20 | ... + ... |
| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:20 | ... + ... |
| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:20 | ... + ... |
| test.cpp:41:15:41:15 | Load | test.cpp:45:16:45:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:45:16:45:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:45:16:45:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:45:16:45:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:46:16:46:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:46:16:46:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:46:16:46:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:46:16:46:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:47:16:47:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:47:16:47:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:47:16:47:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:47:16:47:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:48:16:48:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:48:16:48:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:48:16:48:16 | Load |
| test.cpp:41:15:41:15 | Load | test.cpp:48:16:48:16 | Load |
| test.cpp:41:15:41:28 | ... + ... | test.cpp:41:15:41:28 | Store |
| test.cpp:41:15:41:28 | ... + ... | test.cpp:41:15:41:28 | Store |
| test.cpp:41:15:41:28 | ... + ... | test.cpp:42:14:42:15 | Load: * ... |
| test.cpp:41:15:41:28 | ... + ... | test.cpp:42:14:42:15 | Load: * ... |
| test.cpp:41:15:41:28 | ... + ... | test.cpp:42:15:42:15 | Load |
| test.cpp:41:15:41:28 | ... + ... | test.cpp:42:15:42:15 | Load |
| test.cpp:41:15:41:28 | ... + ... | test.cpp:43:16:43:16 | Load |
| test.cpp:41:15:41:28 | ... + ... | test.cpp:43:16:43:16 | Load |
| test.cpp:41:15:41:28 | ... + ... | test.cpp:44:14:44:21 | Load: * ... |
| test.cpp:41:15:41:28 | ... + ... | test.cpp:44:14:44:21 | Load: * ... |
| test.cpp:41:15:41:28 | ... + ... | test.cpp:44:16:44:16 | Load |
| test.cpp:41:15:41:28 | ... + ... | test.cpp:44:16:44:16 | Load |
| test.cpp:41:15:41:28 | ... + ... | test.cpp:45:16:45:16 | Load |
| test.cpp:41:15:41:28 | ... + ... | test.cpp:45:16:45:16 | Load |
| test.cpp:41:15:41:28 | ... + ... | test.cpp:46:16:46:16 | Load |
| test.cpp:41:15:41:28 | ... + ... | test.cpp:46:16:46:16 | Load |
| test.cpp:41:15:41:28 | ... + ... | test.cpp:47:16:47:16 | Load |
| test.cpp:41:15:41:28 | ... + ... | test.cpp:47:16:47:16 | Load |
| test.cpp:41:15:41:28 | ... + ... | test.cpp:48:16:48:16 | Load |
| test.cpp:41:15:41:28 | Store | test.cpp:42:14:42:15 | Load: * ... |
| test.cpp:41:15:41:28 | Store | test.cpp:42:14:42:15 | Load: * ... |
| test.cpp:41:15:41:28 | Store | test.cpp:42:15:42:15 | Load |
| test.cpp:41:15:41:28 | Store | test.cpp:42:15:42:15 | Load |
| test.cpp:41:15:41:28 | Store | test.cpp:43:16:43:16 | Load |
| test.cpp:41:15:41:28 | Store | test.cpp:43:16:43:16 | Load |
| test.cpp:41:15:41:28 | Store | test.cpp:44:14:44:21 | Load: * ... |
| test.cpp:41:15:41:28 | Store | test.cpp:44:14:44:21 | Load: * ... |
| test.cpp:41:15:41:28 | Store | test.cpp:44:16:44:16 | Load |
| test.cpp:41:15:41:28 | Store | test.cpp:44:16:44:16 | Load |
| test.cpp:41:15:41:28 | Store | test.cpp:45:16:45:16 | Load |
| test.cpp:41:15:41:28 | Store | test.cpp:45:16:45:16 | Load |
| test.cpp:41:15:41:28 | Store | test.cpp:46:16:46:16 | Load |
| test.cpp:41:15:41:28 | Store | test.cpp:46:16:46:16 | Load |
| test.cpp:41:15:41:28 | Store | test.cpp:47:16:47:16 | Load |
| test.cpp:41:15:41:28 | Store | test.cpp:47:16:47:16 | Load |
| test.cpp:41:15:41:28 | Store | test.cpp:48:16:48:16 | Load |
| test.cpp:42:15:42:15 | Load | test.cpp:42:14:42:15 | Load: * ... |
| test.cpp:42:15:42:15 | Load | test.cpp:42:14:42:15 | Load: * ... |
| test.cpp:42:15:42:15 | Load | test.cpp:43:16:43:16 | Load |
| test.cpp:42:15:42:15 | Load | test.cpp:43:16:43:16 | Load |
| test.cpp:42:15:42:15 | Load | test.cpp:44:14:44:21 | Load: * ... |
| test.cpp:42:15:42:15 | Load | test.cpp:44:14:44:21 | Load: * ... |
| test.cpp:42:15:42:15 | Load | test.cpp:44:16:44:16 | Load |
| test.cpp:42:15:42:15 | Load | test.cpp:44:16:44:16 | Load |
| test.cpp:42:15:42:15 | Load | test.cpp:45:16:45:16 | Load |
| test.cpp:42:15:42:15 | Load | test.cpp:45:16:45:16 | Load |
| test.cpp:42:15:42:15 | Load | test.cpp:46:16:46:16 | Load |
| test.cpp:42:15:42:15 | Load | test.cpp:46:16:46:16 | Load |
| test.cpp:42:15:42:15 | Load | test.cpp:47:16:47:16 | Load |
| test.cpp:42:15:42:15 | Load | test.cpp:47:16:47:16 | Load |
| test.cpp:42:15:42:15 | Load | test.cpp:48:16:48:16 | Load |
| test.cpp:43:16:43:16 | Load | test.cpp:42:14:42:15 | Load: * ... |
| test.cpp:43:16:43:16 | Load | test.cpp:42:14:42:15 | Load: * ... |
| test.cpp:43:16:43:16 | Load | test.cpp:44:14:44:21 | Load: * ... |
| test.cpp:43:16:43:16 | Load | test.cpp:44:14:44:21 | Load: * ... |
| test.cpp:43:16:43:16 | Load | test.cpp:44:16:44:16 | Load |
| test.cpp:43:16:43:16 | Load | test.cpp:44:16:44:16 | Load |
| test.cpp:43:16:43:16 | Load | test.cpp:45:16:45:16 | Load |
| test.cpp:43:16:43:16 | Load | test.cpp:45:16:45:16 | Load |
| test.cpp:43:16:43:16 | Load | test.cpp:46:16:46:16 | Load |
| test.cpp:43:16:43:16 | Load | test.cpp:46:16:46:16 | Load |
| test.cpp:43:16:43:16 | Load | test.cpp:47:16:47:16 | Load |
| test.cpp:43:16:43:16 | Load | test.cpp:47:16:47:16 | Load |
| test.cpp:43:16:43:16 | Load | test.cpp:48:16:48:16 | Load |
| test.cpp:44:16:44:16 | Load | test.cpp:42:14:42:15 | Load: * ... |
| test.cpp:44:16:44:16 | Load | test.cpp:42:14:42:15 | Load: * ... |
| test.cpp:44:16:44:16 | Load | test.cpp:44:14:44:21 | Load: * ... |
| test.cpp:44:16:44:16 | Load | test.cpp:44:14:44:21 | Load: * ... |
| test.cpp:44:16:44:16 | Load | test.cpp:45:16:45:16 | Load |
| test.cpp:44:16:44:16 | Load | test.cpp:45:16:45:16 | Load |
| test.cpp:44:16:44:16 | Load | test.cpp:46:16:46:16 | Load |
| test.cpp:44:16:44:16 | Load | test.cpp:46:16:46:16 | Load |
| test.cpp:44:16:44:16 | Load | test.cpp:47:16:47:16 | Load |
| test.cpp:44:16:44:16 | Load | test.cpp:47:16:47:16 | Load |
| test.cpp:44:16:44:16 | Load | test.cpp:48:16:48:16 | Load |
| test.cpp:44:16:44:20 | ... + ... | test.cpp:44:14:44:21 | Load: * ... |
| test.cpp:44:16:44:20 | ... + ... | test.cpp:44:14:44:21 | Load: * ... |
| test.cpp:45:16:45:16 | Load | test.cpp:42:14:42:15 | Load: * ... |
| test.cpp:45:16:45:16 | Load | test.cpp:42:14:42:15 | Load: * ... |
| test.cpp:45:16:45:16 | Load | test.cpp:44:14:44:21 | Load: * ... |
| test.cpp:45:16:45:16 | Load | test.cpp:44:14:44:21 | Load: * ... |
| test.cpp:45:16:45:16 | Load | test.cpp:46:16:46:16 | Load |
| test.cpp:45:16:45:16 | Load | test.cpp:46:16:46:16 | Load |
| test.cpp:45:16:45:16 | Load | test.cpp:47:16:47:16 | Load |
| test.cpp:45:16:45:16 | Load | test.cpp:47:16:47:16 | Load |
| test.cpp:45:16:45:16 | Load | test.cpp:48:16:48:16 | Load |
| test.cpp:46:16:46:16 | Load | test.cpp:42:14:42:15 | Load: * ... |
| test.cpp:46:16:46:16 | Load | test.cpp:42:14:42:15 | Load: * ... |
| test.cpp:46:16:46:16 | Load | test.cpp:44:14:44:21 | Load: * ... |
| test.cpp:46:16:46:16 | Load | test.cpp:44:14:44:21 | Load: * ... |
| test.cpp:46:16:46:16 | Load | test.cpp:47:16:47:16 | Load |
| test.cpp:46:16:46:16 | Load | test.cpp:47:16:47:16 | Load |
| test.cpp:46:16:46:16 | Load | test.cpp:48:16:48:16 | Load |
| test.cpp:47:16:47:16 | Load | test.cpp:42:14:42:15 | Load: * ... |
| test.cpp:47:16:47:16 | Load | test.cpp:42:14:42:15 | Load: * ... |
| test.cpp:47:16:47:16 | Load | test.cpp:44:14:44:21 | Load: * ... |
| test.cpp:47:16:47:16 | Load | test.cpp:44:14:44:21 | Load: * ... |
| test.cpp:47:16:47:16 | Load | test.cpp:48:16:48:16 | Load |
| test.cpp:48:16:48:16 | Load | test.cpp:42:14:42:15 | Load: * ... |
| test.cpp:48:16:48:16 | Load | test.cpp:42:14:42:15 | Load: * ... |
| test.cpp:48:16:48:16 | Load | test.cpp:44:14:44:21 | Load: * ... |
| test.cpp:48:16:48:16 | Load | test.cpp:44:14:44:21 | Load: * ... |
| test.cpp:51:7:51:14 | VariableAddress indirection | test.cpp:62:39:62:39 | Load |
| test.cpp:51:7:51:14 | VariableAddress indirection | test.cpp:66:39:66:39 | Load |
| test.cpp:51:7:51:14 | VariableAddress indirection | test.cpp:70:38:70:38 | Load |
| test.cpp:51:33:51:35 | Load indirection | test.cpp:60:34:60:37 | mk_array output argument |
| test.cpp:52:19:52:24 | call to malloc | test.cpp:51:7:51:14 | VariableAddress indirection |
| test.cpp:52:19:52:24 | call to malloc | test.cpp:53:12:53:16 | Load |
| test.cpp:53:5:53:23 | Store | test.cpp:51:33:51:35 | Load indirection |
| test.cpp:53:12:53:16 | Load | test.cpp:53:5:53:23 | Store |
| test.cpp:53:12:53:16 | Load | test.cpp:53:5:53:23 | Store |
| test.cpp:53:12:53:16 | Load | test.cpp:53:12:53:23 | ... + ... |
| test.cpp:53:12:53:16 | Load | test.cpp:53:12:53:23 | ... + ... |
| test.cpp:53:12:53:23 | ... + ... | test.cpp:51:33:51:35 | Load indirection |
| test.cpp:60:34:60:37 | mk_array output argument | test.cpp:62:32:62:34 | Load |
| test.cpp:60:34:60:37 | mk_array output argument | test.cpp:66:32:66:34 | Load |
| test.cpp:60:34:60:37 | mk_array output argument | test.cpp:70:31:70:33 | Load |
| test.cpp:62:32:62:34 | Load | test.cpp:67:9:67:14 | Store: ... = ... |
| test.cpp:62:32:62:34 | Load | test.cpp:67:9:67:14 | Store: ... = ... |
| test.cpp:66:32:66:34 | Load | test.cpp:67:9:67:14 | Store: ... = ... |
| test.cpp:66:32:66:34 | Load | test.cpp:67:9:67:14 | Store: ... = ... |
| test.cpp:70:31:70:33 | Load | test.cpp:67:9:67:14 | Store: ... = ... |
| test.cpp:70:31:70:33 | Load | test.cpp:67:9:67:14 | Store: ... = ... |
| test.cpp:80:9:80:16 | VariableAddress indirection [begin] | test.cpp:91:20:91:22 | arr indirection [begin] |
| test.cpp:80:9:80:16 | VariableAddress indirection [begin] | test.cpp:95:20:95:22 | arr indirection [begin] |
| test.cpp:80:9:80:16 | VariableAddress indirection [begin] | test.cpp:99:20:99:22 | arr indirection [begin] |
| test.cpp:80:9:80:16 | VariableAddress indirection [begin] | test.cpp:119:18:119:25 | call to mk_array [begin] |
| test.cpp:80:9:80:16 | VariableAddress indirection [end] | test.cpp:91:36:91:38 | arr indirection [end] |
| test.cpp:80:9:80:16 | VariableAddress indirection [end] | test.cpp:95:36:95:38 | arr indirection [end] |
| test.cpp:80:9:80:16 | VariableAddress indirection [end] | test.cpp:99:35:99:37 | arr indirection [end] |
| test.cpp:80:9:80:16 | VariableAddress indirection [end] | test.cpp:119:18:119:25 | call to mk_array [end] |
| test.cpp:82:5:82:28 | Store | test.cpp:82:9:82:13 | arr indirection [post update] [begin] |
| test.cpp:82:9:82:13 | arr indirection [post update] [begin] | test.cpp:80:9:80:16 | VariableAddress indirection [begin] |
| test.cpp:82:9:82:13 | arr indirection [post update] [begin] | test.cpp:83:15:83:17 | arr indirection [begin] |
| test.cpp:82:17:82:22 | call to malloc | test.cpp:82:5:82:28 | Store |
| test.cpp:83:5:83:30 | Store | test.cpp:83:9:83:11 | arr indirection [post update] [end] |
| test.cpp:83:9:83:11 | arr indirection [post update] [end] | test.cpp:80:9:80:16 | VariableAddress indirection [end] |
| test.cpp:83:15:83:17 | arr indirection [begin] | test.cpp:83:19:83:23 | begin |
| test.cpp:83:15:83:30 | ... + ... | test.cpp:83:5:83:30 | Store |
| test.cpp:83:19:83:23 | Load | test.cpp:83:5:83:30 | Store |
| test.cpp:83:19:83:23 | Load | test.cpp:83:5:83:30 | Store |
| test.cpp:83:19:83:23 | Load | test.cpp:83:15:83:30 | ... + ... |
| test.cpp:83:19:83:23 | Load | test.cpp:83:15:83:30 | ... + ... |
| test.cpp:83:19:83:23 | begin | test.cpp:83:19:83:23 | Load |
| test.cpp:91:20:91:22 | arr indirection [begin] | test.cpp:91:24:91:28 | begin |
| test.cpp:91:20:91:22 | arr indirection [begin] | test.cpp:91:47:91:47 | Load |
| test.cpp:91:24:91:28 | begin | test.cpp:91:47:91:47 | Load |
| test.cpp:91:36:91:38 | arr indirection [end] | test.cpp:91:40:91:42 | end |
| test.cpp:91:40:91:42 | Load | test.cpp:96:9:96:14 | Store: ... = ... |
| test.cpp:91:40:91:42 | Load | test.cpp:96:9:96:14 | Store: ... = ... |
| test.cpp:91:40:91:42 | end | test.cpp:91:40:91:42 | Load |
| test.cpp:95:20:95:22 | arr indirection [begin] | test.cpp:95:24:95:28 | begin |
| test.cpp:95:20:95:22 | arr indirection [begin] | test.cpp:95:47:95:47 | Load |
| test.cpp:95:24:95:28 | begin | test.cpp:95:47:95:47 | Load |
| test.cpp:95:36:95:38 | arr indirection [end] | test.cpp:95:40:95:42 | end |
| test.cpp:95:40:95:42 | Load | test.cpp:96:9:96:14 | Store: ... = ... |
| test.cpp:95:40:95:42 | Load | test.cpp:96:9:96:14 | Store: ... = ... |
| test.cpp:95:40:95:42 | end | test.cpp:95:40:95:42 | Load |
| test.cpp:99:20:99:22 | arr indirection [begin] | test.cpp:99:24:99:28 | begin |
| test.cpp:99:20:99:22 | arr indirection [begin] | test.cpp:99:46:99:46 | Load |
| test.cpp:99:24:99:28 | begin | test.cpp:99:46:99:46 | Load |
| test.cpp:99:35:99:37 | arr indirection [end] | test.cpp:99:39:99:41 | end |
| test.cpp:99:39:99:41 | Load | test.cpp:96:9:96:14 | Store: ... = ... |
| test.cpp:99:39:99:41 | Load | test.cpp:96:9:96:14 | Store: ... = ... |
| test.cpp:99:39:99:41 | end | test.cpp:99:39:99:41 | Load |
| test.cpp:104:27:104:29 | arr [begin] | test.cpp:105:20:105:22 | arr indirection [begin] |
| test.cpp:104:27:104:29 | arr [begin] | test.cpp:109:20:109:22 | arr indirection [begin] |
| test.cpp:104:27:104:29 | arr [begin] | test.cpp:113:20:113:22 | arr indirection [begin] |
| test.cpp:104:27:104:29 | arr [end] | test.cpp:105:36:105:38 | arr indirection [end] |
| test.cpp:104:27:104:29 | arr [end] | test.cpp:109:36:109:38 | arr indirection [end] |
| test.cpp:104:27:104:29 | arr [end] | test.cpp:113:35:113:37 | arr indirection [end] |
| test.cpp:105:20:105:22 | arr indirection [begin] | test.cpp:105:24:105:28 | begin |
| test.cpp:105:20:105:22 | arr indirection [begin] | test.cpp:105:47:105:47 | Load |
| test.cpp:105:24:105:28 | begin | test.cpp:105:47:105:47 | Load |
| test.cpp:105:36:105:38 | arr indirection [end] | test.cpp:105:40:105:42 | end |
| test.cpp:105:40:105:42 | Load | test.cpp:110:9:110:14 | Store: ... = ... |
| test.cpp:105:40:105:42 | Load | test.cpp:110:9:110:14 | Store: ... = ... |
| test.cpp:105:40:105:42 | end | test.cpp:105:40:105:42 | Load |
| test.cpp:109:20:109:22 | arr indirection [begin] | test.cpp:109:24:109:28 | begin |
| test.cpp:109:20:109:22 | arr indirection [begin] | test.cpp:109:47:109:47 | Load |
| test.cpp:109:24:109:28 | begin | test.cpp:109:47:109:47 | Load |
| test.cpp:109:36:109:38 | arr indirection [end] | test.cpp:109:40:109:42 | end |
| test.cpp:109:40:109:42 | Load | test.cpp:110:9:110:14 | Store: ... = ... |
| test.cpp:109:40:109:42 | Load | test.cpp:110:9:110:14 | Store: ... = ... |
| test.cpp:109:40:109:42 | end | test.cpp:109:40:109:42 | Load |
| test.cpp:113:20:113:22 | arr indirection [begin] | test.cpp:113:24:113:28 | begin |
| test.cpp:113:20:113:22 | arr indirection [begin] | test.cpp:113:46:113:46 | Load |
| test.cpp:113:24:113:28 | begin | test.cpp:113:46:113:46 | Load |
| test.cpp:113:35:113:37 | arr indirection [end] | test.cpp:113:39:113:41 | end |
| test.cpp:113:39:113:41 | Load | test.cpp:110:9:110:14 | Store: ... = ... |
| test.cpp:113:39:113:41 | Load | test.cpp:110:9:110:14 | Store: ... = ... |
| test.cpp:113:39:113:41 | end | test.cpp:113:39:113:41 | Load |
| test.cpp:119:18:119:25 | call to mk_array [begin] | test.cpp:104:27:104:29 | arr [begin] |
| test.cpp:119:18:119:25 | call to mk_array [end] | test.cpp:104:27:104:29 | arr [end] |
| test.cpp:124:15:124:20 | call to malloc | test.cpp:125:5:125:17 | Store |
| test.cpp:124:15:124:20 | call to malloc | test.cpp:126:15:126:15 | Load |
| test.cpp:125:5:125:17 | Store | test.cpp:125:9:125:13 | arr indirection [post update] [begin] |
| test.cpp:125:9:125:13 | arr indirection [post update] [begin] | test.cpp:129:11:129:13 | arr indirection [begin] |
| test.cpp:125:9:125:13 | arr indirection [post update] [begin] | test.cpp:133:11:133:13 | arr indirection [begin] |
| test.cpp:125:9:125:13 | arr indirection [post update] [begin] | test.cpp:137:11:137:13 | arr indirection [begin] |
| test.cpp:129:11:129:13 | arr indirection [begin] | test.cpp:129:15:129:19 | begin |
| test.cpp:129:15:129:19 | begin | test.cpp:129:15:129:19 | Load |
| test.cpp:133:11:133:13 | arr indirection [begin] | test.cpp:133:15:133:19 | begin |
| test.cpp:133:15:133:19 | begin | test.cpp:133:15:133:19 | Load |
| test.cpp:137:11:137:13 | arr indirection [begin] | test.cpp:137:15:137:19 | begin |
| test.cpp:137:15:137:19 | begin | test.cpp:137:15:137:19 | Load |
| test.cpp:141:10:141:19 | VariableAddress indirection [begin] | test.cpp:150:20:150:29 | Call indirection [begin] |
| test.cpp:141:10:141:19 | VariableAddress indirection [begin] | test.cpp:180:19:180:28 | call to mk_array_p indirection [begin] |
| test.cpp:141:10:141:19 | VariableAddress indirection [end] | test.cpp:150:20:150:29 | Call indirection [end] |
| test.cpp:141:10:141:19 | VariableAddress indirection [end] | test.cpp:180:19:180:28 | call to mk_array_p indirection [end] |
| test.cpp:143:5:143:29 | Store | test.cpp:143:10:143:14 | Load indirection [post update] [begin] |
| test.cpp:143:10:143:14 | Load indirection [post update] [begin] | test.cpp:141:10:141:19 | VariableAddress indirection [begin] |
| test.cpp:143:10:143:14 | Load indirection [post update] [begin] | test.cpp:144:16:144:18 | Load indirection [begin] |
| test.cpp:143:18:143:23 | call to malloc | test.cpp:143:5:143:29 | Store |
| test.cpp:144:5:144:32 | Store | test.cpp:144:10:144:12 | Load indirection [post update] [end] |
| test.cpp:144:10:144:12 | Load indirection [post update] [end] | test.cpp:141:10:141:19 | VariableAddress indirection [end] |
| test.cpp:144:16:144:18 | Load indirection [begin] | test.cpp:144:21:144:25 | begin |
| test.cpp:144:16:144:32 | ... + ... | test.cpp:144:5:144:32 | Store |
| test.cpp:144:21:144:25 | Load | test.cpp:144:5:144:32 | Store |
| test.cpp:144:21:144:25 | Load | test.cpp:144:5:144:32 | Store |
| test.cpp:144:21:144:25 | Load | test.cpp:144:16:144:32 | ... + ... |
| test.cpp:144:21:144:25 | Load | test.cpp:144:16:144:32 | ... + ... |
| test.cpp:144:21:144:25 | begin | test.cpp:144:21:144:25 | Load |
| test.cpp:150:20:150:29 | Call indirection [begin] | test.cpp:152:20:152:22 | Load indirection [begin] |
| test.cpp:150:20:150:29 | Call indirection [begin] | test.cpp:156:20:156:22 | Load indirection [begin] |
| test.cpp:150:20:150:29 | Call indirection [begin] | test.cpp:160:20:160:22 | Load indirection [begin] |
| test.cpp:150:20:150:29 | Call indirection [end] | test.cpp:156:37:156:39 | Load indirection [end] |
| test.cpp:152:20:152:22 | Load indirection [begin] | test.cpp:152:25:152:29 | begin |
| test.cpp:152:20:152:22 | Load indirection [begin] | test.cpp:152:49:152:49 | Load |
| test.cpp:152:25:152:29 | begin | test.cpp:152:49:152:49 | Load |
| test.cpp:156:20:156:22 | Load indirection [begin] | test.cpp:156:25:156:29 | begin |
| test.cpp:156:20:156:22 | Load indirection [begin] | test.cpp:156:49:156:49 | Load |
| test.cpp:156:25:156:29 | begin | test.cpp:156:49:156:49 | Load |
| test.cpp:156:37:156:39 | Load indirection [end] | test.cpp:156:42:156:44 | end |
| test.cpp:156:42:156:44 | Load | test.cpp:157:9:157:14 | Store: ... = ... |
| test.cpp:156:42:156:44 | Load | test.cpp:157:9:157:14 | Store: ... = ... |
| test.cpp:156:42:156:44 | end | test.cpp:156:42:156:44 | Load |
| test.cpp:160:20:160:22 | Load indirection [begin] | test.cpp:160:25:160:29 | begin |
| test.cpp:160:20:160:22 | Load indirection [begin] | test.cpp:160:48:160:48 | Load |
| test.cpp:160:25:160:29 | begin | test.cpp:160:48:160:48 | Load |
| test.cpp:165:29:165:31 | arr indirection [begin] | test.cpp:166:20:166:22 | Load indirection [begin] |
| test.cpp:165:29:165:31 | arr indirection [begin] | test.cpp:170:20:170:22 | Load indirection [begin] |
| test.cpp:165:29:165:31 | arr indirection [begin] | test.cpp:174:20:174:22 | Load indirection [begin] |
| test.cpp:165:29:165:31 | arr indirection [end] | test.cpp:166:37:166:39 | Load indirection [end] |
| test.cpp:165:29:165:31 | arr indirection [end] | test.cpp:170:37:170:39 | Load indirection [end] |
| test.cpp:165:29:165:31 | arr indirection [end] | test.cpp:174:36:174:38 | Load indirection [end] |
| test.cpp:166:20:166:22 | Load indirection [begin] | test.cpp:166:25:166:29 | begin |
| test.cpp:166:20:166:22 | Load indirection [begin] | test.cpp:166:49:166:49 | Load |
| test.cpp:166:25:166:29 | begin | test.cpp:166:49:166:49 | Load |
| test.cpp:166:37:166:39 | Load indirection [end] | test.cpp:166:42:166:44 | end |
| test.cpp:166:42:166:44 | Load | test.cpp:171:9:171:14 | Store: ... = ... |
| test.cpp:166:42:166:44 | Load | test.cpp:171:9:171:14 | Store: ... = ... |
| test.cpp:166:42:166:44 | end | test.cpp:166:42:166:44 | Load |
| test.cpp:170:20:170:22 | Load indirection [begin] | test.cpp:170:25:170:29 | begin |
| test.cpp:170:20:170:22 | Load indirection [begin] | test.cpp:170:49:170:49 | Load |
| test.cpp:170:25:170:29 | begin | test.cpp:170:49:170:49 | Load |
| test.cpp:170:37:170:39 | Load indirection [end] | test.cpp:170:42:170:44 | end |
| test.cpp:170:42:170:44 | Load | test.cpp:171:9:171:14 | Store: ... = ... |
| test.cpp:170:42:170:44 | Load | test.cpp:171:9:171:14 | Store: ... = ... |
| test.cpp:170:42:170:44 | end | test.cpp:170:42:170:44 | Load |
| test.cpp:174:20:174:22 | Load indirection [begin] | test.cpp:174:25:174:29 | begin |
| test.cpp:174:20:174:22 | Load indirection [begin] | test.cpp:174:48:174:48 | Load |
| test.cpp:174:25:174:29 | begin | test.cpp:174:48:174:48 | Load |
| test.cpp:174:36:174:38 | Load indirection [end] | test.cpp:174:41:174:43 | end |
| test.cpp:174:41:174:43 | Load | test.cpp:171:9:171:14 | Store: ... = ... |
| test.cpp:174:41:174:43 | Load | test.cpp:171:9:171:14 | Store: ... = ... |
| test.cpp:174:41:174:43 | end | test.cpp:174:41:174:43 | Load |
| test.cpp:180:19:180:28 | call to mk_array_p indirection [begin] | test.cpp:165:29:165:31 | arr indirection [begin] |
| test.cpp:180:19:180:28 | call to mk_array_p indirection [end] | test.cpp:165:29:165:31 | arr indirection [end] |
| test.cpp:188:15:188:20 | call to malloc | test.cpp:189:15:189:15 | Load |
#select
| test.cpp:6:14:6:15 | Load: * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:6:14:6:15 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:4:15:4:20 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size |
| test.cpp:8:14:8:21 | Load: * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:8:14:8:21 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:4:15:4:20 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size |
| test.cpp:8:14:8:21 | Load: * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:8:14:8:21 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:4:15:4:20 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size |
| test.cpp:20:14:20:21 | Load: * ... | test.cpp:16:15:16:20 | call to malloc | test.cpp:20:14:20:21 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:16:15:16:20 | call to malloc | call to malloc | test.cpp:17:19:17:22 | size | size |
| test.cpp:30:14:30:15 | Load: * ... | test.cpp:28:15:28:20 | call to malloc | test.cpp:30:14:30:15 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:28:15:28:20 | call to malloc | call to malloc | test.cpp:29:20:29:27 | ... + ... | ... + ... |
| test.cpp:32:14:32:21 | Load: * ... | test.cpp:28:15:28:20 | call to malloc | test.cpp:32:14:32:21 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:28:15:28:20 | call to malloc | call to malloc | test.cpp:29:20:29:27 | ... + ... | ... + ... |
| test.cpp:32:14:32:21 | Load: * ... | test.cpp:28:15:28:20 | call to malloc | test.cpp:32:14:32:21 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:28:15:28:20 | call to malloc | call to malloc | test.cpp:29:20:29:27 | ... + ... | ... + ... |
| test.cpp:42:14:42:15 | Load: * ... | test.cpp:40:15:40:20 | call to malloc | test.cpp:42:14:42:15 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:40:15:40:20 | call to malloc | call to malloc | test.cpp:41:20:41:27 | ... - ... | ... - ... |
| test.cpp:44:14:44:21 | Load: * ... | test.cpp:40:15:40:20 | call to malloc | test.cpp:44:14:44:21 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:40:15:40:20 | call to malloc | call to malloc | test.cpp:41:20:41:27 | ... - ... | ... - ... |
| test.cpp:44:14:44:21 | Load: * ... | test.cpp:40:15:40:20 | call to malloc | test.cpp:44:14:44:21 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:40:15:40:20 | call to malloc | call to malloc | test.cpp:41:20:41:27 | ... - ... | ... - ... |
| test.cpp:67:9:67:14 | Store: ... = ... | test.cpp:52:19:52:24 | call to malloc | test.cpp:67:9:67:14 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:52:19:52:24 | call to malloc | call to malloc | test.cpp:53:20:53:23 | size | size |
| test.cpp:96:9:96:14 | Store: ... = ... | test.cpp:82:17:82:22 | call to malloc | test.cpp:96:9:96:14 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:82:17:82:22 | call to malloc | call to malloc | test.cpp:83:27:83:30 | size | size |
| test.cpp:110:9:110:14 | Store: ... = ... | test.cpp:82:17:82:22 | call to malloc | test.cpp:110:9:110:14 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:82:17:82:22 | call to malloc | call to malloc | test.cpp:83:27:83:30 | size | size |
| test.cpp:157:9:157:14 | Store: ... = ... | test.cpp:143:18:143:23 | call to malloc | test.cpp:157:9:157:14 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:143:18:143:23 | call to malloc | call to malloc | test.cpp:144:29:144:32 | size | size |
| test.cpp:171:9:171:14 | Store: ... = ... | test.cpp:143:18:143:23 | call to malloc | test.cpp:171:9:171:14 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:143:18:143:23 | call to malloc | call to malloc | test.cpp:144:29:144:32 | size | size |

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql

View File

@@ -0,0 +1,191 @@
char *malloc(int size);
void test1(int size) {
char* p = malloc(size);
char* q = p + size;
char a = *q; // BAD
char b = *(q - 1); // GOOD
char c = *(q + 1); // BAD
char d = *(q + size); // BAD [NOT DETECTED]
char e = *(q - size); // GOOD
char f = *(q + size + 1); // BAD [NOT DETECTED]
char g = *(q - size - 1); // GOOD
}
void test2(int size) {
char* p = malloc(size);
char* q = p + size - 1;
char a = *q; // GOOD
char b = *(q - 1); // GOOD
char c = *(q + 1); // BAD
char d = *(q + size); // BAD [NOT DETECTED]
char e = *(q - size); // GOOD
char f = *(q + size + 1); // BAD [NOT DETECTED]
char g = *(q - size - 1); // GOOD
}
void test3(int size) {
char* p = malloc(size + 1);
char* q = p + (size + 1);
char a = *q; // BAD
char b = *(q - 1); // GOOD
char c = *(q + 1); // BAD
char d = *(q + size); // BAD [NOT DETECTED]
char e = *(q - size); // GOOD
char f = *(q + size + 1); // BAD [NOT DETECTED]
char g = *(q - size - 1); // GOOD
}
void test4(int size) {
char* p = malloc(size - 1);
char* q = p + (size - 1);
char a = *q; // BAD
char b = *(q - 1); // GOOD
char c = *(q + 1); // BAD
char d = *(q + size); // BAD [NOT DETECTED]
char e = *(q - size); // GOOD
char f = *(q + size + 1); // BAD [NOT DETECTED]
char g = *(q - size - 1); // GOOD
}
char* mk_array(int size, char** end) {
char* begin = malloc(size);
*end = begin + size;
return begin;
}
void test5(int size) {
char* end;
char* begin = mk_array(size, &end);
for (char* p = begin; p != end; ++p) {
*p = 0; // GOOD
}
for (char* p = begin; p <= end; ++p) {
*p = 0; // BAD
}
for (char* p = begin; p < end; ++p) {
*p = 0; // GOOD
}
}
struct array_t {
char* begin;
char* end;
};
array_t mk_array(int size) {
array_t arr;
arr.begin = malloc(size);
arr.end = arr.begin + size;
return arr;
}
void test6(int size) {
array_t arr = mk_array(size);
for (char* p = arr.begin; p != arr.end; ++p) {
*p = 0; // GOOD
}
for (char* p = arr.begin; p <= arr.end; ++p) {
*p = 0; // BAD
}
for (char* p = arr.begin; p < arr.end; ++p) {
*p = 0; // GOOD
}
}
void test7_callee(array_t arr) {
for (char* p = arr.begin; p != arr.end; ++p) {
*p = 0; // GOOD
}
for (char* p = arr.begin; p <= arr.end; ++p) {
*p = 0; // BAD
}
for (char* p = arr.begin; p < arr.end; ++p) {
*p = 0; // GOOD
}
}
void test7(int size) {
test7_callee(mk_array(size));
}
void test8(int size) {
array_t arr;
char* p = malloc(size);
arr.begin = p;
arr.end = p + size;
for (int i = 0; i < arr.end - arr.begin; i++) {
*(arr.begin + i) = 0; // GOOD
}
for (int i = 0; i != arr.end - arr.begin; i++) {
*(arr.begin + i) = 0; // GOOD
}
for (int i = 0; i <= arr.end - arr.begin; i++) {
*(arr.begin + i) = 0; // BAD [NOT DETECTED]
}
}
array_t *mk_array_p(int size) {
array_t *arr = (array_t*) malloc(sizeof(array_t));
arr->begin = malloc(size);
arr->end = arr->begin + size;
return arr;
}
void test9(int size) {
array_t *arr = mk_array_p(size);
for (char* p = arr->begin; p != arr->end; ++p) {
*p = 0; // GOOD
}
for (char* p = arr->begin; p <= arr->end; ++p) {
*p = 0; // BAD
}
for (char* p = arr->begin; p < arr->end; ++p) {
*p = 0; // GOOD
}
}
void test10_callee(array_t *arr) {
for (char* p = arr->begin; p != arr->end; ++p) {
*p = 0; // GOOD
}
for (char* p = arr->begin; p <= arr->end; ++p) {
*p = 0; // BAD
}
for (char* p = arr->begin; p < arr->end; ++p) {
*p = 0; // GOOD
}
}
void test10(int size) {
test10_callee(mk_array_p(size));
}
void deref_plus_one(char* q) {
char a = *(q + 1); // BAD [NOT DETECTED]
}
void test11(unsigned size) {
char *p = malloc(size);
char *q = p + size - 1;
deref_plus_one(q);
}

View File

@@ -64,6 +64,10 @@ edges
| test.cpp:201:5:201:17 | EnterFunction: maybe_deref_p | test.cpp:201:5:201:17 | VariableAddress: maybe_deref_p | | test.cpp:201:5:201:17 | EnterFunction: maybe_deref_p | test.cpp:201:5:201:17 | VariableAddress: maybe_deref_p |
| test.cpp:210:3:210:9 | Call: call to escape1 | test.cpp:201:5:201:17 | EnterFunction: maybe_deref_p | | test.cpp:210:3:210:9 | Call: call to escape1 | test.cpp:201:5:201:17 | EnterFunction: maybe_deref_p |
| test.cpp:210:3:210:9 | Call: call to escape1 | test.cpp:201:5:201:17 | VariableAddress: maybe_deref_p | | test.cpp:210:3:210:9 | Call: call to escape1 | test.cpp:201:5:201:17 | VariableAddress: maybe_deref_p |
| test.cpp:234:3:234:13 | Store: ... = ... | test.cpp:238:3:238:9 | Call: call to escape2 |
| test.cpp:238:3:238:9 | Call: call to escape2 | test.cpp:239:17:239:17 | Load: p |
| test.cpp:263:3:263:13 | Store: ... = ... | test.cpp:267:3:267:9 | Call: call to escape3 |
| test.cpp:267:3:267:9 | Call: call to escape3 | test.cpp:268:17:268:17 | Load: p |
#select #select
| test.cpp:15:16:15:16 | Load: p | test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:15:16:15:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:9:7:9:7 | x | x | test.cpp:10:3:10:13 | Store: ... = ... | here | | test.cpp:15:16:15:16 | Load: p | test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:15:16:15:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:9:7:9:7 | x | x | test.cpp:10:3:10:13 | Store: ... = ... | here |
| test.cpp:24:16:24:16 | Load: p | test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:24:16:24:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:9:7:9:7 | x | x | test.cpp:10:3:10:13 | Store: ... = ... | here | | test.cpp:24:16:24:16 | Load: p | test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:24:16:24:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:9:7:9:7 | x | x | test.cpp:10:3:10:13 | Store: ... = ... | here |
@@ -90,3 +94,5 @@ edges
| test.cpp:180:14:180:19 | Load: * ... | test.cpp:154:3:154:22 | Store: ... = ... | test.cpp:180:14:180:19 | Load: * ... | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:133:7:133:8 | b2 | b2 | test.cpp:154:3:154:22 | Store: ... = ... | here | | test.cpp:180:14:180:19 | Load: * ... | test.cpp:154:3:154:22 | Store: ... = ... | test.cpp:180:14:180:19 | Load: * ... | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:133:7:133:8 | b2 | b2 | test.cpp:154:3:154:22 | Store: ... = ... | here |
| test.cpp:181:13:181:20 | Load: access to array | test.cpp:155:3:155:21 | Store: ... = ... | test.cpp:181:13:181:20 | Load: access to array | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:155:3:155:21 | Store: ... = ... | here | | test.cpp:181:13:181:20 | Load: access to array | test.cpp:155:3:155:21 | Store: ... = ... | test.cpp:181:13:181:20 | Load: access to array | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:155:3:155:21 | Store: ... = ... | here |
| test.cpp:182:14:182:19 | Load: * ... | test.cpp:156:3:156:25 | Store: ... = ... | test.cpp:182:14:182:19 | Load: * ... | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:156:3:156:25 | Store: ... = ... | here | | test.cpp:182:14:182:19 | Load: * ... | test.cpp:156:3:156:25 | Store: ... = ... | test.cpp:182:14:182:19 | Load: * ... | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:156:3:156:25 | Store: ... = ... | here |
| test.cpp:239:17:239:17 | Load: p | test.cpp:234:3:234:13 | Store: ... = ... | test.cpp:239:17:239:17 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:232:7:232:7 | x | x | test.cpp:234:3:234:13 | Store: ... = ... | here |
| test.cpp:268:17:268:17 | Load: p | test.cpp:263:3:263:13 | Store: ... = ... | test.cpp:268:17:268:17 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:260:7:260:7 | x | x | test.cpp:263:3:263:13 | Store: ... = ... | here |

View File

@@ -209,4 +209,61 @@ int maybe_deref_p(bool b) {
int field_indirect_maybe_bad(bool b) { int field_indirect_maybe_bad(bool b) {
escape1(); escape1();
return maybe_deref_p(b); return maybe_deref_p(b);
}
// These next tests cover subsequent stores to the same address in the same basic block.
static struct S100 s102;
void not_escape1() {
int x;
s102.p = &x;
s102.p = nullptr;
}
void calls_not_escape1() {
not_escape1();
int x = *s102.p; // GOOD
}
static struct S100 s103;
void escape2() {
int x;
s103.p = nullptr;
s103.p = &x;
}
void calls_escape2() {
escape2();
int x = *s103.p; // BAD
}
bool unknown();
static struct S100 s104;
void not_escape2() {
int x;
s104.p = &x;
if(unknown()) { }
s104.p = nullptr;
}
void calls_not_escape2() {
not_escape2();
int x = *s104.p; // GOOD
}
static struct S100 s105;
void escape3() {
int x;
s105.p = nullptr;
if(unknown()) { }
s105.p = &x;
}
void calls_escape3() {
escape3();
int x = *s105.p; // BAD
} }

View File

@@ -1,5 +1,4 @@
edges edges
| test2.cpp:52:44:52:57 | password_tries | test2.cpp:52:40:52:58 | * ... |
| test2.cpp:62:18:62:25 | password | test2.cpp:65:31:65:34 | cpy1 | | test2.cpp:62:18:62:25 | password | test2.cpp:65:31:65:34 | cpy1 |
| test2.cpp:72:17:72:24 | password | test2.cpp:73:30:73:32 | buf | | test2.cpp:72:17:72:24 | password | test2.cpp:73:30:73:32 | buf |
| test2.cpp:72:17:72:24 | password | test2.cpp:76:30:76:32 | buf | | test2.cpp:72:17:72:24 | password | test2.cpp:76:30:76:32 | buf |
@@ -9,8 +8,6 @@ nodes
| test2.cpp:44:37:44:45 | thepasswd | semmle.label | thepasswd | | test2.cpp:44:37:44:45 | thepasswd | semmle.label | thepasswd |
| test2.cpp:45:38:45:47 | accountkey | semmle.label | accountkey | | test2.cpp:45:38:45:47 | accountkey | semmle.label | accountkey |
| test2.cpp:50:41:50:53 | passwd_config | semmle.label | passwd_config | | test2.cpp:50:41:50:53 | passwd_config | semmle.label | passwd_config |
| test2.cpp:52:40:52:58 | * ... | semmle.label | * ... |
| test2.cpp:52:44:52:57 | password_tries | semmle.label | password_tries |
| test2.cpp:54:41:54:52 | widepassword | semmle.label | widepassword | | test2.cpp:54:41:54:52 | widepassword | semmle.label | widepassword |
| test2.cpp:55:40:55:51 | widepassword | semmle.label | widepassword | | test2.cpp:55:40:55:51 | widepassword | semmle.label | widepassword |
| test2.cpp:57:39:57:49 | call to getPassword | semmle.label | call to getPassword | | test2.cpp:57:39:57:49 | call to getPassword | semmle.label | call to getPassword |

View File

@@ -1,3 +1,5 @@
## 1.2.5
## 1.2.4 ## 1.2.4
## 1.2.3 ## 1.2.3

View File

@@ -0,0 +1 @@
## 1.2.5

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 1.2.4 lastReleaseVersion: 1.2.5

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-all name: codeql/csharp-solorigate-all
version: 1.2.5-dev version: 1.2.6-dev
groups: groups:
- csharp - csharp
- solorigate - solorigate

View File

@@ -1,3 +1,5 @@
## 1.2.5
## 1.2.4 ## 1.2.4
## 1.2.3 ## 1.2.3

View File

@@ -0,0 +1 @@
## 1.2.5

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 1.2.4 lastReleaseVersion: 1.2.5

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-queries name: codeql/csharp-solorigate-queries
version: 1.2.5-dev version: 1.2.6-dev
groups: groups:
- csharp - csharp
- solorigate - solorigate

View File

@@ -0,0 +1,2 @@
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");

View File

@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,8 @@
import os
from create_database_utils import *
run_codeql_database_create(['dotnet pack'], test_db="default-db", db=None, lang="csharp")
## Check that the NuGet package is created.
if not os.path.isfile("bin/Debug/dotnet_pack.1.0.0.nupkg"):
raise Exception("The NuGet package was not created.")

View File

@@ -0,0 +1,2 @@
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");

View File

@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,8 @@
import os
from create_database_utils import *
run_codeql_database_create(['dotnet publish'], test_db="default-db", db=None, lang="csharp")
## Check that the publish folder is created.
if not os.path.isdir("bin/Debug/net6.0/publish/"):
raise Exception("The publish artifact folder was not created.")

View File

@@ -0,0 +1,17 @@
using NUnit.Framework;
namespace dotnet_test;
public class Tests
{
[SetUp]
public void Setup()
{
}
[Test]
public void Test1()
{
Assert.Pass();
}
}

View File

@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="NUnit" Version="3.13.2" />
<PackageReference Include="NUnit3TestAdapter" Version="4.0.0" />
<PackageReference Include="coverlet.collector" Version="3.1.0" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,3 @@
from create_database_utils import *
run_codeql_database_create(['dotnet test'], test_db="default-db", db=None, lang="csharp")

View File

@@ -1,3 +1,5 @@
## 0.3.5
## 0.3.4 ## 0.3.4
### Deprecated APIs ### Deprecated APIs

View File

@@ -0,0 +1,5 @@
---
category: deprecated
---
* Some classes/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
The old name still exists as a deprecated alias.

View File

@@ -0,0 +1 @@
## 0.3.5

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 0.3.4 lastReleaseVersion: 0.3.5

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-all name: codeql/csharp-all
version: 0.3.5-dev version: 0.3.6-dev
groups: csharp groups: csharp
dbscheme: semmlecode.csharp.dbscheme dbscheme: semmlecode.csharp.dbscheme
extractor: csharp extractor: csharp

View File

@@ -56,7 +56,7 @@ private predicate alwaysNotNullVariableUpdate(VariableUpdate vu) {
/** Holds if expression `expr` always evaluates to non-null. */ /** Holds if expression `expr` always evaluates to non-null. */
private predicate alwaysNotNullExpr(Expr expr) { private predicate alwaysNotNullExpr(Expr expr) {
expr instanceof Opcodes::Newobj expr instanceof Opcodes::NewObj
or or
expr instanceof Literal and not expr instanceof NullLiteral expr instanceof Literal and not expr instanceof NullLiteral
or or

View File

@@ -766,7 +766,7 @@ module Opcodes {
} }
/** A `newobj` instruction. */ /** A `newobj` instruction. */
class Newobj extends Call, @cil_newobj { class NewObj extends Call, @cil_newobj {
override string getOpcodeName() { result = "newobj" } override string getOpcodeName() { result = "newobj" }
override int getPushCount() { result = 1 } override int getPushCount() { result = 1 }
@@ -788,6 +788,9 @@ module Opcodes {
} }
} }
/** DEPRECATED: Alias for NewObj */
deprecated class Newobj = NewObj;
/** An `initobj` instruction. */ /** An `initobj` instruction. */
class Initobj extends Instruction, @cil_initobj { class Initobj extends Instruction, @cil_initobj {
override string getOpcodeName() { result = "initobj" } override string getOpcodeName() { result = "initobj" }
@@ -847,10 +850,13 @@ module Opcodes {
} }
/** A `rethrow` instruction. */ /** A `rethrow` instruction. */
class Rethrow extends Throw, @cil_rethrow { class ReThrow extends Throw, @cil_rethrow {
override string getOpcodeName() { result = "rethrow" } override string getOpcodeName() { result = "rethrow" }
} }
/** DEPRECATED: Alias for ReThrow */
deprecated class Rethrow = ReThrow;
/** A `ldlen` instruction. */ /** A `ldlen` instruction. */
class Ldlen extends UnaryExpr, @cil_ldlen { class Ldlen extends UnaryExpr, @cil_ldlen {
override string getOpcodeName() { result = "ldlen" } override string getOpcodeName() { result = "ldlen" }

View File

@@ -1,3 +1,5 @@
## 0.3.4
## 0.3.3 ## 0.3.3
### Minor Analysis Improvements ### Minor Analysis Improvements

View File

@@ -0,0 +1 @@
## 0.3.4

View File

@@ -1,2 +1,2 @@
--- ---
lastReleaseVersion: 0.3.3 lastReleaseVersion: 0.3.4

View File

@@ -6,7 +6,7 @@
private import IRFunctionBase private import IRFunctionBase
private import TInstruction private import TInstruction
module SSA { module Ssa {
class MemoryLocation = boolean; class MemoryLocation = boolean;
predicate hasPhiInstruction(TRawInstruction blockStartInstr, MemoryLocation memoryLocation) { predicate hasPhiInstruction(TRawInstruction blockStartInstr, MemoryLocation memoryLocation) {
@@ -17,3 +17,6 @@ module SSA {
predicate hasUnreachedInstruction(IRFunctionBase irFunc) { none() } predicate hasUnreachedInstruction(IRFunctionBase irFunc) { none() }
} }
/** DEPRECATED: Alias for Ssa */
deprecated module SSA = Ssa;

View File

@@ -20,24 +20,24 @@ newtype TInstruction =
IRConstruction::Raw::hasInstruction(tag1, tag2) IRConstruction::Raw::hasInstruction(tag1, tag2)
} or } or
TUnaliasedSsaPhiInstruction( TUnaliasedSsaPhiInstruction(
TRawInstruction blockStartInstr, UnaliasedSsa::SSA::MemoryLocation memoryLocation TRawInstruction blockStartInstr, UnaliasedSsa::Ssa::MemoryLocation memoryLocation
) { ) {
UnaliasedSsa::SSA::hasPhiInstruction(blockStartInstr, memoryLocation) UnaliasedSsa::Ssa::hasPhiInstruction(blockStartInstr, memoryLocation)
} or } or
TUnaliasedSsaChiInstruction(TRawInstruction primaryInstruction) { none() } or TUnaliasedSsaChiInstruction(TRawInstruction primaryInstruction) { none() } or
TUnaliasedSsaUnreachedInstruction(IRFunctionBase irFunc) { TUnaliasedSsaUnreachedInstruction(IRFunctionBase irFunc) {
UnaliasedSsa::SSA::hasUnreachedInstruction(irFunc) UnaliasedSsa::Ssa::hasUnreachedInstruction(irFunc)
} or } or
TAliasedSsaPhiInstruction( TAliasedSsaPhiInstruction(
TRawInstruction blockStartInstr, AliasedSsa::SSA::MemoryLocation memoryLocation TRawInstruction blockStartInstr, AliasedSsa::Ssa::MemoryLocation memoryLocation
) { ) {
AliasedSsa::SSA::hasPhiInstruction(blockStartInstr, memoryLocation) AliasedSsa::Ssa::hasPhiInstruction(blockStartInstr, memoryLocation)
} or } or
TAliasedSsaChiInstruction(TRawInstruction primaryInstruction) { TAliasedSsaChiInstruction(TRawInstruction primaryInstruction) {
AliasedSsa::SSA::hasChiInstruction(primaryInstruction) AliasedSsa::Ssa::hasChiInstruction(primaryInstruction)
} or } or
TAliasedSsaUnreachedInstruction(IRFunctionBase irFunc) { TAliasedSsaUnreachedInstruction(IRFunctionBase irFunc) {
AliasedSsa::SSA::hasUnreachedInstruction(irFunc) AliasedSsa::Ssa::hasUnreachedInstruction(irFunc)
} }
/** /**
@@ -50,7 +50,7 @@ module UnaliasedSsaInstructions {
class TPhiInstruction = TUnaliasedSsaPhiInstruction; class TPhiInstruction = TUnaliasedSsaPhiInstruction;
TPhiInstruction phiInstruction( TPhiInstruction phiInstruction(
TRawInstruction blockStartInstr, UnaliasedSsa::SSA::MemoryLocation memoryLocation TRawInstruction blockStartInstr, UnaliasedSsa::Ssa::MemoryLocation memoryLocation
) { ) {
result = TUnaliasedSsaPhiInstruction(blockStartInstr, memoryLocation) result = TUnaliasedSsaPhiInstruction(blockStartInstr, memoryLocation)
} }
@@ -83,7 +83,7 @@ module AliasedSsaInstructions {
class TPhiInstruction = TAliasedSsaPhiInstruction or TUnaliasedSsaPhiInstruction; class TPhiInstruction = TAliasedSsaPhiInstruction or TUnaliasedSsaPhiInstruction;
TPhiInstruction phiInstruction( TPhiInstruction phiInstruction(
TRawInstruction blockStartInstr, AliasedSsa::SSA::MemoryLocation memoryLocation TRawInstruction blockStartInstr, AliasedSsa::Ssa::MemoryLocation memoryLocation
) { ) {
result = TAliasedSsaPhiInstruction(blockStartInstr, memoryLocation) result = TAliasedSsaPhiInstruction(blockStartInstr, memoryLocation)
} }

View File

@@ -1,2 +1,2 @@
private import SSAConstruction as SSA private import SSAConstruction as Ssa
import SSA::SsaConsistency import Ssa::SsaConsistency

View File

@@ -1135,7 +1135,7 @@ deprecated module SSAConsistency = SsaConsistency;
* These predicates are all just aliases for predicates defined in the `Cached` module. This ensures * These predicates are all just aliases for predicates defined in the `Cached` module. This ensures
* that all of SSA construction will be evaluated in the same stage. * that all of SSA construction will be evaluated in the same stage.
*/ */
module SSA { module Ssa {
class MemoryLocation = Alias::MemoryLocation; class MemoryLocation = Alias::MemoryLocation;
predicate hasPhiInstruction = Cached::hasPhiInstructionCached/2; predicate hasPhiInstruction = Cached::hasPhiInstructionCached/2;
@@ -1144,3 +1144,6 @@ module SSA {
predicate hasUnreachedInstruction = Cached::hasUnreachedInstructionCached/1; predicate hasUnreachedInstruction = Cached::hasUnreachedInstructionCached/1;
} }
/** DEPRECATED: Alias for Ssa */
deprecated module SSA = Ssa;

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-queries name: codeql/csharp-queries
version: 0.3.4-dev version: 0.3.5-dev
groups: groups:
- csharp - csharp
- queries - queries

View File

@@ -4,10 +4,10 @@
* @id csharp/utils/model-generator/discarded-summary-models * @id csharp/utils/model-generator/discarded-summary-models
*/ */
private import semmle.code.csharp.dataflow.ExternalFlow import semmle.code.csharp.dataflow.ExternalFlow
private import internal.CaptureModels import internal.CaptureModels
private import internal.CaptureSummaryFlow import internal.CaptureSummaryFlow
from TargetApi api, string flow from DataFlowTargetApi api, string flow
where flow = captureFlow(api) and hasSummary(api, false) where flow = captureFlow(api) and hasSummary(api, false)
select flow order by flow select flow order by flow

View File

@@ -6,10 +6,12 @@
* @tags model-generator * @tags model-generator
*/ */
private import semmle.code.csharp.dataflow.ExternalFlow import semmle.code.csharp.dataflow.ExternalFlow
private import internal.CaptureModels import internal.CaptureModels
private import internal.CaptureSummaryFlow import internal.CaptureSummaryFlow
from TargetApi api, string noflow from DataFlowTargetApi api, string noflow
where noflow = captureNoFlow(api) and not hasSummary(api, false) where
noflow = captureNoFlow(api) and
not hasSummary(api, false)
select noflow order by noflow select noflow order by noflow

View File

@@ -6,8 +6,8 @@
* @tags model-generator * @tags model-generator
*/ */
private import internal.CaptureModels import internal.CaptureModels
from TargetApi api, string sink from DataFlowTargetApi api, string sink
where sink = captureSink(api) where sink = captureSink(api)
select sink order by sink select sink order by sink

View File

@@ -6,8 +6,8 @@
* @tags model-generator * @tags model-generator
*/ */
private import internal.CaptureModels import internal.CaptureModels
from TargetApi api, string source from DataFlowTargetApi api, string source
where source = captureSource(api) where source = captureSource(api)
select source order by source select source order by source

View File

@@ -6,10 +6,10 @@
* @tags model-generator * @tags model-generator
*/ */
private import semmle.code.csharp.dataflow.ExternalFlow import semmle.code.csharp.dataflow.ExternalFlow
private import internal.CaptureModels import internal.CaptureModels
private import internal.CaptureSummaryFlow import internal.CaptureSummaryFlow
from TargetApi api, string flow from DataFlowTargetApi api, string flow
where flow = captureFlow(api) and not hasSummary(api, false) where flow = captureFlow(api) and not hasSummary(api, false)
select flow order by flow select flow order by flow

View File

@@ -0,0 +1,14 @@
/**
* @name Capture typed based summary models.
* @description Finds applicable summary models to be used by other queries.
* @kind diagnostic
* @id cs/utils/model-generator/summary-models-typed-based
* @tags model-generator
*/
import semmle.code.csharp.dataflow.ExternalFlow
import internal.CaptureTypeBasedSummaryModels
from TypeBasedFlowTargetApi api, string flow
where flow = captureFlow(api)
select flow order by flow

View File

@@ -5,7 +5,9 @@
private import CaptureModelsSpecific private import CaptureModelsSpecific
class TargetApi = TargetApiSpecific; class DataFlowTargetApi extends TargetApiSpecific {
DataFlowTargetApi() { isRelevantForDataFlowModels(this) }
}
/** /**
* Holds if data can flow from `node1` to `node2` either via a read or a write of an intermediate field `f`. * Holds if data can flow from `node1` to `node2` either via a read or a write of an intermediate field `f`.
@@ -40,7 +42,7 @@ private predicate isRelevantContent(DataFlow::Content c) {
* Gets the summary model for `api` with `input`, `output` and `kind`. * Gets the summary model for `api` with `input`, `output` and `kind`.
*/ */
bindingset[input, output, kind] bindingset[input, output, kind]
private string asSummaryModel(TargetApi api, string input, string output, string kind) { private string asSummaryModel(TargetApiSpecific api, string input, string output, string kind) {
result = result =
asPartialModel(api) + input + ";" // asPartialModel(api) + input + ";" //
+ output + ";" // + output + ";" //
@@ -48,13 +50,15 @@ private string asSummaryModel(TargetApi api, string input, string output, string
+ "generated" + "generated"
} }
string asNegativeSummaryModel(TargetApi api) { result = asPartialNegativeModel(api) + "generated" } string asNegativeSummaryModel(TargetApiSpecific api) {
result = asPartialNegativeModel(api) + "generated"
}
/** /**
* Gets the value summary model for `api` with `input` and `output`. * Gets the value summary model for `api` with `input` and `output`.
*/ */
bindingset[input, output] bindingset[input, output]
private string asValueModel(TargetApi api, string input, string output) { string asValueModel(TargetApiSpecific api, string input, string output) {
result = asSummaryModel(api, input, output, "value") result = asSummaryModel(api, input, output, "value")
} }
@@ -62,7 +66,7 @@ private string asValueModel(TargetApi api, string input, string output) {
* Gets the taint summary model for `api` with `input` and `output`. * Gets the taint summary model for `api` with `input` and `output`.
*/ */
bindingset[input, output] bindingset[input, output]
private string asTaintModel(TargetApi api, string input, string output) { private string asTaintModel(TargetApiSpecific api, string input, string output) {
result = asSummaryModel(api, input, output, "taint") result = asSummaryModel(api, input, output, "taint")
} }
@@ -70,7 +74,7 @@ private string asTaintModel(TargetApi api, string input, string output) {
* Gets the sink model for `api` with `input` and `kind`. * Gets the sink model for `api` with `input` and `kind`.
*/ */
bindingset[input, kind] bindingset[input, kind]
private string asSinkModel(TargetApi api, string input, string kind) { private string asSinkModel(TargetApiSpecific api, string input, string kind) {
result = result =
asPartialModel(api) + input + ";" // asPartialModel(api) + input + ";" //
+ kind + ";" // + kind + ";" //
@@ -81,7 +85,7 @@ private string asSinkModel(TargetApi api, string input, string kind) {
* Gets the source model for `api` with `output` and `kind`. * Gets the source model for `api` with `output` and `kind`.
*/ */
bindingset[output, kind] bindingset[output, kind]
private string asSourceModel(TargetApi api, string output, string kind) { private string asSourceModel(TargetApiSpecific api, string output, string kind) {
result = result =
asPartialModel(api) + output + ";" // asPartialModel(api) + output + ";" //
+ kind + ";" // + kind + ";" //
@@ -91,7 +95,7 @@ private string asSourceModel(TargetApi api, string output, string kind) {
/** /**
* Gets the summary model of `api`, if it follows the `fluent` programming pattern (returns `this`). * Gets the summary model of `api`, if it follows the `fluent` programming pattern (returns `this`).
*/ */
string captureQualifierFlow(TargetApi api) { string captureQualifierFlow(TargetApiSpecific api) {
exists(DataFlowImplCommon::ReturnNodeExt ret | exists(DataFlowImplCommon::ReturnNodeExt ret |
api = returnNodeEnclosingCallable(ret) and api = returnNodeEnclosingCallable(ret) and
isOwnInstanceAccessNode(ret) isOwnInstanceAccessNode(ret)
@@ -140,7 +144,7 @@ private class ThroughFlowConfig extends TaintTracking::Configuration {
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) {
source instanceof DataFlow::ParameterNode and source instanceof DataFlow::ParameterNode and
source.getEnclosingCallable() instanceof TargetApi and source.getEnclosingCallable() instanceof DataFlowTargetApi and
state.(TaintRead).getStep() = 0 state.(TaintRead).getStep() = 0
} }
@@ -184,7 +188,7 @@ private class ThroughFlowConfig extends TaintTracking::Configuration {
/** /**
* Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter. * Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter.
*/ */
string captureThroughFlow(TargetApi api) { string captureThroughFlow(DataFlowTargetApi api) {
exists( exists(
ThroughFlowConfig config, DataFlow::ParameterNode p, ThroughFlowConfig config, DataFlow::ParameterNode p,
DataFlowImplCommon::ReturnNodeExt returnNodeExt, string input, string output DataFlowImplCommon::ReturnNodeExt returnNodeExt, string input, string output
@@ -211,7 +215,7 @@ private class FromSourceConfiguration extends TaintTracking::Configuration {
override predicate isSource(DataFlow::Node source) { ExternalFlow::sourceNode(source, _) } override predicate isSource(DataFlow::Node source) { ExternalFlow::sourceNode(source, _) }
override predicate isSink(DataFlow::Node sink) { override predicate isSink(DataFlow::Node sink) {
exists(TargetApi c | exists(DataFlowTargetApi c |
sink instanceof DataFlowImplCommon::ReturnNodeExt and sink instanceof DataFlowImplCommon::ReturnNodeExt and
sink.getEnclosingCallable() = c sink.getEnclosingCallable() = c
) )
@@ -229,7 +233,7 @@ private class FromSourceConfiguration extends TaintTracking::Configuration {
/** /**
* Gets the source model(s) of `api`, if there is flow from an existing known source to the return of `api`. * Gets the source model(s) of `api`, if there is flow from an existing known source to the return of `api`.
*/ */
string captureSource(TargetApi api) { string captureSource(DataFlowTargetApi api) {
exists(DataFlow::Node source, DataFlow::Node sink, FromSourceConfiguration config, string kind | exists(DataFlow::Node source, DataFlow::Node sink, FromSourceConfiguration config, string kind |
config.hasFlow(source, sink) and config.hasFlow(source, sink) and
ExternalFlow::sourceNode(source, kind) and ExternalFlow::sourceNode(source, kind) and
@@ -259,7 +263,7 @@ private class PropagateToSinkConfiguration extends PropagateToSinkConfigurationS
/** /**
* Gets the sink model(s) of `api`, if there is flow from a parameter to an existing known sink. * Gets the sink model(s) of `api`, if there is flow from a parameter to an existing known sink.
*/ */
string captureSink(TargetApi api) { string captureSink(DataFlowTargetApi api) {
exists(DataFlow::Node src, DataFlow::Node sink, PropagateToSinkConfiguration config, string kind | exists(DataFlow::Node src, DataFlow::Node sink, PropagateToSinkConfiguration config, string kind |
config.hasFlow(src, sink) and config.hasFlow(src, sink) and
ExternalFlow::sinkNode(sink, kind) and ExternalFlow::sinkNode(sink, kind) and

View File

@@ -36,10 +36,21 @@ private predicate isRelevantForModels(CS::Callable api) {
api.getDeclaringType().getNamespace().getQualifiedName() != "" and api.getDeclaringType().getNamespace().getQualifiedName() != "" and
not api instanceof CS::ConversionOperator and not api instanceof CS::ConversionOperator and
not api instanceof Util::MainMethod and not api instanceof Util::MainMethod and
not isHigherOrder(api) and
not api instanceof CS::Destructor not api instanceof CS::Destructor
} }
/**
* Holds if it is relevant to generate models for `api` based on data flow analysis.
*/
predicate isRelevantForDataFlowModels(CS::Callable api) {
isRelevantForModels(api) and not isHigherOrder(api)
}
/**
* Holds if it is relevant to generate models for `api` based on its type.
*/
predicate isRelevantForTypeBasedFlowModels = isRelevantForModels/1;
/** /**
* A class of callables that are relevant generating summary, source and sinks models for. * A class of callables that are relevant generating summary, source and sinks models for.
* *
@@ -49,8 +60,7 @@ private predicate isRelevantForModels(CS::Callable api) {
class TargetApiSpecific extends DotNet::Callable { class TargetApiSpecific extends DotNet::Callable {
TargetApiSpecific() { TargetApiSpecific() {
this.fromSource() and this.fromSource() and
this.isUnboundDeclaration() and this.isUnboundDeclaration()
isRelevantForModels(this)
} }
} }
@@ -100,7 +110,7 @@ predicate isRelevantType(CS::Type t) {
*/ */
string qualifierString() { result = "Argument[this]" } string qualifierString() { result = "Argument[this]" }
private string parameterAccess(CS::Parameter p) { string parameterAccess(CS::Parameter p) {
if Collections::isCollectionType(p.getType()) if Collections::isCollectionType(p.getType())
then result = "Argument[" + p.getPosition() + "].Element" then result = "Argument[" + p.getPosition() + "].Element"
else result = "Argument[" + p.getPosition() + "]" else result = "Argument[" + p.getPosition() + "]"

View File

@@ -75,7 +75,7 @@ private import CaptureModels
* Captured Model: * Captured Model:
* ```Summaries;BasicFlow;false;AssignToArray;(System.Int32,System.Int32[]);Argument[0];Argument[1].Element;taint``` * ```Summaries;BasicFlow;false;AssignToArray;(System.Int32,System.Int32[]);Argument[0];Argument[1].Element;taint```
*/ */
string captureFlow(TargetApi api) { string captureFlow(DataFlowTargetApi api) {
result = captureQualifierFlow(api) or result = captureQualifierFlow(api) or
result = captureThroughFlow(api) result = captureThroughFlow(api)
} }
@@ -84,7 +84,7 @@ string captureFlow(TargetApi api) {
* Gets the negative summary for `api`, if any. * Gets the negative summary for `api`, if any.
* A negative summary is generated, if there does not exist any positive flow. * A negative summary is generated, if there does not exist any positive flow.
*/ */
string captureNoFlow(TargetApi api) { string captureNoFlow(DataFlowTargetApi api) {
not exists(captureFlow(api)) and not exists(captureFlow(api)) and
result = asNegativeSummaryModel(api) result = asNegativeSummaryModel(api)
} }

View File

@@ -0,0 +1,224 @@
private import csharp
private import dotnet
private import semmle.code.csharp.frameworks.system.collections.Generic as GenericCollections
private import semmle.code.csharp.dataflow.internal.DataFlowPrivate
private import semmle.code.csharp.frameworks.system.linq.Expressions
private import CaptureModelsSpecific as Specific
private import CaptureModels
/**
* Holds if `t` is a subtype (reflexive/transitive) of `IEnumerable<T>`, where `T` = `tp`.
*/
private predicate genericCollectionType(ValueOrRefType t, TypeParameter tp) {
exists(ConstructedGeneric t2 |
t2 = t.getABaseType*() and
t2.getUnboundDeclaration() instanceof
GenericCollections::SystemCollectionsGenericIEnumerableTInterface and
tp = t2.getATypeArgument()
)
}
/**
* Holds if `tp` is a type parameter of the immediate type declaring `callable`.
*/
private predicate classTypeParameter(DotNet::Callable callable, TypeParameter tp) {
callable.getDeclaringType().(UnboundGeneric).getATypeParameter() = tp
}
/**
* Holds if `tp` is type parameter of `callable` or the type declaring `callable`.
*/
private predicate localTypeParameter(DotNet::Callable callable, TypeParameter tp) {
classTypeParameter(callable, tp) or
callable.(UnboundGeneric).getATypeParameter() = tp
}
/**
* Holds if `callable` has a parameter of type `tp`
* or collection parameterized over type `tp`.
*/
private predicate parameter(DotNet::Callable callable, string input, TypeParameter tp) {
exists(Parameter p |
input = Specific::parameterAccess(p) and
p = callable.getAParameter() and
(
// Parameter of type tp
p.getType() = tp
or
// Parameter is a collection of type tp
genericCollectionType(p.getType(), tp)
)
)
}
/**
* Gets the string representation of a synthetic field corresponding to `tp`.
*/
private string getSyntheticField(TypeParameter tp) {
result = ".SyntheticField[ArgType" + tp.getIndex() + "]"
}
/**
* Gets a models as data string representation of, how a value of type `tp`
* can be read or stored implicitly in relation to `callable`.
*/
private string implicit(DotNet::Callable callable, TypeParameter tp) {
classTypeParameter(callable, tp) and
exists(string access |
if genericCollectionType(callable.getDeclaringType(), tp)
then access = ".Element"
else access = getSyntheticField(tp)
|
result = Specific::qualifierString() + access
)
}
/**
* Holds if `callable` has a delegate parameter `dt` at parameter position `position`.
*/
private predicate delegate(DotNet::Callable callable, DelegateType dt, int position) {
exists(Parameter p |
p = callable.getAParameter() and
dt = p.getType().(SystemLinqExpressions::DelegateExtType).getDelegateType() and
position = p.getPosition()
)
}
/**
* Gets models as data input/output access relative to the type parameter `tp` in the
* type `t` in the scope of `callable`.
*
* Note: This predicate has to be inlined as `callable` is not related to `return` or `tp`
* in every disjunction.
*/
bindingset[callable]
private string getAccess(DotNet::Callable callable, Type return, TypeParameter tp) {
return = tp and result = ""
or
genericCollectionType(return, tp) and result = ".Element"
or
not genericCollectionType(return, tp) and
(
return.(ConstructedGeneric).getATypeArgument() = tp
or
callable.getDeclaringType() = return and return.(UnboundGeneric).getATypeParameter() = tp
) and
result = getSyntheticField(tp)
}
/**
* Holds if `input` is a models as data string representation of, how a value of type `tp`
* (or a generic parameterized over `tp`) can be generated by a delegate parameter of `callable`.
*/
private predicate delegateSource(DotNet::Callable callable, string input, TypeParameter tp) {
exists(DelegateType dt, int position, Type return, string access |
delegate(callable, dt, position) and
return = dt.getReturnType() and
access = getAccess(callable, return, tp) and
input = "Argument[" + position + "].ReturnValue" + access
)
}
/**
* Holds if `input` is a models as data string representation of, how a
* value of type `tp` (or a generic parameterized over `tp`)
* can be provided as input to `callable`.
* This includes
* (1) The implicit synthetic field(s) of the declaring type of `callable`.
* (2) The parameters of `callable`.
* (3) Any delegate parameters of `callable`.
*/
private predicate input(DotNet::Callable callable, string input, TypeParameter tp) {
input = implicit(callable, tp)
or
parameter(callable, input, tp)
or
delegateSource(callable, input, tp)
}
/**
* Holds if `callable` returns a value of type `tp` (or a generic parameterized over `tp`) and `output`
* is a models as data string representation of, how data is routed to the return.
*/
private predicate returns(DotNet::Callable callable, TypeParameter tp, string output) {
exists(Type return, string access | return = callable.getReturnType() |
access = getAccess(callable, return, tp) and
output = "ReturnValue" + access
)
}
/**
* Holds if `callable` has a delegate parameter that accepts a value of type `tp`
* and `output` is the models as data string representation of, how data is routed to
* the delegate parameter.
*/
private predicate delegateSink(DotNet::Callable callable, TypeParameter tp, string output) {
exists(DelegateType dt, int position, Parameter p |
delegate(callable, dt, position) and
p = dt.getAParameter() and
p.getType() = tp and
output = "Argument[" + position + "]" + ".Parameter[" + p.getPosition() + "]"
)
}
/**
* Holds if `output` is a models as data string representation of, how values of type `tp`
* (or generics parameterized over `tp`) can be routed.
* This includes
* (1) The implicit synthetic field(s) of the declaring type of `callable`.
* (2) The return of `callable`.
* (3) Any delegate parameters of `callable`.
*/
private predicate output(DotNet::Callable callable, TypeParameter tp, string output) {
output = implicit(callable, tp)
or
returns(callable, tp, output)
or
delegateSink(callable, tp, output)
}
/**
* A class of callables that are relevant generating summaries for based
* on the Theorems for Free approach.
*/
class TypeBasedFlowTargetApi extends Specific::TargetApiSpecific {
TypeBasedFlowTargetApi() { Specific::isRelevantForTypeBasedFlowModels(this) }
/**
* Gets the string representation of all type based summaries for `this`
* inspired by the Theorems for Free approach.
*
* Examples could be (see C# psuedo code below)
* (1) `Get` returns a value of type `T`. We assume that the returned
* value was fetched from a (synthetic) field.
* (2) `Set` consumes a value of type `T`. We assume that the value is stored in
* a (synthetic) field.
* (3) `Apply<S>` is assumed to apply the provided function to a value stored in
* a (synthetic) field and return the result.
* (4) `Apply<S1,S2>` is assumed to apply the provided function to provided value
* and return the result.
* ```csharp
* public class MyGeneric<T> {
* public void Set(T x) { ... }
* public T Get() { ... }
* public S Apply<S>(Func<T, S> f) { ... }
* public S2 Apply<S1, S2>(S1 x, Func<S1, S2> f) { ... }
* }
* ```
*/
string getSummaries() {
exists(TypeParameter tp, string input, string output |
localTypeParameter(this, tp) and
input(this, input, tp) and
output(this, tp, output) and
input != output
|
result = asValueModel(this, input, output)
)
}
}
/**
* Returns the Theorems for Free inspired typed based summaries for `api`.
*/
string captureFlow(TypeBasedFlowTargetApi api) { result = api.getSummaries() }

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