Compare commits

..

2 Commits

Author SHA1 Message Date
Jean Helie
bc0e2947d7 use new mad kinds 2023-06-19 08:51:27 +02:00
Jean Helie
982bebea82 add raw framework generated models for spring framework 2023-06-16 12:08:20 +02:00
1399 changed files with 15052 additions and 56786 deletions

View File

@@ -1,9 +1,3 @@
common --enable_platform_specific_config
build --repo_env=CC=clang --repo_env=CXX=clang++
build:linux --cxxopt=-std=c++20
build:macos --cxxopt=-std=c++20 --cpu=darwin_x86_64
build:windows --cxxopt=/std:c++20 --cxxopt=/Zc:preprocessor
build --repo_env=CC=clang --repo_env=CXX=clang++ --cxxopt="-std=c++20"
try-import %workspace%/local.bazelrc

View File

@@ -1,29 +0,0 @@
name: "Check implicit this warnings"
on:
workflow_dispatch:
pull_request:
paths:
- "**qlpack.yml"
branches:
- main
- "rc/*"
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Check that implicit this warnings is enabled for all packs
shell: bash
run: |
EXIT_CODE=0
packs="$(find . -iname 'qlpack.yml')"
for pack_file in ${packs}; do
option="$(yq '.warnOnImplicitThis' ${pack_file})"
if [ "${option}" != "true" ]; then
echo "::error file=${pack_file}::warnOnImplicitThis property must be set to 'true' for pack ${pack_file}"
EXIT_CODE=1
fi
done
exit "${EXIT_CODE}"

View File

@@ -5,9 +5,9 @@ repos:
rev: v3.2.0
hooks:
- id: trailing-whitespace
exclude: /test/.*$(?<!\.ql)(?<!\.qll)(?<!\.qlref)|.*\.patch
exclude: /test/.*$(?<!\.ql)(?<!\.qll)(?<!\.qlref)
- id: end-of-file-fixer
exclude: /test/.*$(?<!\.ql)(?<!\.qll)(?<!\.qlref)|.*\.patch
exclude: /test/.*$(?<!\.ql)(?<!\.qll)(?<!\.qlref)
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v13.0.1
@@ -21,11 +21,6 @@ repos:
- id: autopep8
files: ^misc/codegen/.*\.py
- repo: https://github.com/warchant/pre-commit-buildifier
rev: 0.0.2
hooks:
- id: buildifier
- repo: local
hooks:
- id: codeql-format

View File

@@ -523,10 +523,6 @@
"python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll",
"ruby/ql/lib/codeql/ruby/typetracking/TypeTracker.qll"
],
"SummaryTypeTracker": [
"python/ql/lib/semmle/python/dataflow/new/internal/SummaryTypeTracker.qll",
"ruby/ql/lib/codeql/ruby/typetracking/internal/SummaryTypeTracker.qll"
],
"AccessPathSyntax": [
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/AccessPathSyntax.qll",
"go/ql/lib/semmle/go/dataflow/internal/AccessPathSyntax.qll",

View File

@@ -2,4 +2,3 @@ name: codeql/cpp-downgrades
groups: cpp
downgrades: .
library: true
warnOnImplicitThis: true

View File

@@ -4,4 +4,3 @@ groups:
- examples
dependencies:
codeql/cpp-all: ${workspace}
warnOnImplicitThis: true

View File

@@ -1,25 +1,3 @@
## 0.8.0
### New Features
* The `ProductFlow::StateConfigSig` signature now includes default predicates for `isBarrier1`, `isBarrier2`, `isAdditionalFlowStep1`, and `isAdditionalFlowStep1`. Hence, it is no longer needed to provide `none()` implementations of these predicates if they are not needed.
### Minor Analysis Improvements
* Deleted the deprecated `getURL` predicate from the `Container`, `Folder`, and `File` classes. Use the `getLocation` predicate instead.
## 0.7.4
No user-facing changes.
## 0.7.3
### Minor Analysis Improvements
* Deleted the deprecated `hasCopyConstructor` predicate from the `Class` class in `Class.qll`.
* Deleted many deprecated predicates and classes with uppercase `AST`, `SSA`, `CFG`, `API`, etc. in their names. Use the PascalCased versions instead.
* Deleted the deprecated `CodeDuplication.qll` file.
## 0.7.2
### New Features

View File

@@ -1,7 +1,6 @@
## 0.7.3
### Minor Analysis Improvements
---
category: minorAnalysis
---
* Deleted the deprecated `hasCopyConstructor` predicate from the `Class` class in `Class.qll`.
* Deleted many deprecated predicates and classes with uppercase `AST`, `SSA`, `CFG`, `API`, etc. in their names. Use the PascalCased versions instead.
* Deleted the deprecated `CodeDuplication.qll` file.
* Deleted the deprecated `CodeDuplication.qll` file.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* The `IRGuards` library has improved handling of pointer addition and subtraction operations.

View File

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

View File

@@ -1,9 +0,0 @@
## 0.8.0
### New Features
* The `ProductFlow::StateConfigSig` signature now includes default predicates for `isBarrier1`, `isBarrier2`, `isAdditionalFlowStep1`, and `isAdditionalFlowStep1`. Hence, it is no longer needed to provide `none()` implementations of these predicates if they are not needed.
### Minor Analysis Improvements
* Deleted the deprecated `getURL` predicate from the `Container`, `Folder`, and `File` classes. Use the `getLocation` predicate instead.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.8.0
lastReleaseVersion: 0.7.2

View File

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

View File

@@ -34,6 +34,14 @@ class Container extends Locatable, @container {
*/
string getAbsolutePath() { none() } // overridden by subclasses
/**
* DEPRECATED: Use `getLocation` instead.
* Gets a URL representing the location of this container.
*
* For more information see [Providing URLs](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/#providing-urls).
*/
deprecated string getURL() { none() } // overridden by subclasses
/**
* Gets the relative path of this file or folder from the root folder of the
* analyzed source location. The relative path of the root folder itself is
@@ -175,6 +183,12 @@ class Folder extends Container, @folder {
}
override string getAPrimaryQlClass() { result = "Folder" }
/**
* DEPRECATED: Use `getLocation` instead.
* Gets the URL of this folder.
*/
deprecated override string getURL() { result = "file://" + this.getAbsolutePath() + ":0:0:0:0" }
}
/**
@@ -199,6 +213,12 @@ class File extends Container, @file {
result.hasLocationInfo(_, 0, 0, 0, 0)
}
/**
* DEPRECATED: Use `getLocation` instead.
* Gets the URL of this file.
*/
deprecated override string getURL() { result = "file://" + this.getAbsolutePath() + ":0:0:0:0" }
/** Holds if this file was compiled as C (at any point). */
predicate compiledAsC() { fileannotations(underlyingElement(this), 1, "compiled as c", "1") }

View File

@@ -627,20 +627,6 @@ private predicate sub_lt(
x = int_value(rhs.getRight()) and
k = c - x
)
or
exists(PointerSubInstruction lhs, int c, int x |
compares_lt(cmp, lhs.getAUse(), right, c, isLt, testIsTrue) and
left = lhs.getLeftOperand() and
x = int_value(lhs.getRight()) and
k = c + x
)
or
exists(PointerSubInstruction rhs, int c, int x |
compares_lt(cmp, left, rhs.getAUse(), c, isLt, testIsTrue) and
right = rhs.getLeftOperand() and
x = int_value(rhs.getRight()) and
k = c - x
)
}
// left + x < right + c => left < right + (c-x)
@@ -667,26 +653,6 @@ private predicate add_lt(
) and
k = c + x
)
or
exists(PointerAddInstruction lhs, int c, int x |
compares_lt(cmp, lhs.getAUse(), right, c, isLt, testIsTrue) and
(
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
or
left = lhs.getRightOperand() and x = int_value(lhs.getLeft())
) and
k = c - x
)
or
exists(PointerAddInstruction rhs, int c, int x |
compares_lt(cmp, left, rhs.getAUse(), c, isLt, testIsTrue) and
(
right = rhs.getLeftOperand() and x = int_value(rhs.getRight())
or
right = rhs.getRightOperand() and x = int_value(rhs.getLeft())
) and
k = c + x
)
}
// left - x == right + c => left == right + (c+x)
@@ -707,20 +673,6 @@ private predicate sub_eq(
x = int_value(rhs.getRight()) and
k = c - x
)
or
exists(PointerSubInstruction lhs, int c, int x |
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, testIsTrue) and
left = lhs.getLeftOperand() and
x = int_value(lhs.getRight()) and
k = c + x
)
or
exists(PointerSubInstruction rhs, int c, int x |
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, testIsTrue) and
right = rhs.getLeftOperand() and
x = int_value(rhs.getRight()) and
k = c - x
)
}
// left + x == right + c => left == right + (c-x)
@@ -747,26 +699,6 @@ private predicate add_eq(
) and
k = c + x
)
or
exists(PointerAddInstruction lhs, int c, int x |
compares_eq(cmp, lhs.getAUse(), right, c, areEqual, testIsTrue) and
(
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
or
left = lhs.getRightOperand() and x = int_value(lhs.getLeft())
) and
k = c - x
)
or
exists(PointerAddInstruction rhs, int c, int x |
compares_eq(cmp, left, rhs.getAUse(), c, areEqual, testIsTrue) and
(
right = rhs.getLeftOperand() and x = int_value(rhs.getRight())
or
right = rhs.getRightOperand() and x = int_value(rhs.getLeft())
) and
k = c + x
)
}
/** The int value of integer constant expression. */

View File

@@ -460,6 +460,7 @@ module Impl<FullStateConfigSig Config> {
* The Boolean `cc` records whether the node is reached through an
* argument in a call.
*/
pragma[assume_small_delta]
private predicate fwdFlow(NodeEx node, Cc cc) {
sourceNode(node, _) and
if hasSourceCallCtx() then cc = true else cc = false
@@ -569,6 +570,7 @@ module Impl<FullStateConfigSig Config> {
/**
* Holds if `c` is the target of a store in the flow covered by `fwdFlow`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate fwdFlowConsCand(Content c) {
exists(NodeEx mid, NodeEx node |
@@ -1214,6 +1216,7 @@ module Impl<FullStateConfigSig Config> {
fwdFlow1(_, _, _, _, _, _, t0, t, ap, _) and t0 != t
}
pragma[assume_small_delta]
pragma[nomagic]
private predicate fwdFlow0(
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
@@ -2018,8 +2021,7 @@ module Impl<FullStateConfigSig Config> {
FlowCheckNode() {
castNode(this.asNode()) or
clearsContentCached(this.asNode(), _) or
expectsContentCached(this.asNode(), _) or
neverSkipInPathGraph(this.asNode())
expectsContentCached(this.asNode(), _)
}
}
@@ -2774,6 +2776,7 @@ module Impl<FullStateConfigSig Config> {
/**
* Gets the number of `AccessPath`s that correspond to `apa`.
*/
pragma[assume_small_delta]
private int countAps(AccessPathApprox apa) {
evalUnfold(apa, false) and
result = 1 and
@@ -2792,6 +2795,7 @@ module Impl<FullStateConfigSig Config> {
* that it is expanded to a precise head-tail representation.
*/
language[monotonicAggregates]
pragma[assume_small_delta]
private int countPotentialAps(AccessPathApprox apa) {
apa instanceof AccessPathApproxNil and result = 1
or
@@ -2828,6 +2832,7 @@ module Impl<FullStateConfigSig Config> {
}
private newtype TPathNode =
pragma[assume_small_delta]
TPathNodeMid(
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap
) {
@@ -2912,6 +2917,7 @@ module Impl<FullStateConfigSig Config> {
override AccessPathFrontHead getFront() { result = TFrontHead(head_) }
pragma[assume_small_delta]
override AccessPathApproxCons getApprox() {
result = TConsNil(head_, t) and tail_ = TAccessPathNil()
or
@@ -2920,6 +2926,7 @@ module Impl<FullStateConfigSig Config> {
result = TCons1(head_, this.length())
}
pragma[assume_small_delta]
override int length() { result = 1 + tail_.length() }
private string toStringImpl(boolean needsSuffix) {
@@ -3371,6 +3378,7 @@ module Impl<FullStateConfigSig Config> {
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep0(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t,
@@ -3583,6 +3591,7 @@ module Impl<FullStateConfigSig Config> {
)
}
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathThroughCallable0(
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc,

View File

@@ -187,6 +187,7 @@ private module LambdaFlow {
else any()
}
pragma[assume_small_delta]
pragma[nomagic]
predicate revLambdaFlow0(
DataFlowCall lambdaCall, LambdaCallKind kind, Node node, DataFlowType t, boolean toReturn,
@@ -273,6 +274,7 @@ private module LambdaFlow {
)
}
pragma[assume_small_delta]
pragma[nomagic]
predicate revLambdaFlowOut(
DataFlowCall lambdaCall, LambdaCallKind kind, TReturnPositionSimple pos, DataFlowType t,

View File

@@ -235,12 +235,6 @@ class CastNode extends Node {
CastNode() { none() } // stub implementation
}
/**
* Holds if `n` should never be skipped over in the `PathGraph` and in path
* explanations.
*/
predicate neverSkipInPathGraph(Node n) { none() }
class DataFlowCallable = Function;
class DataFlowExpr = Expr;

View File

@@ -460,6 +460,7 @@ module Impl<FullStateConfigSig Config> {
* The Boolean `cc` records whether the node is reached through an
* argument in a call.
*/
pragma[assume_small_delta]
private predicate fwdFlow(NodeEx node, Cc cc) {
sourceNode(node, _) and
if hasSourceCallCtx() then cc = true else cc = false
@@ -569,6 +570,7 @@ module Impl<FullStateConfigSig Config> {
/**
* Holds if `c` is the target of a store in the flow covered by `fwdFlow`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate fwdFlowConsCand(Content c) {
exists(NodeEx mid, NodeEx node |
@@ -1214,6 +1216,7 @@ module Impl<FullStateConfigSig Config> {
fwdFlow1(_, _, _, _, _, _, t0, t, ap, _) and t0 != t
}
pragma[assume_small_delta]
pragma[nomagic]
private predicate fwdFlow0(
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
@@ -2018,8 +2021,7 @@ module Impl<FullStateConfigSig Config> {
FlowCheckNode() {
castNode(this.asNode()) or
clearsContentCached(this.asNode(), _) or
expectsContentCached(this.asNode(), _) or
neverSkipInPathGraph(this.asNode())
expectsContentCached(this.asNode(), _)
}
}
@@ -2774,6 +2776,7 @@ module Impl<FullStateConfigSig Config> {
/**
* Gets the number of `AccessPath`s that correspond to `apa`.
*/
pragma[assume_small_delta]
private int countAps(AccessPathApprox apa) {
evalUnfold(apa, false) and
result = 1 and
@@ -2792,6 +2795,7 @@ module Impl<FullStateConfigSig Config> {
* that it is expanded to a precise head-tail representation.
*/
language[monotonicAggregates]
pragma[assume_small_delta]
private int countPotentialAps(AccessPathApprox apa) {
apa instanceof AccessPathApproxNil and result = 1
or
@@ -2828,6 +2832,7 @@ module Impl<FullStateConfigSig Config> {
}
private newtype TPathNode =
pragma[assume_small_delta]
TPathNodeMid(
NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t, AccessPath ap
) {
@@ -2912,6 +2917,7 @@ module Impl<FullStateConfigSig Config> {
override AccessPathFrontHead getFront() { result = TFrontHead(head_) }
pragma[assume_small_delta]
override AccessPathApproxCons getApprox() {
result = TConsNil(head_, t) and tail_ = TAccessPathNil()
or
@@ -2920,6 +2926,7 @@ module Impl<FullStateConfigSig Config> {
result = TCons1(head_, this.length())
}
pragma[assume_small_delta]
override int length() { result = 1 + tail_.length() }
private string toStringImpl(boolean needsSuffix) {
@@ -3371,6 +3378,7 @@ module Impl<FullStateConfigSig Config> {
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep0(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t,
@@ -3583,6 +3591,7 @@ module Impl<FullStateConfigSig Config> {
)
}
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathThroughCallable0(
DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc,

View File

@@ -187,6 +187,7 @@ private module LambdaFlow {
else any()
}
pragma[assume_small_delta]
pragma[nomagic]
predicate revLambdaFlow0(
DataFlowCall lambdaCall, LambdaCallKind kind, Node node, DataFlowType t, boolean toReturn,
@@ -273,6 +274,7 @@ private module LambdaFlow {
)
}
pragma[assume_small_delta]
pragma[nomagic]
predicate revLambdaFlowOut(
DataFlowCall lambdaCall, LambdaCallKind kind, TReturnPositionSimple pos, DataFlowType t,

View File

@@ -193,89 +193,86 @@ private class SingleUseOperandNode0 extends OperandNode0, TSingleUseOperandNode0
SingleUseOperandNode0() { this = TSingleUseOperandNode0(op) }
}
private module IndirectOperands {
/**
* INTERNAL: Do not use.
*
* A node that represents the indirect value of an operand in the IR
* after `index` number of loads.
*
* Note: Unlike `RawIndirectOperand`, a value of type `IndirectOperand` may
* be an `OperandNode`.
*/
class IndirectOperand extends Node {
Operand operand;
int indirectionIndex;
IndirectOperand() {
this.(RawIndirectOperand).getOperand() = operand and
this.(RawIndirectOperand).getIndirectionIndex() = indirectionIndex
or
nodeHasOperand(this, Ssa::getIRRepresentationOfIndirectOperand(operand, indirectionIndex),
indirectionIndex - 1)
}
/** Gets the underlying operand. */
Operand getOperand() { result = operand }
/** Gets the underlying indirection index. */
int getIndirectionIndex() { result = indirectionIndex }
/**
* INTERNAL: Do not use.
*
* A node that represents the indirect value of an operand in the IR
* after `index` number of loads.
*
* Note: Unlike `RawIndirectOperand`, a value of type `IndirectOperand` may
* be an `OperandNode`.
* Holds if this `IndirectOperand` is represented directly in the IR instead of
* a `RawIndirectionOperand` with operand `op` and indirection index `index`.
*/
abstract class IndirectOperand extends Node {
/** Gets the underlying operand and the underlying indirection index. */
abstract predicate hasOperandAndIndirectionIndex(Operand operand, int indirectionIndex);
}
private class IndirectOperandFromRaw extends IndirectOperand instanceof RawIndirectOperand {
override predicate hasOperandAndIndirectionIndex(Operand operand, int indirectionIndex) {
operand = RawIndirectOperand.super.getOperand() and
indirectionIndex = RawIndirectOperand.super.getIndirectionIndex()
}
}
private class IndirectOperandFromIRRepr extends IndirectOperand {
Operand operand;
int indirectionIndex;
IndirectOperandFromIRRepr() {
exists(Operand repr |
repr = Ssa::getIRRepresentationOfIndirectOperand(operand, indirectionIndex) and
nodeHasOperand(this, repr, indirectionIndex - 1)
)
}
override predicate hasOperandAndIndirectionIndex(Operand op, int index) {
op = operand and index = indirectionIndex
}
predicate isIRRepresentationOf(Operand op, int index) {
this instanceof OperandNode and
(
op = operand and
index = indirectionIndex
)
}
}
import IndirectOperands
/**
* INTERNAL: Do not use.
*
* A node that represents the indirect value of an instruction in the IR
* after `index` number of loads.
*
* Note: Unlike `RawIndirectInstruction`, a value of type `IndirectInstruction` may
* be an `InstructionNode`.
*/
class IndirectInstruction extends Node {
Instruction instr;
int indirectionIndex;
IndirectInstruction() {
this.(RawIndirectInstruction).getInstruction() = instr and
this.(RawIndirectInstruction).getIndirectionIndex() = indirectionIndex
or
nodeHasInstruction(this, Ssa::getIRRepresentationOfIndirectInstruction(instr, indirectionIndex),
indirectionIndex - 1)
}
/** Gets the underlying instruction. */
Instruction getInstruction() { result = instr }
/** Gets the underlying indirection index. */
int getIndirectionIndex() { result = indirectionIndex }
private module IndirectInstructions {
/**
* INTERNAL: Do not use.
*
* A node that represents the indirect value of an instruction in the IR
* after `index` number of loads.
*
* Note: Unlike `RawIndirectInstruction`, a value of type `IndirectInstruction` may
* be an `InstructionNode`.
* Holds if this `IndirectInstruction` is represented directly in the IR instead of
* a `RawIndirectionInstruction` with instruction `i` and indirection index `index`.
*/
abstract class IndirectInstruction extends Node {
/** Gets the underlying operand and the underlying indirection index. */
abstract predicate hasInstructionAndIndirectionIndex(Instruction instr, int index);
}
private class IndirectInstructionFromRaw extends IndirectInstruction instanceof RawIndirectInstruction
{
override predicate hasInstructionAndIndirectionIndex(Instruction instr, int index) {
instr = RawIndirectInstruction.super.getInstruction() and
index = RawIndirectInstruction.super.getIndirectionIndex()
}
}
private class IndirectInstructionFromIRRepr extends IndirectInstruction {
Instruction instr;
int indirectionIndex;
IndirectInstructionFromIRRepr() {
exists(Instruction repr |
repr = Ssa::getIRRepresentationOfIndirectInstruction(instr, indirectionIndex) and
nodeHasInstruction(this, repr, indirectionIndex - 1)
)
}
override predicate hasInstructionAndIndirectionIndex(Instruction i, int index) {
i = instr and index = indirectionIndex
}
predicate isIRRepresentationOf(Instruction i, int index) {
this instanceof InstructionNode and
(
i = instr and
index = indirectionIndex
)
}
}
import IndirectInstructions
/** Gets the callable in which this node occurs. */
DataFlowCallable nodeGetEnclosingCallable(Node n) { result = n.getEnclosingCallable() }
@@ -321,11 +318,9 @@ private class PrimaryArgumentNode extends ArgumentNode, OperandNode {
private class SideEffectArgumentNode extends ArgumentNode, SideEffectOperandNode {
override predicate argumentOf(DataFlowCall dfCall, ArgumentPosition pos) {
exists(int indirectionIndex |
pos = TIndirectionPosition(argumentIndex, pragma[only_bind_into](indirectionIndex)) and
this.getCallInstruction() = dfCall and
super.hasAddressOperandAndIndirectionIndex(_, pragma[only_bind_into](indirectionIndex))
)
this.getCallInstruction() = dfCall and
pos.(IndirectionPosition).getArgumentIndex() = this.getArgumentIndex() and
pos.(IndirectionPosition).getIndirectionIndex() = super.getIndirectionIndex()
}
}
@@ -653,16 +648,13 @@ predicate jumpStep(Node n1, Node n2) {
* Holds if data can flow from `node1` to `node2` via an assignment to `f`.
* Thus, `node2` references an object with a field `f` that contains the
* value of `node1`.
*
* The boolean `certain` is true if the destination address does not involve
* any pointer arithmetic, and false otherwise.
*/
predicate storeStepImpl(Node node1, Content c, PostFieldUpdateNode node2, boolean certain) {
predicate storeStep(Node node1, Content c, PostFieldUpdateNode node2) {
exists(int indirectionIndex1, int numberOfLoads, StoreInstruction store |
nodeHasInstruction(node1, store, pragma[only_bind_into](indirectionIndex1)) and
node2.getIndirectionIndex() = 1 and
numberOfLoadsFromOperand(node2.getFieldAddress(), store.getDestinationAddressOperand(),
numberOfLoads, certain)
numberOfLoads)
|
exists(FieldContent fc | fc = c |
fc.getField() = node2.getUpdatedField() and
@@ -676,34 +668,21 @@ predicate storeStepImpl(Node node1, Content c, PostFieldUpdateNode node2, boolea
)
}
/**
* Holds if data can flow from `node1` to `node2` via an assignment to `f`.
* Thus, `node2` references an object with a field `f` that contains the
* value of `node1`.
*/
predicate storeStep(Node node1, Content c, PostFieldUpdateNode node2) {
storeStepImpl(node1, c, node2, _)
}
/**
* Holds if `operandFrom` flows to `operandTo` using a sequence of conversion-like
* operations and exactly `n` `LoadInstruction` operations.
*/
private predicate numberOfLoadsFromOperandRec(
Operand operandFrom, Operand operandTo, int ind, boolean certain
) {
private predicate numberOfLoadsFromOperandRec(Operand operandFrom, Operand operandTo, int ind) {
exists(Instruction load | Ssa::isDereference(load, operandFrom) |
operandTo = operandFrom and ind = 0 and certain = true
operandTo = operandFrom and ind = 0
or
numberOfLoadsFromOperand(load.getAUse(), operandTo, ind - 1, certain)
numberOfLoadsFromOperand(load.getAUse(), operandTo, ind - 1)
)
or
exists(Operand op, Instruction instr, boolean isPointerArith, boolean certain0 |
exists(Operand op, Instruction instr |
instr = op.getDef() and
conversionFlow(operandFrom, instr, isPointerArith, _) and
numberOfLoadsFromOperand(op, operandTo, ind, certain0)
|
if isPointerArith = true then certain = false else certain = certain0
conversionFlow(operandFrom, instr, _, _) and
numberOfLoadsFromOperand(op, operandTo, ind)
)
}
@@ -711,16 +690,13 @@ private predicate numberOfLoadsFromOperandRec(
* Holds if `operandFrom` flows to `operandTo` using a sequence of conversion-like
* operations and exactly `n` `LoadInstruction` operations.
*/
private predicate numberOfLoadsFromOperand(
Operand operandFrom, Operand operandTo, int n, boolean certain
) {
numberOfLoadsFromOperandRec(operandFrom, operandTo, n, certain)
private predicate numberOfLoadsFromOperand(Operand operandFrom, Operand operandTo, int n) {
numberOfLoadsFromOperandRec(operandFrom, operandTo, n)
or
not Ssa::isDereference(_, operandFrom) and
not conversionFlow(operandFrom, _, _, _) and
operandFrom = operandTo and
n = 0 and
certain = true
n = 0
}
// Needed to join on both an operand and an index at the same time.
@@ -750,7 +726,7 @@ predicate readStep(Node node1, Content c, Node node2) {
// The `1` here matches the `node2.getIndirectionIndex() = 1` conjunct
// in `storeStep`.
nodeHasOperand(node1, fa1.getObjectAddressOperand(), 1) and
numberOfLoadsFromOperand(fa1, operand, numberOfLoads, _)
numberOfLoadsFromOperand(fa1, operand, numberOfLoads)
|
exists(FieldContent fc | fc = c |
fc.getField() = fa1.getField() and
@@ -768,33 +744,7 @@ predicate readStep(Node node1, Content c, Node node2) {
* Holds if values stored inside content `c` are cleared at node `n`.
*/
predicate clearsContent(Node n, Content c) {
n =
any(PostUpdateNode pun, Content d | d.impliesClearOf(c) and storeStepImpl(_, d, pun, true) | pun)
.getPreUpdateNode() and
(
// The crement operations and pointer addition and subtraction self-assign. We do not
// want to clear the contents if it is indirectly pointed at by any of these operations,
// as part of the contents might still be accessible afterwards. If there is no such
// indirection clearing the contents is safe.
not exists(Operand op, Cpp::Operation p |
n.(IndirectOperand).hasOperandAndIndirectionIndex(op, _) and
(
p instanceof Cpp::AssignPointerAddExpr or
p instanceof Cpp::AssignPointerSubExpr or
p instanceof Cpp::CrementOperation
)
|
p.getAnOperand() = op.getUse().getAst()
)
or
forex(PostUpdateNode pun, Content d |
pragma[only_bind_into](d).impliesClearOf(pragma[only_bind_into](c)) and
storeStepImpl(_, d, pun, true) and
pun.getPreUpdateNode() = n
|
c.getIndirectionIndex() = d.getIndirectionIndex()
)
)
none() // stub implementation
}
/**
@@ -833,12 +783,6 @@ class CastNode extends Node {
CastNode() { none() } // stub implementation
}
/**
* Holds if `n` should never be skipped over in the `PathGraph` and in path
* explanations.
*/
predicate neverSkipInPathGraph(Node n) { none() }
/**
* A function that may contain code or a variable that may contain itself. When
* flow crosses from one _enclosing callable_ to another, the interprocedural
@@ -856,73 +800,7 @@ class DataFlowCall extends CallInstruction {
Function getEnclosingCallable() { result = this.getEnclosingFunction() }
}
module IsUnreachableInCall {
private import semmle.code.cpp.ir.ValueNumbering
private import semmle.code.cpp.controlflow.IRGuards as G
private class ConstantIntegralTypeArgumentNode extends PrimaryArgumentNode {
int value;
ConstantIntegralTypeArgumentNode() {
value = op.getDef().(IntegerConstantInstruction).getValue().toInt()
}
int getValue() { result = value }
}
pragma[nomagic]
private predicate ensuresEq(Operand left, Operand right, int k, IRBlock block, boolean areEqual) {
any(G::IRGuardCondition guard).ensuresEq(left, right, k, block, areEqual)
}
pragma[nomagic]
private predicate ensuresLt(Operand left, Operand right, int k, IRBlock block, boolean areEqual) {
any(G::IRGuardCondition guard).ensuresLt(left, right, k, block, areEqual)
}
predicate isUnreachableInCall(Node n, DataFlowCall call) {
exists(
DirectParameterNode paramNode, ConstantIntegralTypeArgumentNode arg,
IntegerConstantInstruction constant, int k, Operand left, Operand right, IRBlock block
|
// arg flows into `paramNode`
DataFlowImplCommon::viableParamArg(call, paramNode, arg) and
left = constant.getAUse() and
right = valueNumber(paramNode.getInstruction()).getAUse() and
block = n.getBasicBlock()
|
// and there's a guard condition which ensures that the result of `left == right + k` is `areEqual`
exists(boolean areEqual |
ensuresEq(pragma[only_bind_into](left), pragma[only_bind_into](right),
pragma[only_bind_into](k), pragma[only_bind_into](block), areEqual)
|
// this block ensures that left = right + k, but it holds that `left != right + k`
areEqual = true and
constant.getValue().toInt() != arg.getValue() + k
or
// this block ensures that or `left != right + k`, but it holds that `left = right + k`
areEqual = false and
constant.getValue().toInt() = arg.getValue() + k
)
or
// or there's a guard condition which ensures that the result of `left < right + k` is `isLessThan`
exists(boolean isLessThan |
ensuresLt(pragma[only_bind_into](left), pragma[only_bind_into](right),
pragma[only_bind_into](k), pragma[only_bind_into](block), isLessThan)
|
isLessThan = true and
// this block ensures that `left < right + k`, but it holds that `left >= right + k`
constant.getValue().toInt() >= arg.getValue() + k
or
// this block ensures that `left >= right + k`, but it holds that `left < right + k`
isLessThan = false and
constant.getValue().toInt() < arg.getValue() + k
)
)
}
}
import IsUnreachableInCall
predicate isUnreachableInCall(Node n, DataFlowCall call) { none() } // stub implementation
int accessPathLimit() { result = 5 }
@@ -961,7 +839,7 @@ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preserves
* One example would be to allow flow like `p.foo = p.bar;`, which is disallowed
* by default as a heuristic.
*/
predicate allowParameterReturnInSelf(ParameterNode p) { p instanceof IndirectParameterNode }
predicate allowParameterReturnInSelf(ParameterNode p) { none() }
private predicate fieldHasApproxName(Field f, string s) {
s = f.getName().charAt(0) and

View File

@@ -274,7 +274,7 @@ class Node extends TIRDataFlowNode {
* represents the value of `**x` going into `f`.
*/
Expr asIndirectArgument(int index) {
this.(SideEffectOperandNode).hasAddressOperandAndIndirectionIndex(_, index) and
this.(SideEffectOperandNode).getIndirectionIndex() = index and
result = this.(SideEffectOperandNode).getArgument()
}
@@ -317,7 +317,7 @@ class Node extends TIRDataFlowNode {
index = 0 and
result = this.(ExplicitParameterNode).getParameter()
or
this.(IndirectParameterNode).hasInstructionAndIndirectionIndex(_, index) and
this.(IndirectParameterNode).getIndirectionIndex() = index and
result = this.(IndirectParameterNode).getParameter()
}
@@ -577,20 +577,15 @@ class SsaPhiNode extends Node, TSsaPhiNode {
*
* A node representing a value after leaving a function.
*/
class SideEffectOperandNode extends Node instanceof IndirectOperand {
class SideEffectOperandNode extends Node, IndirectOperand {
CallInstruction call;
int argumentIndex;
SideEffectOperandNode() {
IndirectOperand.super.hasOperandAndIndirectionIndex(call.getArgumentOperand(argumentIndex), _)
}
SideEffectOperandNode() { operand = call.getArgumentOperand(argumentIndex) }
CallInstruction getCallInstruction() { result = call }
/** Gets the underlying operand and the underlying indirection index. */
predicate hasAddressOperandAndIndirectionIndex(Operand operand, int indirectionIndex) {
IndirectOperand.super.hasOperandAndIndirectionIndex(operand, indirectionIndex)
}
Operand getAddressOperand() { result = operand }
int getArgumentIndex() { result = argumentIndex }
@@ -670,10 +665,10 @@ class InitialGlobalValue extends Node, TInitialGlobalValue {
*
* A node representing an indirection of a parameter.
*/
class IndirectParameterNode extends Node instanceof IndirectInstruction {
class IndirectParameterNode extends Node, IndirectInstruction {
InitializeParameterInstruction init;
IndirectParameterNode() { IndirectInstruction.super.hasInstructionAndIndirectionIndex(init, _) }
IndirectParameterNode() { this.getInstruction() = init }
int getArgumentIndex() { init.hasIndex(result) }
@@ -682,12 +677,7 @@ class IndirectParameterNode extends Node instanceof IndirectInstruction {
override Declaration getEnclosingCallable() { result = this.getFunction() }
override Declaration getFunction() { result = init.getEnclosingFunction() }
/** Gets the underlying operand and the underlying indirection index. */
predicate hasInstructionAndIndirectionIndex(Instruction instr, int index) {
IndirectInstruction.super.hasInstructionAndIndirectionIndex(instr, index)
}
override Declaration getFunction() { result = this.getInstruction().getEnclosingFunction() }
override Location getLocationImpl() { result = this.getParameter().getLocation() }
@@ -709,8 +699,7 @@ class IndirectReturnNode extends Node {
IndirectReturnNode() {
this instanceof FinalParameterNode
or
this.(IndirectOperand)
.hasOperandAndIndirectionIndex(any(ReturnValueInstruction ret).getReturnAddressOperand(), _)
this.(IndirectOperand).getOperand() = any(ReturnValueInstruction ret).getReturnAddressOperand()
}
override Declaration getEnclosingCallable() { result = this.getFunction() }
@@ -733,7 +722,7 @@ class IndirectReturnNode extends Node {
int getIndirectionIndex() {
result = this.(FinalParameterNode).getIndirectionIndex()
or
this.(IndirectOperand).hasOperandAndIndirectionIndex(_, result)
result = this.(IndirectOperand).getIndirectionIndex()
}
}
@@ -1117,8 +1106,7 @@ predicate exprNodeShouldBeInstruction(Node node, Expr e) {
/** Holds if `node` should be an `IndirectInstruction` that maps `node.asIndirectExpr()` to `e`. */
predicate indirectExprNodeShouldBeIndirectInstruction(IndirectInstruction node, Expr e) {
exists(Instruction instr |
node.hasInstructionAndIndirectionIndex(instr, _) and
not indirectExprNodeShouldBeIndirectOperand(_, e)
instr = node.getInstruction() and not indirectExprNodeShouldBeIndirectOperand(_, e)
|
e = instr.(VariableAddressInstruction).getAst().(Expr).getFullyConverted()
or
@@ -1319,8 +1307,8 @@ pragma[noinline]
private predicate indirectParameterNodeHasArgumentIndexAndIndex(
IndirectParameterNode node, int argumentIndex, int indirectionIndex
) {
node.hasInstructionAndIndirectionIndex(_, indirectionIndex) and
node.getArgumentIndex() = argumentIndex
node.getArgumentIndex() = argumentIndex and
node.getIndirectionIndex() = indirectionIndex
}
/** A synthetic parameter to model the pointed-to object of a pointer parameter. */
@@ -1491,14 +1479,18 @@ VariableNode variableNode(Variable v) {
*/
Node uninitializedNode(LocalVariable v) { none() }
pragma[noinline]
predicate hasOperandAndIndex(IndirectOperand indirectOperand, Operand operand, int indirectionIndex) {
indirectOperand.hasOperandAndIndirectionIndex(operand, indirectionIndex)
indirectOperand.getOperand() = operand and
indirectOperand.getIndirectionIndex() = indirectionIndex
}
pragma[noinline]
predicate hasInstructionAndIndex(
IndirectInstruction indirectInstr, Instruction instr, int indirectionIndex
) {
indirectInstr.hasInstructionAndIndirectionIndex(instr, indirectionIndex)
indirectInstr.getInstruction() = instr and
indirectInstr.getIndirectionIndex() = indirectionIndex
}
cached
@@ -1664,7 +1656,8 @@ module ExprFlowCached {
private predicate isIndirectBaseOfArrayAccess(IndirectOperand n, Expr e) {
exists(LoadInstruction load, PointerArithmeticInstruction pai |
pai = load.getSourceAddress() and
n.hasOperandAndIndirectionIndex(pai.getLeftOperand(), 1) and
pai.getLeftOperand() = n.getOperand() and
n.getIndirectionIndex() = 1 and
e = load.getConvertedResultExpression()
)
}
@@ -1832,20 +1825,6 @@ class Content extends TContent {
predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
path = "" and sl = 0 and sc = 0 and el = 0 and ec = 0
}
/** Gets the indirection index of this `Content`. */
abstract int getIndirectionIndex();
/**
* INTERNAL: Do not use.
*
* Holds if a write to this `Content` implies that `c` is
* also cleared.
*
* For example, a write to a field `f` implies that any content of
* the form `*f` is also cleared.
*/
abstract predicate impliesClearOf(Content c);
}
/** A reference through a non-union instance field. */
@@ -1863,21 +1842,10 @@ class FieldContent extends Content, TFieldContent {
Field getField() { result = f }
/** Gets the indirection index of this `FieldContent`. */
pragma[inline]
override int getIndirectionIndex() {
int getIndirectionIndex() {
pragma[only_bind_into](result) = pragma[only_bind_out](indirectionIndex)
}
override predicate impliesClearOf(Content c) {
exists(FieldContent fc |
fc = c and
fc.getField() = f and
// If `this` is `f` then `c` is cleared if it's of the
// form `*f`, `**f`, etc.
fc.getIndirectionIndex() >= indirectionIndex
)
}
}
/** A reference through an instance field of a union. */
@@ -1902,21 +1870,9 @@ class UnionContent extends Content, TUnionContent {
/** Gets the indirection index of this `UnionContent`. */
pragma[inline]
override int getIndirectionIndex() {
int getIndirectionIndex() {
pragma[only_bind_into](result) = pragma[only_bind_out](indirectionIndex)
}
override predicate impliesClearOf(Content c) {
exists(UnionContent uc |
uc = c and
uc.getUnion() = u and
// If `this` is `u` then `c` is cleared if it's of the
// form `*u`, `**u`, etc. (and we ignore `bytes` because
// we know the entire union is overwritten because it's a
// union).
uc.getIndirectionIndex() >= indirectionIndex
)
}
}
/**

View File

@@ -13,7 +13,7 @@ class FieldFlowPropertyProvider extends IRPropertyProvider {
override string getOperandProperty(Operand operand, string key) {
exists(PostFieldUpdateNode pfun, Content content |
key = "store " + content.toString() and
pfun.getPreUpdateNode().(IndirectOperand).hasOperandAndIndirectionIndex(operand, _) and
operand = pfun.getPreUpdateNode().(IndirectOperand).getOperand() and
result =
strictconcat(string element, Node node |
storeStep(node, content, pfun) and
@@ -25,7 +25,7 @@ class FieldFlowPropertyProvider extends IRPropertyProvider {
or
exists(Node node2, Content content |
key = "read " + content.toString() and
node2.(IndirectOperand).hasOperandAndIndirectionIndex(operand, _) and
operand = node2.(IndirectOperand).getOperand() and
result =
strictconcat(string element, Node node1 |
readStep(node1, content, node2) and

View File

@@ -18,12 +18,9 @@ private string stars(int k) {
}
string starsForNode(Node node) {
exists(int indirectionIndex |
node.(IndirectInstruction).hasInstructionAndIndirectionIndex(_, indirectionIndex) or
node.(IndirectOperand).hasOperandAndIndirectionIndex(_, indirectionIndex)
|
result = stars(indirectionIndex)
)
result = stars(node.(IndirectInstruction).getIndirectionIndex())
or
result = stars(node.(IndirectOperand).getIndirectionIndex())
or
not node instanceof IndirectInstruction and
not node instanceof IndirectOperand and

View File

@@ -192,13 +192,13 @@ module ProductFlow {
* Holds if data flow through `node` is prohibited through the first projection of the product
* dataflow graph when the flow state is `state`.
*/
default predicate isBarrier1(DataFlow::Node node, FlowState1 state) { none() }
predicate isBarrier1(DataFlow::Node node, FlowState1 state);
/**
* Holds if data flow through `node` is prohibited through the second projection of the product
* dataflow graph when the flow state is `state`.
*/
default predicate isBarrier2(DataFlow::Node node, FlowState2 state) { none() }
predicate isBarrier2(DataFlow::Node node, FlowState2 state);
/**
* Holds if data flow through `node` is prohibited through the first projection of the product
@@ -237,11 +237,9 @@ module ProductFlow {
*
* This step is only applicable in `state1` and updates the flow state to `state2`.
*/
default predicate isAdditionalFlowStep1(
predicate isAdditionalFlowStep1(
DataFlow::Node node1, FlowState1 state1, DataFlow::Node node2, FlowState1 state2
) {
none()
}
);
/**
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps in
@@ -255,11 +253,9 @@ module ProductFlow {
*
* This step is only applicable in `state1` and updates the flow state to `state2`.
*/
default predicate isAdditionalFlowStep2(
predicate isAdditionalFlowStep2(
DataFlow::Node node1, FlowState2 state1, DataFlow::Node node2, FlowState2 state2
) {
none()
}
);
/**
* Holds if data flow into `node` is prohibited in the first projection of the product
@@ -363,6 +359,7 @@ module ProductFlow {
Config::isSinkPair(node1.getNode(), node1.getState(), node2.getNode(), node2.getState())
}
pragma[assume_small_delta]
pragma[nomagic]
private predicate fwdReachableInterprocEntry(Flow1::PathNode node1, Flow2::PathNode node2) {
isSourcePair(node1, node2)
@@ -399,6 +396,7 @@ module ProductFlow {
fwdIsSuccessorExit(pragma[only_bind_into](mid1), pragma[only_bind_into](mid2), succ1, succ2)
}
pragma[assume_small_delta]
private predicate fwdIsSuccessor(
Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode succ1, Flow2::PathNode succ2
) {
@@ -408,6 +406,7 @@ module ProductFlow {
)
}
pragma[assume_small_delta]
pragma[nomagic]
private predicate revReachableInterprocEntry(Flow1::PathNode node1, Flow2::PathNode node2) {
fwdReachableInterprocEntry(node1, node2) and

View File

@@ -117,16 +117,6 @@ private int countIndirections(Type t) {
else (
result = any(Indirection ind | ind.getType() = t).getNumberOfIndirections()
or
// If there is an indirection for the type, but we cannot count the number of indirections
// it means we couldn't reach a non-indirection type by stripping off indirections. This
// can occur if an iterator specifies itself as the value type. In this case we default to
// 1 indirection fore the type.
exists(Indirection ind |
ind.getType() = t and
not exists(ind.getNumberOfIndirections()) and
result = 1
)
or
not exists(Indirection ind | ind.getType() = t) and
result = 0
)
@@ -273,7 +263,7 @@ private module IteratorIndirections {
// Taint through `operator+=` and `operator-=` on iterators.
call.getStaticCallTarget() instanceof Iterator::IteratorAssignArithmeticOperator and
node2.(IndirectArgumentOutNode).getPreUpdateNode() = node1 and
node1.(IndirectOperand).hasOperandAndIndirectionIndex(call.getArgumentOperand(0), _) and
node1.(IndirectOperand).getOperand() = call.getArgumentOperand(0) and
node1.getType().getUnspecifiedType() = this
)
}
@@ -588,6 +578,7 @@ private module Cached {
)
}
pragma[assume_small_delta]
private predicate convertsIntoArgumentRev(Instruction instr) {
convertsIntoArgumentFwd(instr) and
(
@@ -805,7 +796,7 @@ private module Cached {
address.getDef() = instr and
isDereference(load, address) and
isUseImpl(address, _, indirectionIndex - 1) and
result = load
result = instr
)
}

View File

@@ -160,7 +160,7 @@ predicate modeledTaintStep(DataFlow::Node nodeIn, DataFlow::Node nodeOut) {
FunctionInput modelIn, FunctionOutput modelOut
|
indirectArgument = callInput(call, modelIn) and
indirectArgument.hasAddressOperandAndIndirectionIndex(nodeIn.asOperand(), _) and
indirectArgument.getAddressOperand() = nodeIn.asOperand() and
call.getStaticCallTarget() = func and
(
func.(DataFlowFunction).hasDataFlow(modelIn, modelOut)

View File

@@ -176,6 +176,7 @@ private predicate binaryValueNumber0(
)
}
pragma[assume_small_delta]
private predicate binaryValueNumber(
BinaryInstruction instr, IRFunction irFunc, Opcode opcode, TValueNumber leftOperand,
TValueNumber rightOperand
@@ -201,6 +202,7 @@ private predicate pointerArithmeticValueNumber0(
)
}
pragma[assume_small_delta]
private predicate pointerArithmeticValueNumber(
PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, int elementSize,
TValueNumber leftOperand, TValueNumber rightOperand
@@ -247,6 +249,7 @@ private predicate loadTotalOverlapValueNumber0(
)
}
pragma[assume_small_delta]
private predicate loadTotalOverlapValueNumber(
LoadTotalOverlapInstruction instr, IRFunction irFunc, IRType type, TValueNumber memOperand,
TValueNumber operand

View File

@@ -176,6 +176,7 @@ private predicate binaryValueNumber0(
)
}
pragma[assume_small_delta]
private predicate binaryValueNumber(
BinaryInstruction instr, IRFunction irFunc, Opcode opcode, TValueNumber leftOperand,
TValueNumber rightOperand
@@ -201,6 +202,7 @@ private predicate pointerArithmeticValueNumber0(
)
}
pragma[assume_small_delta]
private predicate pointerArithmeticValueNumber(
PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, int elementSize,
TValueNumber leftOperand, TValueNumber rightOperand
@@ -247,6 +249,7 @@ private predicate loadTotalOverlapValueNumber0(
)
}
pragma[assume_small_delta]
private predicate loadTotalOverlapValueNumber(
LoadTotalOverlapInstruction instr, IRFunction irFunc, IRType type, TValueNumber memOperand,
TValueNumber operand

View File

@@ -176,6 +176,7 @@ private predicate binaryValueNumber0(
)
}
pragma[assume_small_delta]
private predicate binaryValueNumber(
BinaryInstruction instr, IRFunction irFunc, Opcode opcode, TValueNumber leftOperand,
TValueNumber rightOperand
@@ -201,6 +202,7 @@ private predicate pointerArithmeticValueNumber0(
)
}
pragma[assume_small_delta]
private predicate pointerArithmeticValueNumber(
PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, int elementSize,
TValueNumber leftOperand, TValueNumber rightOperand
@@ -247,6 +249,7 @@ private predicate loadTotalOverlapValueNumber0(
)
}
pragma[assume_small_delta]
private predicate loadTotalOverlapValueNumber(
LoadTotalOverlapInstruction instr, IRFunction irFunc, IRType type, TValueNumber memOperand,
TValueNumber operand

View File

@@ -108,7 +108,7 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, Sid
// these may do only a partial copy of the input buffer to the output
// buffer
exists(this.getParamSize()) and
input.isParameterDeref(this.getParamSrc()) and
input.isParameter(this.getParamSrc()) and
(
output.isParameterDeref(this.getParamDest()) or
output.isReturnValueDeref()

View File

@@ -70,27 +70,6 @@ predicate semBackEdge(SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionP
// Conservatively assume that every edge is a back edge if we don't have dominance information.
(
phi.getBasicBlock().bbDominates(edge.getOrigBlock()) or
irreducibleSccEdge(edge.getOrigBlock(), phi.getBasicBlock()) or
not edge.getOrigBlock().hasDominanceInformation()
)
}
/**
* Holds if the edge from b1 to b2 is part of a multiple-entry cycle in an irreducible control flow
* graph.
*
* An ireducible control flow graph is one where the usual dominance-based back edge detection does
* not work, because there is a cycle with multiple entry points, meaning there are
* mutually-reachable basic blocks where neither dominates the other. For such a graph, we first
* remove all detectable back-edges using the normal condition that the predecessor block is
* dominated by the successor block, then mark all edges in a cycle in the resulting graph as back
* edges.
*/
private predicate irreducibleSccEdge(SemBasicBlock b1, SemBasicBlock b2) {
trimmedEdge(b1, b2) and trimmedEdge+(b2, b1)
}
private predicate trimmedEdge(SemBasicBlock pred, SemBasicBlock succ) {
pred.getASuccessor() = succ and
not succ.bbDominates(pred)
}

View File

@@ -877,6 +877,7 @@ module RangeStage<
)
}
pragma[assume_small_delta]
pragma[nomagic]
private predicate boundedPhiRankStep(
SemSsaPhiNode phi, SemBound b, D::Delta delta, boolean upper, boolean fromBackEdge,

View File

@@ -1,19 +1,3 @@
## 0.7.0
### Minor Analysis Improvements
* The `cpp/comparison-with-wider-type` query now correctly handles relational operations on signed operators. As a result the query may find more results.
## 0.6.4
No user-facing changes.
## 0.6.3
### New Queries
* Added a new query, `cpp/overrun-write`, to detect buffer overflows in C-style functions that manipulate buffers.
## 0.6.2
No user-facing changes.

View File

@@ -135,24 +135,18 @@ module ParameterSinks {
}
}
module IsUse {
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplCommon
predicate isUse(DataFlow::Node n, Expr e) {
isUse0(n, e)
or
exists(CallInstruction call, InitializeParameterInstruction init |
n.asOperand().getDef().getUnconvertedResultExpression() = e and
pragma[only_bind_into](init) = ParameterSinks::getAnAlwaysDereferencedParameter() and
viableParamArg(call, DataFlow::instructionNode(init), n) and
pragma[only_bind_out](init.getEnclosingFunction()) =
pragma[only_bind_out](call.getStaticCallTarget())
)
}
predicate isUse(DataFlow::Node n, Expr e) {
isUse0(n, e)
or
exists(CallInstruction call, int i, InitializeParameterInstruction init |
n.asOperand().getDef().getUnconvertedResultExpression() = e and
init = ParameterSinks::getAnAlwaysDereferencedParameter() and
call.getArgumentOperand(i) = n.asOperand() and
init.hasIndex(i) and
init.getEnclosingFunction() = call.getStaticCallTarget()
)
}
import IsUse
/**
* `dealloc1` is a deallocation expression, `e` is an expression that dereferences a
* pointer, and the `(dealloc1, e)` pair should be excluded by the `FlowFromFree` library.

View File

@@ -233,8 +233,7 @@ module StringSizeConfig implements ProductFlow::StateConfigSig {
// 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`.
exists(state1) and
hasSize(bufSource.asConvertedExpr(), sizeSource, state2) and
validState(sizeSource, state2)
hasSize(bufSource.asConvertedExpr(), sizeSource, state2)
}
predicate isSinkPair(
@@ -248,10 +247,20 @@ module StringSizeConfig implements ProductFlow::StateConfigSig {
)
}
predicate isBarrier1(DataFlow::Node node, FlowState1 state) { none() }
predicate isBarrier2(DataFlow::Node node, FlowState2 state) { none() }
predicate isBarrierOut2(DataFlow::Node node) {
node = any(DataFlow::SsaPhiNode phi).getAnInput(true)
}
predicate isAdditionalFlowStep1(
DataFlow::Node node1, FlowState1 state1, DataFlow::Node node2, FlowState1 state2
) {
none()
}
predicate isAdditionalFlowStep2(
DataFlow::Node node1, FlowState2 state1, DataFlow::Node node2, FlowState2 state2
) {

View File

@@ -45,20 +45,13 @@ Element friendlyLoc(Expr e) {
not e instanceof Access and not e instanceof Call and result = e
}
int getComparisonSizeAdjustment(Expr e) {
if e.getType().(IntegralType).isSigned() then result = 1 else result = 0
}
from Loop l, RelationalOperation rel, VariableAccess small, Expr large
where
small = rel.getLesserOperand() and
large = rel.getGreaterOperand() and
rel = l.getCondition().getAChild*() and
forall(Expr conv | conv = large.getConversion*() |
// We adjust the comparison size in the case of a signed integer type.
// This is to exclude the sign bit from the comparison that determines if the small type's size is sufficient to hold
// the value of the larger type determined with range analysis.
upperBound(conv).log2() > (getComparisonSize(small) * 8 - getComparisonSizeAdjustment(small))
upperBound(conv).log2() > getComparisonSize(small) * 8
) and
// Ignore cases where the smaller type is int or larger
// These are still bugs, but you should need a very large string or array to

View File

@@ -1,5 +1,4 @@
## 0.6.3
### New Queries
---
category: newQuery
---
* Added a new query, `cpp/overrun-write`, to detect buffer overflows in C-style functions that manipulate buffers.

View File

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

View File

@@ -1,5 +0,0 @@
## 0.7.0
### Minor Analysis Improvements
* The `cpp/comparison-with-wider-type` query now correctly handles relational operations on signed operators. As a result the query may find more results.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.7.0
lastReleaseVersion: 0.6.2

View File

@@ -14,7 +14,7 @@ import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysi
import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExprSpecific
import semmle.code.cpp.ir.IR
import semmle.code.cpp.ir.dataflow.DataFlow
import ArrayAddressToDerefFlow::PathGraph
import FieldAddressToDerefFlow::PathGraph
pragma[nomagic]
Instruction getABoundIn(SemBound b, IRFunction func) {
@@ -78,45 +78,28 @@ predicate isInvalidPointerDerefSink2(DataFlow::Node sink, Instruction i, string
)
}
predicate arrayTypeCand(ArrayType arrayType) {
any(Variable v).getUnspecifiedType() = arrayType and
exists(arrayType.getByteSize())
}
bindingset[baseTypeSize]
pragma[inline_late]
predicate arrayTypeHasSizes(ArrayType arr, int baseTypeSize, int size) {
arrayTypeCand(arr) and
arr.getByteSize() / baseTypeSize = size
}
bindingset[pai]
pragma[inline_late]
predicate constantUpperBounded(PointerArithmeticInstruction pai, int delta) {
semBounded(getSemanticExpr(pai.getRight()), any(SemZeroBound b), delta, true, _)
}
bindingset[pai, size]
predicate pointerArithOverflow0Impl(PointerArithmeticInstruction pai, int size, int delta) {
exists(int bound |
constantUpperBounded(pai, bound) and
delta = bound - size and
delta >= 0 and
size != 0 and
size != 1
)
}
pragma[nomagic]
predicate pointerArithOverflow0(PointerArithmeticInstruction pai, int delta) {
exists(int size |
arrayTypeHasSizes(_, pai.getElementSize(), size) and
pointerArithOverflow0Impl(pai, size, delta)
)
predicate arrayTypeHasSizes(ArrayType arr, int baseTypeSize, int arraySize) {
arr.getBaseType().getSize() = baseTypeSize and
arr.getArraySize() = arraySize
}
predicate pointerArithOverflow0(
PointerArithmeticInstruction pai, Field f, int size, int bound, int delta
) {
not f.getNamespace() instanceof StdNamespace and
arrayTypeHasSizes(f.getUnspecifiedType(), pai.getElementSize(), size) and
semBounded(getSemanticExpr(pai.getRight()), any(SemZeroBound b), bound, true, _) and
delta = bound - size and
delta >= 0 and
size != 0 and
size != 1
}
module PointerArithmeticToDerefConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { pointerArithOverflow0(source.asInstruction(), _) }
predicate isSource(DataFlow::Node source) {
pointerArithOverflow0(source.asInstruction(), _, _, _, _)
}
predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
@@ -127,38 +110,25 @@ module PointerArithmeticToDerefConfig implements DataFlow::ConfigSig {
module PointerArithmeticToDerefFlow = DataFlow::Global<PointerArithmeticToDerefConfig>;
predicate pointerArithOverflow(PointerArithmeticInstruction pai, int delta) {
pointerArithOverflow0(pai, delta) and
predicate pointerArithOverflow(
PointerArithmeticInstruction pai, Field f, int size, int bound, int delta
) {
pointerArithOverflow0(pai, f, size, bound, delta) and
PointerArithmeticToDerefFlow::flow(DataFlow::instructionNode(pai), _)
}
bindingset[v]
predicate finalPointerArithOverflow(Variable v, PointerArithmeticInstruction pai, int delta) {
exists(int size |
arrayTypeHasSizes(pragma[only_bind_out](v.getUnspecifiedType()), pai.getElementSize(), size) and
pointerArithOverflow0Impl(pai, size, delta)
)
}
predicate isSourceImpl(DataFlow::Node source, Variable v) {
(
source.asInstruction().(FieldAddressInstruction).getField() = v
or
source.asInstruction().(VariableAddressInstruction).getAstVariable() = v
) and
arrayTypeCand(v.getUnspecifiedType())
}
module ArrayAddressToDerefConfig implements DataFlow::StateConfigSig {
module FieldAddressToDerefConfig implements DataFlow::StateConfigSig {
newtype FlowState =
additional TArray() or
additional TArray(Field f) { pointerArithOverflow(_, f, _, _, _) } or
additional TOverflowArithmetic(PointerArithmeticInstruction pai) {
pointerArithOverflow(pai, _)
pointerArithOverflow(pai, _, _, _, _)
}
predicate isSource(DataFlow::Node source, FlowState state) {
isSourceImpl(source, _) and
state = TArray()
exists(Field f |
source.asInstruction().(FieldAddressInstruction).getField() = f and
state = TArray(f)
)
}
predicate isSink(DataFlow::Node sink, FlowState state) {
@@ -177,27 +147,27 @@ module ArrayAddressToDerefConfig implements DataFlow::StateConfigSig {
predicate isAdditionalFlowStep(
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
) {
exists(PointerArithmeticInstruction pai |
state1 = TArray() and
exists(PointerArithmeticInstruction pai, Field f |
state1 = TArray(f) and
state2 = TOverflowArithmetic(pai) and
pai.getLeft() = node1.asInstruction() and
node2.asInstruction() = pai and
pointerArithOverflow(pai, _)
pointerArithOverflow(pai, f, _, _, _)
)
}
}
module ArrayAddressToDerefFlow = DataFlow::GlobalWithState<ArrayAddressToDerefConfig>;
module FieldAddressToDerefFlow = DataFlow::GlobalWithState<FieldAddressToDerefConfig>;
from
Variable v, ArrayAddressToDerefFlow::PathNode source, PointerArithmeticInstruction pai,
ArrayAddressToDerefFlow::PathNode sink, Instruction deref, string operation, int delta
Field f, FieldAddressToDerefFlow::PathNode source, PointerArithmeticInstruction pai,
FieldAddressToDerefFlow::PathNode sink, Instruction deref, string operation, int delta
where
ArrayAddressToDerefFlow::flowPath(pragma[only_bind_into](source), pragma[only_bind_into](sink)) and
FieldAddressToDerefFlow::flowPath(source, sink) and
isInvalidPointerDerefSink2(sink.getNode(), deref, operation) and
pragma[only_bind_out](sink.getState()) = ArrayAddressToDerefConfig::TOverflowArithmetic(pai) and
isSourceImpl(source.getNode(), v) and
finalPointerArithOverflow(v, pai, delta)
source.getState() = FieldAddressToDerefConfig::TArray(f) and
sink.getState() = FieldAddressToDerefConfig::TOverflowArithmetic(pai) and
pointerArithOverflow(pai, f, _, _, delta)
select pai, source, sink,
"This pointer arithmetic may have an off-by-" + (delta + 1) +
" error allowing it to overrun $@ at this $@.", v, v.getName(), deref, operation
" error allowing it to overrun $@ at this $@.", f, f.getName(), deref, operation

View File

@@ -19,8 +19,6 @@ import cpp
import semmle.code.cpp.ir.dataflow.internal.ProductFlow
import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysis
import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExprSpecific
import semmle.code.cpp.ir.ValueNumbering
import semmle.code.cpp.controlflow.IRGuards
import semmle.code.cpp.ir.IR
import codeql.util.Unit
@@ -69,86 +67,6 @@ predicate hasSize(HeuristicAllocationExpr alloc, DataFlow::Node n, int state) {
)
}
/**
* A module that encapsulates a barrier guard to remove false positives from flow like:
* ```cpp
* char *p = new char[size];
* // ...
* unsigned n = size;
* // ...
* if(n < size) {
* use(*p[n]);
* }
* ```
* In this case, the sink pair identified by the product flow library (without any additional barriers)
* would be `(p, n)` (where `n` is the `n` in `p[n]`), because there exists a pointer-arithmetic
* instruction `pai` such that:
* 1. The left-hand of `pai` flows from the allocation, and
* 2. The right-hand of `pai` is non-strictly upper bounded by `n` (where `n` is the `n` in `p[n]`)
* but because there's a strict comparison that compares `n` against the size of the allocation this
* snippet is fine.
*/
module Barrier2 {
private class FlowState2 = AllocToInvalidPointerConfig::FlowState2;
private module BarrierConfig2 implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
// The sources is the same as in the sources for the second
// projection in the `AllocToInvalidPointerConfig` module.
hasSize(_, source, _)
}
additional predicate isSink(
DataFlow::Node left, DataFlow::Node right, IRGuardCondition g, FlowState2 state,
boolean testIsTrue
) {
// The sink is any "large" side of a relational comparison.
g.comparesLt(left.asOperand(), right.asOperand(), state, true, testIsTrue)
}
predicate isSink(DataFlow::Node sink) { isSink(_, sink, _, _, _) }
}
private import DataFlow::Global<BarrierConfig2>
private FlowState2 getAFlowStateForNode(DataFlow::Node node) {
exists(DataFlow::Node source |
flow(source, node) and
hasSize(_, source, result)
)
}
private predicate operandGuardChecks(
IRGuardCondition g, Operand left, Operand right, FlowState2 state, boolean edge
) {
exists(DataFlow::Node nLeft, DataFlow::Node nRight, FlowState2 state0 |
nRight.asOperand() = right and
nLeft.asOperand() = left and
BarrierConfig2::isSink(nLeft, nRight, g, state0, edge) and
state = getAFlowStateForNode(nRight) and
state0 <= state
)
}
Instruction getABarrierInstruction(FlowState2 state) {
exists(IRGuardCondition g, ValueNumber value, Operand use, boolean edge |
use = value.getAUse() and
operandGuardChecks(pragma[only_bind_into](g), pragma[only_bind_into](use), _,
pragma[only_bind_into](state), pragma[only_bind_into](edge)) and
result = value.getAnInstruction() and
g.controls(result.getBlock(), edge)
)
}
DataFlow::Node getABarrierNode(FlowState2 state) {
result.asOperand() = getABarrierInstruction(state).getAUse()
}
IRBlock getABarrierBlock(FlowState2 state) {
result.getAnInstruction() = getABarrierInstruction(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`.
@@ -193,18 +111,33 @@ module AllocToInvalidPointerConfig implements ProductFlow::StateConfigSig {
exists(state1) and
// We check that the delta computed by the range analysis matches the
// state value that we set in `isSourcePair`.
isSinkImpl(_, sink1, sink2, state2)
exists(int delta |
isSinkImpl(_, sink1, sink2, delta) and
state2 = delta
)
}
predicate isBarrier2(DataFlow::Node node, FlowState2 state) {
node = Barrier2::getABarrierNode(state)
}
predicate isBarrier1(DataFlow::Node node, FlowState1 state) { none() }
predicate isBarrier2(DataFlow::Node node, FlowState2 state) { none() }
predicate isBarrierIn1(DataFlow::Node node) { isSourcePair(node, _, _, _) }
predicate isBarrierOut2(DataFlow::Node node) {
node = any(DataFlow::SsaPhiNode phi).getAnInput(true)
}
predicate isAdditionalFlowStep1(
DataFlow::Node node1, FlowState1 state1, DataFlow::Node node2, FlowState1 state2
) {
none()
}
predicate isAdditionalFlowStep2(
DataFlow::Node node1, FlowState2 state1, DataFlow::Node node2, FlowState2 state2
) {
none()
}
}
module AllocToInvalidPointerFlow = ProductFlow::GlobalWithState<AllocToInvalidPointerConfig>;
@@ -227,40 +160,13 @@ pragma[nomagic]
predicate pointerAddInstructionHasBounds(
PointerAddInstruction pai, DataFlow::Node sink1, DataFlow::Node sink2, int delta
) {
InterestingPointerAddInstruction::isInteresting(pragma[only_bind_into](pai)) and
exists(Instruction right, Instruction instr2 |
exists(Instruction right |
pai.getRight() = right and
pai.getLeft() = sink1.asInstruction() and
instr2 = sink2.asInstruction() and
bounded1(right, instr2, delta) and
not right = Barrier2::getABarrierInstruction(delta) and
not instr2 = Barrier2::getABarrierInstruction(delta)
bounded1(right, sink2.asInstruction(), delta)
)
}
module InterestingPointerAddInstruction {
private module PointerAddInstructionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
// The sources is the same as in the sources for the second
// projection in the `AllocToInvalidPointerConfig` module.
hasSize(source.asConvertedExpr(), _, _)
}
predicate isSink(DataFlow::Node sink) {
sink.asInstruction() = any(PointerAddInstruction pai).getLeft()
}
}
private import DataFlow::Global<PointerAddInstructionConfig>
predicate isInteresting(PointerAddInstruction pai) {
exists(DataFlow::Node n |
n.asInstruction() = pai.getLeft() and
flowTo(n)
)
}
}
/**
* Holds if `pai` is non-strictly upper bounded by `sink2 + delta` and `sink1` is the
* left operand of the pointer-arithmetic operation.
@@ -298,13 +204,11 @@ Instruction getASuccessor(Instruction instr) {
*/
pragma[inline]
predicate isInvalidPointerDerefSink(DataFlow::Node sink, Instruction i, string operation, int delta) {
exists(AddressOperand addr, Instruction s, IRBlock b |
exists(AddressOperand addr, Instruction s |
s = sink.asInstruction() and
boundedImpl(addr.getDef(), s, delta) and
bounded1(addr.getDef(), s, delta) and
delta >= 0 and
i.getAnOperand() = addr and
b = i.getBlock() and
not b = InvalidPointerToDerefBarrier::getABarrierBlock(delta)
i.getAnOperand() = addr
|
i instanceof StoreInstruction and
operation = "write"
@@ -314,60 +218,6 @@ predicate isInvalidPointerDerefSink(DataFlow::Node sink, Instruction i, string o
)
}
module InvalidPointerToDerefBarrier {
private module BarrierConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
// The sources is the same as in the sources for `InvalidPointerToDerefConfig`.
invalidPointerToDerefSource(_, source, _)
}
additional predicate isSink(
DataFlow::Node left, DataFlow::Node right, IRGuardCondition g, int state, boolean testIsTrue
) {
// The sink is any "large" side of a relational comparison.
g.comparesLt(left.asOperand(), right.asOperand(), state, true, testIsTrue)
}
predicate isSink(DataFlow::Node sink) { isSink(_, sink, _, _, _) }
}
private import DataFlow::Global<BarrierConfig>
private int getInvalidPointerToDerefSourceDelta(DataFlow::Node node) {
exists(DataFlow::Node source |
flow(source, node) and
invalidPointerToDerefSource(_, source, result)
)
}
private predicate operandGuardChecks(
IRGuardCondition g, Operand left, Operand right, int state, boolean edge
) {
exists(DataFlow::Node nLeft, DataFlow::Node nRight, int state0 |
nRight.asOperand() = right and
nLeft.asOperand() = left and
BarrierConfig::isSink(nLeft, nRight, g, state0, edge) and
state = getInvalidPointerToDerefSourceDelta(nRight) and
state0 <= state
)
}
Instruction getABarrierInstruction(int state) {
exists(IRGuardCondition g, ValueNumber value, Operand use, boolean edge |
use = value.getAUse() and
operandGuardChecks(pragma[only_bind_into](g), pragma[only_bind_into](use), _, state,
pragma[only_bind_into](edge)) and
result = value.getAnInstruction() and
g.controls(result.getBlock(), edge)
)
}
DataFlow::Node getABarrierNode() { result.asOperand() = getABarrierInstruction(_).getAUse() }
pragma[nomagic]
IRBlock getABarrierBlock(int state) { result.getAnInstruction() = getABarrierInstruction(state) }
}
/**
* A configuration to track flow from a pointer-arithmetic operation found
* by `AllocToInvalidPointerConfig` to a dereference of the pointer.
@@ -380,8 +230,6 @@ module InvalidPointerToDerefConfig implements DataFlow::ConfigSig {
predicate isBarrier(DataFlow::Node node) {
node = any(DataFlow::SsaPhiNode phi | not phi.isPhiRead()).getAnInput(true)
or
node = InvalidPointerToDerefBarrier::getABarrierNode()
}
}
@@ -398,21 +246,12 @@ module InvalidPointerToDerefFlow = DataFlow::Global<InvalidPointerToDerefConfig>
predicate invalidPointerToDerefSource(
PointerArithmeticInstruction pai, DataFlow::Node source, int delta
) {
exists(
AllocToInvalidPointerFlow::PathNode1 p1, AllocToInvalidPointerFlow::PathNode2 p2,
DataFlow::Node sink1, DataFlow::Node sink2, int delta0
|
pragma[only_bind_out](p1.getNode()) = sink1 and
pragma[only_bind_out](p2.getNode()) = sink2 and
AllocToInvalidPointerFlow::flowPath(_, _, pragma[only_bind_into](p1), pragma[only_bind_into](p2)) and
// Note that `delta` is not necessarily equal to `delta0`:
// `delta0` is the constant offset added to the size of the allocation, and
// delta is the constant difference between the pointer-arithmetic instruction
// and the instruction computing the address for which we will search for a dereference.
isSinkImpl(pai, sink1, sink2, delta0) and
exists(AllocToInvalidPointerFlow::PathNode1 p, DataFlow::Node sink1 |
pragma[only_bind_out](p.getNode()) = sink1 and
AllocToInvalidPointerFlow::flowPath(_, _, pragma[only_bind_into](p), _) and
isSinkImpl(pai, sink1, _, _) and
bounded2(source.asInstruction(), pai, delta) and
delta >= 0 and
not source.getBasicBlock() = Barrier2::getABarrierBlock(delta0)
delta >= 0
)
}
@@ -426,7 +265,7 @@ newtype TMergedPathNode =
// pointer, but we want to raise an alert at the dereference.
TPathNodeSink(Instruction i) {
exists(DataFlow::Node n |
InvalidPointerToDerefFlow::flowTo(pragma[only_bind_into](n)) and
InvalidPointerToDerefFlow::flowTo(n) and
isInvalidPointerDerefSink(n, i, _, _) and
i = getASuccessor(n.asInstruction())
)

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 0.7.1-dev
version: 0.6.3-dev
groups:
- cpp
- queries

View File

@@ -4,9 +4,8 @@ edges
| test.cpp:19:9:19:16 | mk_array indirection [p] | test.cpp:28:19:28:26 | call to mk_array [p] |
| test.cpp:19:9:19:16 | mk_array indirection [p] | test.cpp:50:18:50:25 | call to mk_array [p] |
| test.cpp:21:5:21:24 | ... = ... | test.cpp:21:9:21:9 | arr indirection [post update] [p] |
| test.cpp:21:9:21:9 | arr indirection [post update] [p] | test.cpp:22:5:22:7 | arr indirection [p] |
| test.cpp:21:9:21:9 | arr indirection [post update] [p] | test.cpp:19:9:19:16 | mk_array indirection [p] |
| test.cpp:21:13:21:18 | call to malloc | test.cpp:21:5:21:24 | ... = ... |
| test.cpp:22:5:22:7 | arr indirection [p] | test.cpp:19:9:19:16 | mk_array indirection [p] |
| test.cpp:28:19:28:26 | call to mk_array [p] | test.cpp:31:9:31:11 | arr indirection [p] |
| test.cpp:28:19:28:26 | call to mk_array [p] | test.cpp:35:9:35:11 | arr indirection [p] |
| test.cpp:31:9:31:11 | arr indirection [p] | test.cpp:31:13:31:13 | p indirection |
@@ -21,10 +20,9 @@ edges
| test.cpp:45:13:45:13 | p indirection | test.cpp:45:13:45:13 | p |
| test.cpp:50:18:50:25 | call to mk_array [p] | test.cpp:39:27:39:29 | arr [p] |
| test.cpp:55:5:55:24 | ... = ... | test.cpp:55:9:55:9 | arr indirection [post update] [p] |
| test.cpp:55:9:55:9 | arr indirection [post update] [p] | test.cpp:56:5:56:7 | arr indirection [p] |
| test.cpp:55:9:55:9 | arr indirection [post update] [p] | test.cpp:59:9:59:11 | arr indirection [p] |
| test.cpp:55:9:55:9 | arr indirection [post update] [p] | test.cpp:63:9:63:11 | arr indirection [p] |
| test.cpp:55:13:55:18 | call to malloc | test.cpp:55:5:55:24 | ... = ... |
| test.cpp:56:5:56:7 | arr indirection [p] | test.cpp:59:9:59:11 | arr indirection [p] |
| test.cpp:56:5:56:7 | arr indirection [p] | test.cpp:63:9:63:11 | arr indirection [p] |
| test.cpp:59:9:59:11 | arr indirection [p] | test.cpp:59:13:59:13 | p indirection |
| test.cpp:59:13:59:13 | p indirection | test.cpp:59:13:59:13 | p |
| test.cpp:63:9:63:11 | arr indirection [p] | test.cpp:63:13:63:13 | p indirection |
@@ -32,9 +30,8 @@ edges
| test.cpp:67:10:67:19 | mk_array_p indirection [p] | test.cpp:76:20:76:29 | call to mk_array_p indirection [p] |
| test.cpp:67:10:67:19 | mk_array_p indirection [p] | test.cpp:98:18:98:27 | call to mk_array_p indirection [p] |
| test.cpp:69:5:69:25 | ... = ... | test.cpp:69:10:69:10 | arr indirection [post update] [p] |
| test.cpp:69:10:69:10 | arr indirection [post update] [p] | test.cpp:70:5:70:7 | arr indirection [p] |
| test.cpp:69:10:69:10 | arr indirection [post update] [p] | test.cpp:67:10:67:19 | mk_array_p indirection [p] |
| test.cpp:69:14:69:19 | call to malloc | test.cpp:69:5:69:25 | ... = ... |
| test.cpp:70:5:70:7 | arr indirection [p] | test.cpp:67:10:67:19 | mk_array_p indirection [p] |
| test.cpp:76:20:76:29 | call to mk_array_p indirection [p] | test.cpp:79:9:79:11 | arr indirection [p] |
| test.cpp:76:20:76:29 | call to mk_array_p indirection [p] | test.cpp:83:9:83:11 | arr indirection [p] |
| test.cpp:79:9:79:11 | arr indirection [p] | test.cpp:79:14:79:14 | p indirection |
@@ -56,7 +53,6 @@ nodes
| test.cpp:21:5:21:24 | ... = ... | semmle.label | ... = ... |
| test.cpp:21:9:21:9 | arr indirection [post update] [p] | semmle.label | arr indirection [post update] [p] |
| test.cpp:21:13:21:18 | call to malloc | semmle.label | call to malloc |
| test.cpp:22:5:22:7 | arr indirection [p] | semmle.label | arr indirection [p] |
| test.cpp:28:19:28:26 | call to mk_array [p] | semmle.label | call to mk_array [p] |
| test.cpp:31:9:31:11 | arr indirection [p] | semmle.label | arr indirection [p] |
| test.cpp:31:13:31:13 | p | semmle.label | p |
@@ -75,7 +71,6 @@ nodes
| test.cpp:55:5:55:24 | ... = ... | semmle.label | ... = ... |
| test.cpp:55:9:55:9 | arr indirection [post update] [p] | semmle.label | arr indirection [post update] [p] |
| test.cpp:55:13:55:18 | call to malloc | semmle.label | call to malloc |
| test.cpp:56:5:56:7 | arr indirection [p] | semmle.label | arr indirection [p] |
| test.cpp:59:9:59:11 | arr indirection [p] | semmle.label | arr indirection [p] |
| test.cpp:59:13:59:13 | p | semmle.label | p |
| test.cpp:59:13:59:13 | p indirection | semmle.label | p indirection |
@@ -86,7 +81,6 @@ nodes
| test.cpp:69:5:69:25 | ... = ... | semmle.label | ... = ... |
| test.cpp:69:10:69:10 | arr indirection [post update] [p] | semmle.label | arr indirection [post update] [p] |
| test.cpp:69:14:69:19 | call to malloc | semmle.label | call to malloc |
| test.cpp:70:5:70:7 | arr indirection [p] | semmle.label | arr indirection [p] |
| test.cpp:76:20:76:29 | call to mk_array_p indirection [p] | semmle.label | call to mk_array_p indirection [p] |
| test.cpp:79:9:79:11 | arr indirection [p] | semmle.label | arr indirection [p] |
| test.cpp:79:14:79:14 | p | semmle.label | p |

View File

@@ -1,136 +1,38 @@
edges
| test.cpp:34:10:34:12 | buf | test.cpp:34:5:34:24 | access to array |
| test.cpp:35:10:35:12 | buf | test.cpp:35:5:35:22 | access to array |
| test.cpp:36:10:36:12 | buf | test.cpp:36:5:36:24 | access to array |
| test.cpp:39:14:39:16 | buf | test.cpp:39:9:39:19 | access to array |
| test.cpp:43:14:43:16 | buf | test.cpp:43:9:43:19 | access to array |
| test.cpp:48:10:48:12 | buf | test.cpp:48:5:48:24 | access to array |
| test.cpp:49:10:49:12 | buf | test.cpp:49:5:49:22 | access to array |
| test.cpp:50:10:50:12 | buf | test.cpp:50:5:50:24 | access to array |
| test.cpp:53:14:53:16 | buf | test.cpp:53:9:53:19 | access to array |
| test.cpp:57:14:57:16 | buf | test.cpp:57:9:57:19 | access to array |
| test.cpp:61:14:61:16 | buf | test.cpp:61:9:61:19 | access to array |
| test.cpp:70:33:70:33 | p | test.cpp:71:5:71:17 | access to array |
| test.cpp:70:33:70:33 | p | test.cpp:72:5:72:15 | access to array |
| test.cpp:76:26:76:46 | & ... | test.cpp:66:32:66:32 | p |
| test.cpp:76:32:76:34 | buf | test.cpp:76:26:76:46 | & ... |
| test.cpp:77:26:77:44 | & ... | test.cpp:66:32:66:32 | p |
| test.cpp:77:32:77:34 | buf | test.cpp:77:26:77:44 | & ... |
| test.cpp:79:27:79:34 | buf | test.cpp:70:33:70:33 | p |
| test.cpp:79:32:79:34 | buf | test.cpp:79:27:79:34 | buf |
| test.cpp:85:34:85:36 | buf | test.cpp:87:5:87:31 | access to array |
| test.cpp:85:34:85:36 | buf | test.cpp:88:5:88:27 | access to array |
| test.cpp:96:13:96:15 | arr | test.cpp:96:13:96:18 | access to array |
| test.cpp:111:17:111:19 | arr | test.cpp:111:17:111:22 | access to array |
| test.cpp:111:17:111:19 | arr | test.cpp:115:35:115:40 | access to array |
| test.cpp:111:17:111:19 | arr | test.cpp:119:17:119:22 | access to array |
| test.cpp:115:35:115:37 | arr | test.cpp:111:17:111:22 | access to array |
| test.cpp:115:35:115:37 | arr | test.cpp:115:35:115:40 | access to array |
| test.cpp:115:35:115:37 | arr | test.cpp:119:17:119:22 | access to array |
| test.cpp:119:17:119:19 | arr | test.cpp:111:17:111:22 | access to array |
| test.cpp:119:17:119:19 | arr | test.cpp:115:35:115:40 | access to array |
| test.cpp:119:17:119:19 | arr | test.cpp:119:17:119:22 | access to array |
| test.cpp:128:9:128:11 | arr | test.cpp:128:9:128:14 | access to array |
| test.cpp:134:25:134:27 | arr | test.cpp:136:9:136:16 | ... += ... |
| test.cpp:136:9:136:16 | ... += ... | test.cpp:138:13:138:15 | arr |
| test.cpp:143:18:143:21 | asdf | test.cpp:134:25:134:27 | arr |
| test.cpp:143:18:143:21 | asdf | test.cpp:143:18:143:21 | asdf |
| test.cpp:146:26:146:26 | p indirection | test.cpp:148:6:148:9 | * ... |
| test.cpp:156:12:156:14 | buf | test.cpp:156:12:156:18 | ... + ... |
| test.cpp:156:12:156:18 | ... + ... | test.cpp:158:17:158:18 | & ... indirection |
| test.cpp:158:17:158:18 | & ... indirection | test.cpp:146:26:146:26 | p indirection |
| test.cpp:218:23:218:28 | buffer | test.cpp:220:5:220:11 | access to array |
| test.cpp:218:23:218:28 | buffer | test.cpp:221:5:221:11 | access to array |
| test.cpp:229:25:229:29 | array | test.cpp:231:5:231:10 | access to array |
| test.cpp:229:25:229:29 | array | test.cpp:232:5:232:10 | access to array |
| test.cpp:245:30:245:30 | p | test.cpp:261:27:261:30 | access to array |
| test.cpp:245:30:245:30 | p | test.cpp:261:27:261:30 | access to array |
| test.cpp:274:14:274:20 | buffer3 | test.cpp:245:30:245:30 | p |
| test.cpp:274:14:274:20 | buffer3 | test.cpp:274:14:274:20 | buffer3 |
| test.cpp:277:35:277:35 | p | test.cpp:278:14:278:14 | p |
| test.cpp:278:14:278:14 | p | test.cpp:245:30:245:30 | p |
| test.cpp:283:19:283:25 | buffer1 | test.cpp:277:35:277:35 | p |
| test.cpp:283:19:283:25 | buffer1 | test.cpp:283:19:283:25 | buffer1 |
| test.cpp:286:19:286:25 | buffer2 | test.cpp:277:35:277:35 | p |
| test.cpp:286:19:286:25 | buffer2 | test.cpp:286:19:286:25 | buffer2 |
| test.cpp:289:19:289:25 | buffer3 | test.cpp:277:35:277:35 | p |
| test.cpp:289:19:289:25 | buffer3 | test.cpp:289:19:289:25 | buffer3 |
nodes
| test.cpp:34:5:34:24 | access to array | semmle.label | access to array |
| test.cpp:34:10:34:12 | buf | semmle.label | buf |
| test.cpp:35:5:35:22 | access to array | semmle.label | access to array |
| test.cpp:35:10:35:12 | buf | semmle.label | buf |
| test.cpp:36:5:36:24 | access to array | semmle.label | access to array |
| test.cpp:36:10:36:12 | buf | semmle.label | buf |
| test.cpp:39:9:39:19 | access to array | semmle.label | access to array |
| test.cpp:39:14:39:16 | buf | semmle.label | buf |
| test.cpp:43:9:43:19 | access to array | semmle.label | access to array |
| test.cpp:43:14:43:16 | buf | semmle.label | buf |
| test.cpp:48:5:48:24 | access to array | semmle.label | access to array |
| test.cpp:48:10:48:12 | buf | semmle.label | buf |
| test.cpp:49:5:49:22 | access to array | semmle.label | access to array |
| test.cpp:49:10:49:12 | buf | semmle.label | buf |
| test.cpp:50:5:50:24 | access to array | semmle.label | access to array |
| test.cpp:50:10:50:12 | buf | semmle.label | buf |
| test.cpp:53:9:53:19 | access to array | semmle.label | access to array |
| test.cpp:53:14:53:16 | buf | semmle.label | buf |
| test.cpp:57:9:57:19 | access to array | semmle.label | access to array |
| test.cpp:57:14:57:16 | buf | semmle.label | buf |
| test.cpp:61:9:61:19 | access to array | semmle.label | access to array |
| test.cpp:61:14:61:16 | buf | semmle.label | buf |
| test.cpp:66:32:66:32 | p | semmle.label | p |
| test.cpp:66:32:66:32 | p | semmle.label | p |
| test.cpp:70:33:70:33 | p | semmle.label | p |
| test.cpp:71:5:71:17 | access to array | semmle.label | access to array |
| test.cpp:72:5:72:15 | access to array | semmle.label | access to array |
| test.cpp:76:26:76:46 | & ... | semmle.label | & ... |
| test.cpp:76:32:76:34 | buf | semmle.label | buf |
| test.cpp:77:26:77:44 | & ... | semmle.label | & ... |
| test.cpp:77:32:77:34 | buf | semmle.label | buf |
| test.cpp:79:27:79:34 | buf | semmle.label | buf |
| test.cpp:79:32:79:34 | buf | semmle.label | buf |
| test.cpp:85:34:85:36 | buf | semmle.label | buf |
| test.cpp:87:5:87:31 | access to array | semmle.label | access to array |
| test.cpp:88:5:88:27 | access to array | semmle.label | access to array |
| test.cpp:96:13:96:15 | arr | semmle.label | arr |
| test.cpp:96:13:96:18 | access to array | semmle.label | access to array |
| test.cpp:111:17:111:19 | arr | semmle.label | arr |
| test.cpp:111:17:111:22 | access to array | semmle.label | access to array |
| test.cpp:115:35:115:37 | arr | semmle.label | arr |
| test.cpp:115:35:115:40 | access to array | semmle.label | access to array |
| test.cpp:119:17:119:19 | arr | semmle.label | arr |
| test.cpp:119:17:119:22 | access to array | semmle.label | access to array |
| test.cpp:128:9:128:11 | arr | semmle.label | arr |
| test.cpp:128:9:128:14 | access to array | semmle.label | access to array |
| test.cpp:134:25:134:27 | arr | semmle.label | arr |
| test.cpp:136:9:136:16 | ... += ... | semmle.label | ... += ... |
| test.cpp:138:13:138:15 | arr | semmle.label | arr |
| test.cpp:143:18:143:21 | asdf | semmle.label | asdf |
| test.cpp:143:18:143:21 | asdf | semmle.label | asdf |
| test.cpp:146:26:146:26 | p indirection | semmle.label | p indirection |
| test.cpp:148:6:148:9 | * ... | semmle.label | * ... |
| test.cpp:156:12:156:14 | buf | semmle.label | buf |
| test.cpp:156:12:156:18 | ... + ... | semmle.label | ... + ... |
| test.cpp:158:17:158:18 | & ... indirection | semmle.label | & ... indirection |
| test.cpp:218:23:218:28 | buffer | semmle.label | buffer |
| test.cpp:220:5:220:11 | access to array | semmle.label | access to array |
| test.cpp:221:5:221:11 | access to array | semmle.label | access to array |
| test.cpp:229:25:229:29 | array | semmle.label | array |
| test.cpp:231:5:231:10 | access to array | semmle.label | access to array |
| test.cpp:232:5:232:10 | access to array | semmle.label | access to array |
| test.cpp:245:30:245:30 | p | semmle.label | p |
| test.cpp:245:30:245:30 | p | semmle.label | p |
| test.cpp:261:27:261:30 | access to array | semmle.label | access to array |
| test.cpp:274:14:274:20 | buffer3 | semmle.label | buffer3 |
| test.cpp:274:14:274:20 | buffer3 | semmle.label | buffer3 |
| test.cpp:277:35:277:35 | p | semmle.label | p |
| test.cpp:278:14:278:14 | p | semmle.label | p |
| test.cpp:283:19:283:25 | buffer1 | semmle.label | buffer1 |
| test.cpp:283:19:283:25 | buffer1 | semmle.label | buffer1 |
| test.cpp:286:19:286:25 | buffer2 | semmle.label | buffer2 |
| test.cpp:286:19:286:25 | buffer2 | semmle.label | buffer2 |
| test.cpp:289:19:289:25 | buffer3 | semmle.label | buffer3 |
| test.cpp:289:19:289:25 | buffer3 | semmle.label | buffer3 |
subpaths
#select
| test.cpp:35:5:35:22 | PointerAdd: access to array | test.cpp:35:10:35:12 | buf | test.cpp:35:5:35:22 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:15:9:15:11 | buf | buf | test.cpp:35:5:35:26 | Store: ... = ... | write |
@@ -142,10 +44,3 @@ subpaths
| test.cpp:61:9:61:19 | PointerAdd: access to array | test.cpp:61:14:61:16 | buf | test.cpp:61:9:61:19 | access to array | This pointer arithmetic may have an off-by-2 error allowing it to overrun $@ at this $@. | test.cpp:19:9:19:11 | buf | buf | test.cpp:61:9:61:23 | Store: ... = ... | write |
| test.cpp:72:5:72:15 | PointerAdd: access to array | test.cpp:79:32:79:34 | buf | test.cpp:72:5:72:15 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:15:9:15:11 | buf | buf | test.cpp:72:5:72:19 | Store: ... = ... | write |
| test.cpp:77:27:77:44 | PointerAdd: access to array | test.cpp:77:32:77:34 | buf | test.cpp:66:32:66:32 | p | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:15:9:15:11 | buf | buf | test.cpp:67:5:67:10 | Store: ... = ... | write |
| test.cpp:88:5:88:27 | PointerAdd: access to array | test.cpp:85:34:85:36 | buf | test.cpp:88:5:88:27 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:15:9:15:11 | buf | buf | test.cpp:88:5:88:31 | Store: ... = ... | write |
| test.cpp:128:9:128:14 | PointerAdd: access to array | test.cpp:128:9:128:11 | arr | test.cpp:128:9:128:14 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:125:11:125:13 | arr | arr | test.cpp:128:9:128:18 | Store: ... = ... | write |
| test.cpp:136:9:136:16 | PointerAdd: ... += ... | test.cpp:143:18:143:21 | asdf | test.cpp:138:13:138:15 | arr | This pointer arithmetic may have an off-by-2 error allowing it to overrun $@ at this $@. | test.cpp:142:10:142:13 | asdf | asdf | test.cpp:138:12:138:15 | Load: * ... | read |
| test.cpp:156:12:156:18 | PointerAdd: ... + ... | test.cpp:156:12:156:14 | buf | test.cpp:148:6:148:9 | * ... | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:154:7:154:9 | buf | buf | test.cpp:147:3:147:13 | Store: ... = ... | write |
| test.cpp:221:5:221:11 | PointerAdd: access to array | test.cpp:218:23:218:28 | buffer | test.cpp:221:5:221:11 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:217:19:217:24 | buffer | buffer | test.cpp:221:5:221:15 | Store: ... = ... | write |
| test.cpp:232:5:232:10 | PointerAdd: access to array | test.cpp:229:25:229:29 | array | test.cpp:232:5:232:10 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:228:10:228:14 | array | array | test.cpp:232:5:232:19 | Store: ... = ... | write |
| test.cpp:261:27:261:30 | PointerAdd: access to array | test.cpp:286:19:286:25 | buffer2 | test.cpp:261:27:261:30 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:285:19:285:25 | buffer2 | buffer2 | test.cpp:261:27:261:30 | Load: access to array | read |

View File

@@ -85,7 +85,7 @@ void testCharIndex(BigArray *arr) {
char *charBuf = (char*) arr->buf;
charBuf[MAX_SIZE_BYTES - 1] = 0; // GOOD
charBuf[MAX_SIZE_BYTES] = 0; // BAD
charBuf[MAX_SIZE_BYTES] = 0; // BAD [FALSE NEGATIVE]
}
void testEqRefinement() {
@@ -120,171 +120,3 @@ void testEqRefinement2() {
}
}
}
void testStackAllocated() {
char *arr[MAX_SIZE];
for(int i = 0; i <= MAX_SIZE; i++) {
arr[i] = 0; // BAD
}
}
int strncmp(const char*, const char*, int);
char testStrncmp2(char *arr) {
if(strncmp(arr, "<test>", 6) == 0) {
arr += 6;
}
return *arr; // GOOD [FALSE POSITIVE]
}
void testStrncmp1() {
char asdf[5];
testStrncmp2(asdf);
}
void countdownBuf1(int **p) {
*--(*p) = 1; // GOOD [FALSE POSITIVE]
*--(*p) = 2; // GOOD
*--(*p) = 3; // GOOD
*--(*p) = 4; // GOOD
}
void countdownBuf2() {
int buf[4];
int *x = buf + 4;
countdownBuf1(&x);
}
int access(int *p) {
return p[0];
}
// unrolled loop style seen in crypto code.
int countdownLength1(int *p, int len) {
while(len > 0) {
access(p);
p[1] = 1;
p[2] = 2;
p[3] = 3;
p[4] = 4;
p[5] = 5;
p[6] = 6; // BAD [FALSE NEGATIVE]
p[7] = 7; // BAD [FALSE NEGATIVE]
p += 8;
len -= 8;
}
return p[5];
}
int callCountdownLength() {
int buf[6];
return countdownLength1(buf, 6);
}
int countdownLength2() {
int buf[6];
int len = 6;
int *p = buf;
if(len % 8) {
return -1;
}
while(len > 0) {
p[0] = 0;
p[1] = 1;
p[2] = 2;
p[3] = 3;
p[4] = 4;
p[5] = 5;
p[6] = 6; // GOOD
p[7] = 7; // GOOD
p += 8;
len -= 8;
}
return p[5];
}
void pointer_size_larger_than_array_element_size() {
unsigned char buffer[100]; // getByteSize() = 100
int *ptr = (int *)buffer; // pai.getElementSize() will be sizeof(int) = 4 -> size = 25
ptr[24] = 0; // GOOD: writes bytes 96, 97, 98, 99
ptr[25] = 0; // BAD: writes bytes 100, 101, 102, 103
}
struct vec2 { int x, y; };
struct vec3 { int x, y, z; };
void pointer_size_smaller_than_array_element_size_but_does_not_divide_it() {
vec3 array[3]; // getByteSize() = 9 * sizeof(int)
vec2 *ptr = (vec2 *)array; // pai.getElementSize() will be 2 * sizeof(int) -> size = 4
ptr[3] = vec2{}; // GOOD: writes ints 6, 7
ptr[4] = vec2{}; // BAD: writes ints 8, 9
}
void pointer_size_larger_than_array_element_size_and_does_not_divide_it() {
vec2 array[2]; // getByteSize() = 4 * sizeof(int) = 4 * 4 = 16
vec3 *ptr = (vec3 *)array; // pai.getElementSize() will be 3 * sizeof(int) -> size = 1
ptr[0] = vec3{}; // GOOD: writes ints 0, 1, 2
ptr[1] = vec3{}; // BAD: writes ints 3, 4, 5 [NOT DETECTED]
}
void use(...);
void call_use(unsigned char* p, int n) {
if(n == 0) {
return;
}
if(n == 1) {
unsigned char x = p[0];
use(x);
}
if(n == 2) {
unsigned char x = p[0];
unsigned char y = p[1];
use(x, y);
}
if(n == 3) {
unsigned char x = p[0];
unsigned char y = p[1];
unsigned char z = p[2]; // GOOD [FALSE POSITIVE]: `call_use(buffer2, 2)` won't reach this point.
use(x, y, z);
}
}
void test_call_use() {
unsigned char buffer1[1];
call_use(buffer1,1);
unsigned char buffer2[2];
call_use(buffer2,2);
unsigned char buffer3[3];
call_use(buffer3,3);
}
void call_call_use(unsigned char* p, int n) {
call_use(p, n);
}
void test_call_use2() {
unsigned char buffer1[1];
call_call_use(buffer1,1);
unsigned char buffer2[2];
call_call_use(buffer2,2);
unsigned char buffer3[3];
call_call_use(buffer3,3);
}

View File

@@ -380,10 +380,9 @@ edges
| test.cpp:80:9:80:16 | mk_array indirection [end] | test.cpp:89:19:89:26 | call to mk_array [end] |
| test.cpp:80:9:80:16 | mk_array indirection [end] | test.cpp:119:18:119:25 | call to mk_array [end] |
| test.cpp:82:5:82:28 | ... = ... | test.cpp:82:9:82:13 | arr indirection [post update] [begin] |
| test.cpp:82:9:82:13 | arr indirection [post update] [begin] | test.cpp:83:5:83:7 | arr indirection [begin] |
| test.cpp:82:9:82:13 | arr indirection [post update] [begin] | test.cpp:80:9:80:16 | mk_array 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 | ... = ... |
| test.cpp:83:5:83:7 | arr indirection [begin] | test.cpp:80:9:80:16 | mk_array indirection [begin] |
| test.cpp:83:5:83:30 | ... = ... | 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 | mk_array indirection [end] |
| test.cpp:83:15:83:17 | arr indirection [begin] | test.cpp:83:19:83:23 | begin indirection |
@@ -456,10 +455,9 @@ edges
| test.cpp:124:15:124:20 | call to malloc | test.cpp:125:5:125:17 | ... = ... |
| test.cpp:124:15:124:20 | call to malloc | test.cpp:126:15:126:15 | p |
| test.cpp:125:5:125:17 | ... = ... | test.cpp:125:9:125:13 | arr indirection [post update] [begin] |
| test.cpp:125:9:125:13 | arr indirection [post update] [begin] | test.cpp:126:5:126:7 | arr indirection [begin] |
| test.cpp:126:5:126:7 | arr indirection [begin] | test.cpp:129:11:129:13 | arr indirection [begin] |
| test.cpp:126:5:126:7 | arr indirection [begin] | test.cpp:133:11:133:13 | arr indirection [begin] |
| test.cpp:126:5:126:7 | arr indirection [begin] | test.cpp:137:11:137:13 | arr indirection [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 indirection |
| test.cpp:129:15:129:19 | begin indirection | test.cpp:129:15:129:19 | begin |
| test.cpp:133:11:133:13 | arr indirection [begin] | test.cpp:133:15:133:19 | begin indirection |
@@ -471,10 +469,9 @@ edges
| test.cpp:141:10:141:19 | mk_array_p indirection [end] | test.cpp:150:20:150:29 | call to mk_array_p indirection [end] |
| test.cpp:141:10:141:19 | mk_array_p indirection [end] | test.cpp:180:19:180:28 | call to mk_array_p indirection [end] |
| test.cpp:143:5:143:29 | ... = ... | test.cpp:143:10:143:14 | arr indirection [post update] [begin] |
| test.cpp:143:10:143:14 | arr indirection [post update] [begin] | test.cpp:144:5:144:7 | arr indirection [begin] |
| test.cpp:143:10:143:14 | arr indirection [post update] [begin] | test.cpp:141:10:141:19 | mk_array_p indirection [begin] |
| test.cpp:143:10:143:14 | arr indirection [post update] [begin] | test.cpp:144:16:144:18 | arr indirection [begin] |
| test.cpp:143:18:143:23 | call to malloc | test.cpp:143:5:143:29 | ... = ... |
| test.cpp:144:5:144:7 | arr indirection [begin] | test.cpp:141:10:141:19 | mk_array_p indirection [begin] |
| test.cpp:144:5:144:32 | ... = ... | test.cpp:144:10:144:12 | arr indirection [post update] [end] |
| test.cpp:144:10:144:12 | arr indirection [post update] [end] | test.cpp:141:10:141:19 | mk_array_p indirection [end] |
| test.cpp:144:16:144:18 | arr indirection [begin] | test.cpp:144:21:144:25 | begin indirection |
@@ -720,6 +717,14 @@ edges
| test.cpp:359:16:359:27 | end_plus_one | test.cpp:359:14:359:32 | Load: * ... |
| test.cpp:359:16:359:31 | ... + ... | test.cpp:359:14:359:32 | Load: * ... |
| test.cpp:363:14:363:27 | new[] | test.cpp:365:15:365:15 | p |
| test.cpp:365:15:365:15 | p | test.cpp:368:5:368:10 | ... += ... |
| test.cpp:365:15:365:15 | p | test.cpp:368:5:368:10 | ... += ... |
| test.cpp:368:5:368:10 | ... += ... | test.cpp:371:7:371:7 | p |
| test.cpp:368:5:368:10 | ... += ... | test.cpp:371:7:371:7 | p |
| test.cpp:368:5:368:10 | ... += ... | test.cpp:372:16:372:16 | p |
| test.cpp:368:5:368:10 | ... += ... | test.cpp:372:16:372:16 | p |
| test.cpp:371:7:371:7 | p | test.cpp:372:15:372:16 | Load: * ... |
| test.cpp:372:16:372:16 | p | test.cpp:372:15:372:16 | Load: * ... |
| test.cpp:377:14:377:27 | new[] | test.cpp:378:15:378:16 | xs |
| test.cpp:378:15:378:16 | xs | test.cpp:378:15:378:23 | ... + ... |
| test.cpp:378:15:378:16 | xs | test.cpp:378:15:378:23 | ... + ... |
@@ -743,304 +748,6 @@ edges
| test.cpp:381:5:381:9 | ... ++ | test.cpp:384:14:384:16 | end |
| test.cpp:381:5:381:9 | ... ++ | test.cpp:384:14:384:16 | end |
| test.cpp:384:14:384:16 | end | test.cpp:384:13:384:16 | Load: * ... |
| test.cpp:388:14:388:27 | new[] | test.cpp:389:16:389:17 | xs |
| test.cpp:388:14:388:27 | new[] | test.cpp:392:3:392:4 | xs |
| test.cpp:399:14:399:27 | new[] | test.cpp:400:16:400:17 | xs |
| test.cpp:399:14:399:27 | new[] | test.cpp:402:5:402:6 | xs |
| test.cpp:410:14:410:27 | new[] | test.cpp:411:16:411:17 | xs |
| test.cpp:410:14:410:27 | new[] | test.cpp:413:5:413:6 | xs |
| test.cpp:411:15:411:23 | & ... | test.cpp:411:15:411:23 | & ... |
| test.cpp:411:15:411:23 | & ... | test.cpp:411:15:411:23 | & ... |
| test.cpp:411:15:411:23 | & ... | test.cpp:412:12:412:14 | end |
| test.cpp:411:15:411:23 | & ... | test.cpp:412:12:412:14 | end |
| test.cpp:411:15:411:23 | & ... | test.cpp:412:12:412:14 | end |
| test.cpp:411:15:411:23 | & ... | test.cpp:412:12:412:14 | end |
| test.cpp:411:15:411:23 | & ... | test.cpp:414:14:414:16 | end |
| test.cpp:411:15:411:23 | & ... | test.cpp:414:14:414:16 | end |
| test.cpp:411:15:411:23 | & ... | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:411:15:411:23 | & ... | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:411:15:411:23 | & ... | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:411:15:411:23 | & ... | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:411:16:411:17 | xs | test.cpp:411:15:411:23 | & ... |
| test.cpp:411:16:411:17 | xs | test.cpp:411:15:411:23 | & ... |
| test.cpp:411:16:411:17 | xs | test.cpp:411:15:411:23 | & ... |
| test.cpp:411:16:411:17 | xs | test.cpp:411:15:411:23 | & ... |
| test.cpp:411:16:411:17 | xs | test.cpp:411:16:411:23 | access to array |
| test.cpp:411:16:411:17 | xs | test.cpp:411:16:411:23 | access to array |
| test.cpp:411:16:411:17 | xs | test.cpp:412:12:412:14 | end |
| test.cpp:411:16:411:17 | xs | test.cpp:412:12:412:14 | end |
| test.cpp:411:16:411:17 | xs | test.cpp:413:5:413:8 | ... ++ |
| test.cpp:411:16:411:17 | xs | test.cpp:413:5:413:8 | ... ++ |
| test.cpp:411:16:411:17 | xs | test.cpp:413:5:413:8 | ... ++ |
| test.cpp:411:16:411:17 | xs | test.cpp:413:5:413:8 | ... ++ |
| test.cpp:411:16:411:17 | xs | test.cpp:414:9:414:10 | xs |
| test.cpp:411:16:411:17 | xs | test.cpp:414:14:414:16 | end |
| test.cpp:411:16:411:17 | xs | test.cpp:415:7:415:11 | access to array |
| test.cpp:411:16:411:23 | access to array | test.cpp:411:15:411:23 | & ... |
| test.cpp:411:16:411:23 | access to array | test.cpp:411:15:411:23 | & ... |
| test.cpp:411:16:411:23 | access to array | test.cpp:411:15:411:23 | & ... |
| test.cpp:411:16:411:23 | access to array | test.cpp:411:15:411:23 | & ... |
| test.cpp:411:16:411:23 | access to array | test.cpp:412:12:412:14 | end |
| test.cpp:411:16:411:23 | access to array | test.cpp:412:12:412:14 | end |
| test.cpp:411:16:411:23 | access to array | test.cpp:414:14:414:16 | end |
| test.cpp:411:16:411:23 | access to array | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:411:16:411:23 | access to array | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:412:12:412:14 | end | test.cpp:414:14:414:16 | end |
| test.cpp:412:12:412:14 | end | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:412:12:412:14 | end | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:413:5:413:8 | ... ++ | test.cpp:413:5:413:8 | ... ++ |
| test.cpp:413:5:413:8 | ... ++ | test.cpp:413:5:413:8 | ... ++ |
| test.cpp:413:5:413:8 | ... ++ | test.cpp:414:9:414:10 | xs |
| test.cpp:413:5:413:8 | ... ++ | test.cpp:414:9:414:10 | xs |
| test.cpp:413:5:413:8 | ... ++ | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:413:5:413:8 | ... ++ | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:413:5:413:8 | ... ++ | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:413:5:413:8 | ... ++ | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:414:9:414:10 | xs | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:414:14:414:16 | end | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:415:7:415:11 | access to array | test.cpp:415:7:415:15 | Store: ... = ... |
| test.cpp:421:14:421:27 | new[] | test.cpp:422:16:422:17 | xs |
| test.cpp:421:14:421:27 | new[] | test.cpp:424:5:424:6 | xs |
| test.cpp:422:15:422:23 | & ... | test.cpp:422:15:422:23 | & ... |
| test.cpp:422:15:422:23 | & ... | test.cpp:422:15:422:23 | & ... |
| test.cpp:422:15:422:23 | & ... | test.cpp:423:12:423:14 | end |
| test.cpp:422:15:422:23 | & ... | test.cpp:423:12:423:14 | end |
| test.cpp:422:15:422:23 | & ... | test.cpp:423:12:423:14 | end |
| test.cpp:422:15:422:23 | & ... | test.cpp:423:12:423:14 | end |
| test.cpp:422:15:422:23 | & ... | test.cpp:425:18:425:20 | end |
| test.cpp:422:15:422:23 | & ... | test.cpp:425:18:425:20 | end |
| test.cpp:422:15:422:23 | & ... | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:422:15:422:23 | & ... | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:422:15:422:23 | & ... | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:422:15:422:23 | & ... | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:422:16:422:17 | xs | test.cpp:422:15:422:23 | & ... |
| test.cpp:422:16:422:17 | xs | test.cpp:422:15:422:23 | & ... |
| test.cpp:422:16:422:17 | xs | test.cpp:422:15:422:23 | & ... |
| test.cpp:422:16:422:17 | xs | test.cpp:422:15:422:23 | & ... |
| test.cpp:422:16:422:17 | xs | test.cpp:422:16:422:23 | access to array |
| test.cpp:422:16:422:17 | xs | test.cpp:422:16:422:23 | access to array |
| test.cpp:422:16:422:17 | xs | test.cpp:423:12:423:14 | end |
| test.cpp:422:16:422:17 | xs | test.cpp:423:12:423:14 | end |
| test.cpp:422:16:422:17 | xs | test.cpp:424:5:424:8 | ... ++ |
| test.cpp:422:16:422:17 | xs | test.cpp:424:5:424:8 | ... ++ |
| test.cpp:422:16:422:17 | xs | test.cpp:424:5:424:8 | ... ++ |
| test.cpp:422:16:422:17 | xs | test.cpp:424:5:424:8 | ... ++ |
| test.cpp:422:16:422:17 | xs | test.cpp:425:9:425:10 | xs |
| test.cpp:422:16:422:17 | xs | test.cpp:425:9:425:10 | xs |
| test.cpp:422:16:422:17 | xs | test.cpp:425:18:425:20 | end |
| test.cpp:422:16:422:17 | xs | test.cpp:426:7:426:8 | xs |
| test.cpp:422:16:422:17 | xs | test.cpp:426:7:426:11 | access to array |
| test.cpp:422:16:422:23 | access to array | test.cpp:422:15:422:23 | & ... |
| test.cpp:422:16:422:23 | access to array | test.cpp:422:15:422:23 | & ... |
| test.cpp:422:16:422:23 | access to array | test.cpp:422:15:422:23 | & ... |
| test.cpp:422:16:422:23 | access to array | test.cpp:422:15:422:23 | & ... |
| test.cpp:422:16:422:23 | access to array | test.cpp:423:12:423:14 | end |
| test.cpp:422:16:422:23 | access to array | test.cpp:423:12:423:14 | end |
| test.cpp:422:16:422:23 | access to array | test.cpp:425:18:425:20 | end |
| test.cpp:422:16:422:23 | access to array | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:422:16:422:23 | access to array | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:423:12:423:14 | end | test.cpp:425:18:425:20 | end |
| test.cpp:423:12:423:14 | end | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:423:12:423:14 | end | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:424:5:424:8 | ... ++ | test.cpp:424:5:424:8 | ... ++ |
| test.cpp:424:5:424:8 | ... ++ | test.cpp:424:5:424:8 | ... ++ |
| test.cpp:424:5:424:8 | ... ++ | test.cpp:425:9:425:10 | xs |
| test.cpp:424:5:424:8 | ... ++ | test.cpp:425:9:425:10 | xs |
| test.cpp:424:5:424:8 | ... ++ | test.cpp:425:9:425:10 | xs |
| test.cpp:424:5:424:8 | ... ++ | test.cpp:425:9:425:10 | xs |
| test.cpp:424:5:424:8 | ... ++ | test.cpp:426:7:426:8 | xs |
| test.cpp:424:5:424:8 | ... ++ | test.cpp:426:7:426:8 | xs |
| test.cpp:424:5:424:8 | ... ++ | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:424:5:424:8 | ... ++ | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:424:5:424:8 | ... ++ | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:424:5:424:8 | ... ++ | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:425:9:425:10 | xs | test.cpp:426:7:426:8 | xs |
| test.cpp:425:9:425:10 | xs | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:425:9:425:10 | xs | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:425:18:425:20 | end | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:426:7:426:8 | xs | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:426:7:426:11 | access to array | test.cpp:426:7:426:15 | Store: ... = ... |
| test.cpp:432:14:432:27 | new[] | test.cpp:433:16:433:17 | xs |
| test.cpp:432:14:432:27 | new[] | test.cpp:436:5:436:6 | xs |
| test.cpp:433:15:433:23 | & ... | test.cpp:433:15:433:23 | & ... |
| test.cpp:433:15:433:23 | & ... | test.cpp:433:15:433:23 | & ... |
| test.cpp:433:15:433:23 | & ... | test.cpp:434:12:434:14 | end |
| test.cpp:433:15:433:23 | & ... | test.cpp:434:12:434:14 | end |
| test.cpp:433:15:433:23 | & ... | test.cpp:434:12:434:14 | end |
| test.cpp:433:15:433:23 | & ... | test.cpp:434:12:434:14 | end |
| test.cpp:433:15:433:23 | & ... | test.cpp:435:5:435:7 | end |
| test.cpp:433:15:433:23 | & ... | test.cpp:435:5:435:7 | end |
| test.cpp:433:15:433:23 | & ... | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:433:15:433:23 | & ... | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:433:15:433:23 | & ... | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:433:15:433:23 | & ... | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:433:16:433:17 | xs | test.cpp:433:15:433:23 | & ... |
| test.cpp:433:16:433:17 | xs | test.cpp:433:15:433:23 | & ... |
| test.cpp:433:16:433:17 | xs | test.cpp:433:15:433:23 | & ... |
| test.cpp:433:16:433:17 | xs | test.cpp:433:15:433:23 | & ... |
| test.cpp:433:16:433:17 | xs | test.cpp:433:16:433:23 | access to array |
| test.cpp:433:16:433:17 | xs | test.cpp:433:16:433:23 | access to array |
| test.cpp:433:16:433:17 | xs | test.cpp:434:12:434:14 | end |
| test.cpp:433:16:433:17 | xs | test.cpp:434:12:434:14 | end |
| test.cpp:433:16:433:17 | xs | test.cpp:435:5:435:7 | end |
| test.cpp:433:16:433:17 | xs | test.cpp:436:5:436:8 | ... ++ |
| test.cpp:433:16:433:17 | xs | test.cpp:436:5:436:8 | ... ++ |
| test.cpp:433:16:433:17 | xs | test.cpp:436:5:436:8 | ... ++ |
| test.cpp:433:16:433:17 | xs | test.cpp:436:5:436:8 | ... ++ |
| test.cpp:433:16:433:17 | xs | test.cpp:437:9:437:10 | xs |
| test.cpp:433:16:433:17 | xs | test.cpp:438:7:438:11 | access to array |
| test.cpp:433:16:433:23 | access to array | test.cpp:433:15:433:23 | & ... |
| test.cpp:433:16:433:23 | access to array | test.cpp:433:15:433:23 | & ... |
| test.cpp:433:16:433:23 | access to array | test.cpp:433:15:433:23 | & ... |
| test.cpp:433:16:433:23 | access to array | test.cpp:433:15:433:23 | & ... |
| test.cpp:433:16:433:23 | access to array | test.cpp:434:12:434:14 | end |
| test.cpp:433:16:433:23 | access to array | test.cpp:434:12:434:14 | end |
| test.cpp:433:16:433:23 | access to array | test.cpp:435:5:435:7 | end |
| test.cpp:433:16:433:23 | access to array | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:433:16:433:23 | access to array | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:434:12:434:14 | end | test.cpp:435:5:435:7 | end |
| test.cpp:434:12:434:14 | end | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:434:12:434:14 | end | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:435:5:435:7 | end | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:436:5:436:8 | ... ++ | test.cpp:436:5:436:8 | ... ++ |
| test.cpp:436:5:436:8 | ... ++ | test.cpp:436:5:436:8 | ... ++ |
| test.cpp:436:5:436:8 | ... ++ | test.cpp:437:9:437:10 | xs |
| test.cpp:436:5:436:8 | ... ++ | test.cpp:437:9:437:10 | xs |
| test.cpp:436:5:436:8 | ... ++ | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:436:5:436:8 | ... ++ | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:436:5:436:8 | ... ++ | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:436:5:436:8 | ... ++ | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:437:9:437:10 | xs | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:438:7:438:11 | access to array | test.cpp:438:7:438:15 | Store: ... = ... |
| test.cpp:444:14:444:27 | new[] | test.cpp:445:16:445:17 | xs |
| test.cpp:444:14:444:27 | new[] | test.cpp:448:5:448:6 | xs |
| test.cpp:445:15:445:23 | & ... | test.cpp:445:15:445:23 | & ... |
| test.cpp:445:15:445:23 | & ... | test.cpp:445:15:445:23 | & ... |
| test.cpp:445:15:445:23 | & ... | test.cpp:446:3:446:5 | end |
| test.cpp:445:15:445:23 | & ... | test.cpp:446:3:446:5 | end |
| test.cpp:445:15:445:23 | & ... | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:445:15:445:23 | & ... | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:445:15:445:23 | & ... | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:445:15:445:23 | & ... | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:445:16:445:17 | xs | test.cpp:445:15:445:23 | & ... |
| test.cpp:445:16:445:17 | xs | test.cpp:445:15:445:23 | & ... |
| test.cpp:445:16:445:17 | xs | test.cpp:445:15:445:23 | & ... |
| test.cpp:445:16:445:17 | xs | test.cpp:445:15:445:23 | & ... |
| test.cpp:445:16:445:17 | xs | test.cpp:445:16:445:23 | access to array |
| test.cpp:445:16:445:17 | xs | test.cpp:445:16:445:23 | access to array |
| test.cpp:445:16:445:17 | xs | test.cpp:446:3:446:5 | end |
| test.cpp:445:16:445:17 | xs | test.cpp:448:5:448:8 | ... ++ |
| test.cpp:445:16:445:17 | xs | test.cpp:448:5:448:8 | ... ++ |
| test.cpp:445:16:445:17 | xs | test.cpp:448:5:448:8 | ... ++ |
| test.cpp:445:16:445:17 | xs | test.cpp:448:5:448:8 | ... ++ |
| test.cpp:445:16:445:17 | xs | test.cpp:449:9:449:10 | xs |
| test.cpp:445:16:445:17 | xs | test.cpp:450:7:450:11 | access to array |
| test.cpp:445:16:445:23 | access to array | test.cpp:445:15:445:23 | & ... |
| test.cpp:445:16:445:23 | access to array | test.cpp:445:15:445:23 | & ... |
| test.cpp:445:16:445:23 | access to array | test.cpp:445:15:445:23 | & ... |
| test.cpp:445:16:445:23 | access to array | test.cpp:445:15:445:23 | & ... |
| test.cpp:445:16:445:23 | access to array | test.cpp:446:3:446:5 | end |
| test.cpp:445:16:445:23 | access to array | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:445:16:445:23 | access to array | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:446:3:446:5 | end | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:448:5:448:8 | ... ++ | test.cpp:448:5:448:8 | ... ++ |
| test.cpp:448:5:448:8 | ... ++ | test.cpp:448:5:448:8 | ... ++ |
| test.cpp:448:5:448:8 | ... ++ | test.cpp:449:9:449:10 | xs |
| test.cpp:448:5:448:8 | ... ++ | test.cpp:449:9:449:10 | xs |
| test.cpp:448:5:448:8 | ... ++ | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:448:5:448:8 | ... ++ | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:448:5:448:8 | ... ++ | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:448:5:448:8 | ... ++ | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:449:9:449:10 | xs | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:450:7:450:11 | access to array | test.cpp:450:7:450:15 | Store: ... = ... |
| test.cpp:456:14:456:31 | new[] | test.cpp:457:16:457:17 | xs |
| test.cpp:456:14:456:31 | new[] | test.cpp:460:5:460:6 | xs |
| test.cpp:468:14:468:27 | new[] | test.cpp:469:16:469:17 | xs |
| test.cpp:468:14:468:27 | new[] | test.cpp:472:5:472:6 | xs |
| test.cpp:480:14:480:27 | new[] | test.cpp:481:16:481:17 | xs |
| test.cpp:480:14:480:27 | new[] | test.cpp:484:5:484:6 | xs |
| test.cpp:481:15:481:23 | & ... | test.cpp:481:15:481:23 | & ... |
| test.cpp:481:15:481:23 | & ... | test.cpp:481:15:481:23 | & ... |
| test.cpp:481:15:481:23 | & ... | test.cpp:482:3:482:5 | end |
| test.cpp:481:15:481:23 | & ... | test.cpp:482:3:482:5 | end |
| test.cpp:481:15:481:23 | & ... | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:481:15:481:23 | & ... | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:481:15:481:23 | & ... | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:481:15:481:23 | & ... | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:481:16:481:17 | xs | test.cpp:481:15:481:23 | & ... |
| test.cpp:481:16:481:17 | xs | test.cpp:481:15:481:23 | & ... |
| test.cpp:481:16:481:17 | xs | test.cpp:481:15:481:23 | & ... |
| test.cpp:481:16:481:17 | xs | test.cpp:481:15:481:23 | & ... |
| test.cpp:481:16:481:17 | xs | test.cpp:481:16:481:23 | access to array |
| test.cpp:481:16:481:17 | xs | test.cpp:481:16:481:23 | access to array |
| test.cpp:481:16:481:17 | xs | test.cpp:482:3:482:5 | end |
| test.cpp:481:16:481:17 | xs | test.cpp:484:5:484:8 | ... ++ |
| test.cpp:481:16:481:17 | xs | test.cpp:484:5:484:8 | ... ++ |
| test.cpp:481:16:481:17 | xs | test.cpp:484:5:484:8 | ... ++ |
| test.cpp:481:16:481:17 | xs | test.cpp:484:5:484:8 | ... ++ |
| test.cpp:481:16:481:17 | xs | test.cpp:485:9:485:10 | xs |
| test.cpp:481:16:481:17 | xs | test.cpp:486:7:486:11 | access to array |
| test.cpp:481:16:481:23 | access to array | test.cpp:481:15:481:23 | & ... |
| test.cpp:481:16:481:23 | access to array | test.cpp:481:15:481:23 | & ... |
| test.cpp:481:16:481:23 | access to array | test.cpp:481:15:481:23 | & ... |
| test.cpp:481:16:481:23 | access to array | test.cpp:481:15:481:23 | & ... |
| test.cpp:481:16:481:23 | access to array | test.cpp:482:3:482:5 | end |
| test.cpp:481:16:481:23 | access to array | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:481:16:481:23 | access to array | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:482:3:482:5 | end | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:484:5:484:8 | ... ++ | test.cpp:484:5:484:8 | ... ++ |
| test.cpp:484:5:484:8 | ... ++ | test.cpp:484:5:484:8 | ... ++ |
| test.cpp:484:5:484:8 | ... ++ | test.cpp:485:9:485:10 | xs |
| test.cpp:484:5:484:8 | ... ++ | test.cpp:485:9:485:10 | xs |
| test.cpp:484:5:484:8 | ... ++ | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:484:5:484:8 | ... ++ | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:484:5:484:8 | ... ++ | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:484:5:484:8 | ... ++ | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:485:9:485:10 | xs | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:486:7:486:11 | access to array | test.cpp:486:7:486:15 | Store: ... = ... |
| test.cpp:499:3:499:25 | ... = ... | test.cpp:499:7:499:8 | val indirection [post update] [xs] |
| test.cpp:499:7:499:8 | val indirection [post update] [xs] | test.cpp:500:3:500:5 | val indirection [xs] |
| test.cpp:499:12:499:25 | new[] | test.cpp:499:3:499:25 | ... = ... |
| test.cpp:500:3:500:5 | val indirection [xs] | test.cpp:500:7:500:8 | xs indirection |
| test.cpp:500:7:500:8 | xs indirection | test.cpp:500:7:500:8 | xs |
| test.cpp:510:16:510:33 | new[] | test.cpp:512:7:512:8 | xs |
| test.cpp:520:14:520:27 | new[] | test.cpp:526:5:526:6 | xs |
| test.cpp:532:14:532:27 | new[] | test.cpp:537:5:537:6 | xs |
| test.cpp:543:14:543:27 | new[] | test.cpp:548:5:548:6 | xs |
| test.cpp:548:5:548:6 | xs | test.cpp:548:5:548:15 | access to array |
| test.cpp:548:5:548:15 | access to array | test.cpp:548:5:548:19 | Store: ... = ... |
| test.cpp:554:14:554:27 | new[] | test.cpp:559:5:559:6 | xs |
| test.cpp:559:5:559:6 | xs | test.cpp:559:5:559:15 | access to array |
| test.cpp:559:5:559:15 | access to array | test.cpp:559:5:559:19 | Store: ... = ... |
| test.cpp:565:14:565:27 | new[] | test.cpp:570:5:570:6 | xs |
| test.cpp:576:14:576:27 | new[] | test.cpp:581:5:581:6 | xs |
| test.cpp:587:14:587:31 | new[] | test.cpp:592:5:592:6 | xs |
| test.cpp:598:14:598:31 | new[] | test.cpp:603:5:603:6 | xs |
| test.cpp:609:14:609:31 | new[] | test.cpp:614:5:614:6 | xs |
| test.cpp:620:14:620:31 | new[] | test.cpp:625:5:625:6 | xs |
| test.cpp:631:14:631:31 | new[] | test.cpp:636:5:636:6 | xs |
| test.cpp:642:14:642:31 | new[] | test.cpp:647:5:647:6 | xs |
| test.cpp:647:5:647:6 | xs | test.cpp:647:5:647:15 | access to array |
| test.cpp:647:5:647:15 | access to array | test.cpp:647:5:647:19 | Store: ... = ... |
| test.cpp:652:14:652:27 | new[] | test.cpp:653:16:653:17 | xs |
| test.cpp:652:14:652:27 | new[] | test.cpp:656:3:656:4 | xs |
| test.cpp:653:16:653:17 | xs | test.cpp:656:3:656:6 | ... ++ |
| test.cpp:653:16:653:17 | xs | test.cpp:656:3:656:6 | ... ++ |
| test.cpp:653:16:653:17 | xs | test.cpp:656:3:656:6 | ... ++ |
| test.cpp:653:16:653:17 | xs | test.cpp:656:3:656:6 | ... ++ |
| test.cpp:653:16:653:17 | xs | test.cpp:657:7:657:8 | xs |
| test.cpp:656:3:656:6 | ... ++ | test.cpp:656:3:656:6 | ... ++ |
| test.cpp:656:3:656:6 | ... ++ | test.cpp:656:3:656:6 | ... ++ |
| test.cpp:656:3:656:6 | ... ++ | test.cpp:657:7:657:8 | xs |
| test.cpp:656:3:656:6 | ... ++ | test.cpp:657:7:657:8 | xs |
| test.cpp:656:3:656:6 | ... ++ | test.cpp:662:3:662:11 | Store: ... = ... |
| test.cpp:656:3:656:6 | ... ++ | test.cpp:662:3:662:11 | Store: ... = ... |
| test.cpp:656:3:656:6 | ... ++ | test.cpp:662:3:662:11 | Store: ... = ... |
| test.cpp:656:3:656:6 | ... ++ | test.cpp:662:3:662:11 | Store: ... = ... |
| test.cpp:657:7:657:8 | xs | test.cpp:662:3:662:11 | Store: ... = ... |
| test.cpp:667:14:667:31 | new[] | test.cpp:675:7:675:8 | xs |
| test.cpp:675:7:675:8 | xs | test.cpp:675:7:675:19 | access to array |
| test.cpp:675:7:675:19 | access to array | test.cpp:675:7:675:23 | Store: ... = ... |
nodes
| test.cpp:4:15:4:20 | call to malloc | semmle.label | call to malloc |
| test.cpp:5:15:5:15 | p | semmle.label | p |
@@ -1133,7 +840,6 @@ nodes
| test.cpp:82:5:82:28 | ... = ... | semmle.label | ... = ... |
| test.cpp:82:9:82:13 | arr indirection [post update] [begin] | semmle.label | arr indirection [post update] [begin] |
| test.cpp:82:17:82:22 | call to malloc | semmle.label | call to malloc |
| test.cpp:83:5:83:7 | arr indirection [begin] | semmle.label | arr indirection [begin] |
| test.cpp:83:5:83:30 | ... = ... | semmle.label | ... = ... |
| test.cpp:83:9:83:11 | arr indirection [post update] [end] | semmle.label | arr indirection [post update] [end] |
| test.cpp:83:15:83:17 | arr indirection [begin] | semmle.label | arr indirection [begin] |
@@ -1193,7 +899,6 @@ nodes
| test.cpp:124:15:124:20 | call to malloc | semmle.label | call to malloc |
| test.cpp:125:5:125:17 | ... = ... | semmle.label | ... = ... |
| test.cpp:125:9:125:13 | arr indirection [post update] [begin] | semmle.label | arr indirection [post update] [begin] |
| test.cpp:126:5:126:7 | arr indirection [begin] | semmle.label | arr indirection [begin] |
| test.cpp:126:15:126:15 | p | semmle.label | p |
| test.cpp:129:11:129:13 | arr indirection [begin] | semmle.label | arr indirection [begin] |
| test.cpp:129:15:129:19 | begin | semmle.label | begin |
@@ -1209,7 +914,6 @@ nodes
| test.cpp:143:5:143:29 | ... = ... | semmle.label | ... = ... |
| test.cpp:143:10:143:14 | arr indirection [post update] [begin] | semmle.label | arr indirection [post update] [begin] |
| test.cpp:143:18:143:23 | call to malloc | semmle.label | call to malloc |
| test.cpp:144:5:144:7 | arr indirection [begin] | semmle.label | arr indirection [begin] |
| test.cpp:144:5:144:32 | ... = ... | semmle.label | ... = ... |
| test.cpp:144:10:144:12 | arr indirection [post update] [end] | semmle.label | arr indirection [post update] [end] |
| test.cpp:144:16:144:18 | arr indirection [begin] | semmle.label | arr indirection [begin] |
@@ -1367,6 +1071,11 @@ nodes
| test.cpp:359:16:359:31 | ... + ... | semmle.label | ... + ... |
| test.cpp:363:14:363:27 | new[] | semmle.label | new[] |
| test.cpp:365:15:365:15 | p | semmle.label | p |
| test.cpp:368:5:368:10 | ... += ... | semmle.label | ... += ... |
| test.cpp:368:5:368:10 | ... += ... | semmle.label | ... += ... |
| test.cpp:371:7:371:7 | p | semmle.label | p |
| test.cpp:372:15:372:16 | Load: * ... | semmle.label | Load: * ... |
| test.cpp:372:16:372:16 | p | semmle.label | p |
| test.cpp:377:14:377:27 | new[] | semmle.label | new[] |
| test.cpp:378:15:378:16 | xs | semmle.label | xs |
| test.cpp:378:15:378:23 | ... + ... | semmle.label | ... + ... |
@@ -1378,162 +1087,6 @@ nodes
| test.cpp:381:5:381:9 | ... ++ | semmle.label | ... ++ |
| test.cpp:384:13:384:16 | Load: * ... | semmle.label | Load: * ... |
| test.cpp:384:14:384:16 | end | semmle.label | end |
| test.cpp:388:14:388:27 | new[] | semmle.label | new[] |
| test.cpp:389:16:389:17 | xs | semmle.label | xs |
| test.cpp:392:3:392:4 | xs | semmle.label | xs |
| test.cpp:399:14:399:27 | new[] | semmle.label | new[] |
| test.cpp:400:16:400:17 | xs | semmle.label | xs |
| test.cpp:402:5:402:6 | xs | semmle.label | xs |
| test.cpp:410:14:410:27 | new[] | semmle.label | new[] |
| test.cpp:411:15:411:23 | & ... | semmle.label | & ... |
| test.cpp:411:15:411:23 | & ... | semmle.label | & ... |
| test.cpp:411:15:411:23 | & ... | semmle.label | & ... |
| test.cpp:411:15:411:23 | & ... | semmle.label | & ... |
| test.cpp:411:16:411:17 | xs | semmle.label | xs |
| test.cpp:411:16:411:23 | access to array | semmle.label | access to array |
| test.cpp:411:16:411:23 | access to array | semmle.label | access to array |
| test.cpp:412:12:412:14 | end | semmle.label | end |
| test.cpp:412:12:412:14 | end | semmle.label | end |
| test.cpp:413:5:413:6 | xs | semmle.label | xs |
| test.cpp:413:5:413:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:413:5:413:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:413:5:413:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:413:5:413:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:414:9:414:10 | xs | semmle.label | xs |
| test.cpp:414:14:414:16 | end | semmle.label | end |
| test.cpp:415:7:415:11 | access to array | semmle.label | access to array |
| test.cpp:415:7:415:15 | Store: ... = ... | semmle.label | Store: ... = ... |
| test.cpp:421:14:421:27 | new[] | semmle.label | new[] |
| test.cpp:422:15:422:23 | & ... | semmle.label | & ... |
| test.cpp:422:15:422:23 | & ... | semmle.label | & ... |
| test.cpp:422:15:422:23 | & ... | semmle.label | & ... |
| test.cpp:422:15:422:23 | & ... | semmle.label | & ... |
| test.cpp:422:16:422:17 | xs | semmle.label | xs |
| test.cpp:422:16:422:23 | access to array | semmle.label | access to array |
| test.cpp:422:16:422:23 | access to array | semmle.label | access to array |
| test.cpp:423:12:423:14 | end | semmle.label | end |
| test.cpp:423:12:423:14 | end | semmle.label | end |
| test.cpp:424:5:424:6 | xs | semmle.label | xs |
| test.cpp:424:5:424:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:424:5:424:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:424:5:424:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:424:5:424:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:425:9:425:10 | xs | semmle.label | xs |
| test.cpp:425:9:425:10 | xs | semmle.label | xs |
| test.cpp:425:18:425:20 | end | semmle.label | end |
| test.cpp:426:7:426:8 | xs | semmle.label | xs |
| test.cpp:426:7:426:11 | access to array | semmle.label | access to array |
| test.cpp:426:7:426:15 | Store: ... = ... | semmle.label | Store: ... = ... |
| test.cpp:432:14:432:27 | new[] | semmle.label | new[] |
| test.cpp:433:15:433:23 | & ... | semmle.label | & ... |
| test.cpp:433:15:433:23 | & ... | semmle.label | & ... |
| test.cpp:433:15:433:23 | & ... | semmle.label | & ... |
| test.cpp:433:15:433:23 | & ... | semmle.label | & ... |
| test.cpp:433:16:433:17 | xs | semmle.label | xs |
| test.cpp:433:16:433:23 | access to array | semmle.label | access to array |
| test.cpp:433:16:433:23 | access to array | semmle.label | access to array |
| test.cpp:434:12:434:14 | end | semmle.label | end |
| test.cpp:434:12:434:14 | end | semmle.label | end |
| test.cpp:435:5:435:7 | end | semmle.label | end |
| test.cpp:436:5:436:6 | xs | semmle.label | xs |
| test.cpp:436:5:436:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:436:5:436:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:436:5:436:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:436:5:436:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:437:9:437:10 | xs | semmle.label | xs |
| test.cpp:438:7:438:11 | access to array | semmle.label | access to array |
| test.cpp:438:7:438:15 | Store: ... = ... | semmle.label | Store: ... = ... |
| test.cpp:444:14:444:27 | new[] | semmle.label | new[] |
| test.cpp:445:15:445:23 | & ... | semmle.label | & ... |
| test.cpp:445:15:445:23 | & ... | semmle.label | & ... |
| test.cpp:445:15:445:23 | & ... | semmle.label | & ... |
| test.cpp:445:15:445:23 | & ... | semmle.label | & ... |
| test.cpp:445:16:445:17 | xs | semmle.label | xs |
| test.cpp:445:16:445:23 | access to array | semmle.label | access to array |
| test.cpp:445:16:445:23 | access to array | semmle.label | access to array |
| test.cpp:446:3:446:5 | end | semmle.label | end |
| test.cpp:448:5:448:6 | xs | semmle.label | xs |
| test.cpp:448:5:448:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:448:5:448:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:448:5:448:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:448:5:448:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:449:9:449:10 | xs | semmle.label | xs |
| test.cpp:450:7:450:11 | access to array | semmle.label | access to array |
| test.cpp:450:7:450:15 | Store: ... = ... | semmle.label | Store: ... = ... |
| test.cpp:456:14:456:31 | new[] | semmle.label | new[] |
| test.cpp:457:16:457:17 | xs | semmle.label | xs |
| test.cpp:460:5:460:6 | xs | semmle.label | xs |
| test.cpp:468:14:468:27 | new[] | semmle.label | new[] |
| test.cpp:469:16:469:17 | xs | semmle.label | xs |
| test.cpp:472:5:472:6 | xs | semmle.label | xs |
| test.cpp:480:14:480:27 | new[] | semmle.label | new[] |
| test.cpp:481:15:481:23 | & ... | semmle.label | & ... |
| test.cpp:481:15:481:23 | & ... | semmle.label | & ... |
| test.cpp:481:15:481:23 | & ... | semmle.label | & ... |
| test.cpp:481:15:481:23 | & ... | semmle.label | & ... |
| test.cpp:481:16:481:17 | xs | semmle.label | xs |
| test.cpp:481:16:481:23 | access to array | semmle.label | access to array |
| test.cpp:481:16:481:23 | access to array | semmle.label | access to array |
| test.cpp:482:3:482:5 | end | semmle.label | end |
| test.cpp:484:5:484:6 | xs | semmle.label | xs |
| test.cpp:484:5:484:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:484:5:484:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:484:5:484:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:484:5:484:8 | ... ++ | semmle.label | ... ++ |
| test.cpp:485:9:485:10 | xs | semmle.label | xs |
| test.cpp:486:7:486:11 | access to array | semmle.label | access to array |
| test.cpp:486:7:486:15 | Store: ... = ... | semmle.label | Store: ... = ... |
| test.cpp:499:3:499:25 | ... = ... | semmle.label | ... = ... |
| test.cpp:499:7:499:8 | val indirection [post update] [xs] | semmle.label | val indirection [post update] [xs] |
| test.cpp:499:12:499:25 | new[] | semmle.label | new[] |
| test.cpp:500:3:500:5 | val indirection [xs] | semmle.label | val indirection [xs] |
| test.cpp:500:7:500:8 | xs | semmle.label | xs |
| test.cpp:500:7:500:8 | xs indirection | semmle.label | xs indirection |
| test.cpp:510:16:510:33 | new[] | semmle.label | new[] |
| test.cpp:512:7:512:8 | xs | semmle.label | xs |
| test.cpp:520:14:520:27 | new[] | semmle.label | new[] |
| test.cpp:526:5:526:6 | xs | semmle.label | xs |
| test.cpp:532:14:532:27 | new[] | semmle.label | new[] |
| test.cpp:537:5:537:6 | xs | semmle.label | xs |
| test.cpp:543:14:543:27 | new[] | semmle.label | new[] |
| test.cpp:548:5:548:6 | xs | semmle.label | xs |
| test.cpp:548:5:548:15 | access to array | semmle.label | access to array |
| test.cpp:548:5:548:19 | Store: ... = ... | semmle.label | Store: ... = ... |
| test.cpp:554:14:554:27 | new[] | semmle.label | new[] |
| test.cpp:559:5:559:6 | xs | semmle.label | xs |
| test.cpp:559:5:559:15 | access to array | semmle.label | access to array |
| test.cpp:559:5:559:19 | Store: ... = ... | semmle.label | Store: ... = ... |
| test.cpp:565:14:565:27 | new[] | semmle.label | new[] |
| test.cpp:570:5:570:6 | xs | semmle.label | xs |
| test.cpp:576:14:576:27 | new[] | semmle.label | new[] |
| test.cpp:581:5:581:6 | xs | semmle.label | xs |
| test.cpp:587:14:587:31 | new[] | semmle.label | new[] |
| test.cpp:592:5:592:6 | xs | semmle.label | xs |
| test.cpp:598:14:598:31 | new[] | semmle.label | new[] |
| test.cpp:603:5:603:6 | xs | semmle.label | xs |
| test.cpp:609:14:609:31 | new[] | semmle.label | new[] |
| test.cpp:614:5:614:6 | xs | semmle.label | xs |
| test.cpp:620:14:620:31 | new[] | semmle.label | new[] |
| test.cpp:625:5:625:6 | xs | semmle.label | xs |
| test.cpp:631:14:631:31 | new[] | semmle.label | new[] |
| test.cpp:636:5:636:6 | xs | semmle.label | xs |
| test.cpp:642:14:642:31 | new[] | semmle.label | new[] |
| test.cpp:647:5:647:6 | xs | semmle.label | xs |
| test.cpp:647:5:647:15 | access to array | semmle.label | access to array |
| test.cpp:647:5:647:19 | Store: ... = ... | semmle.label | Store: ... = ... |
| test.cpp:652:14:652:27 | new[] | semmle.label | new[] |
| test.cpp:653:16:653:17 | xs | semmle.label | xs |
| test.cpp:656:3:656:4 | xs | semmle.label | xs |
| test.cpp:656:3:656:6 | ... ++ | semmle.label | ... ++ |
| test.cpp:656:3:656:6 | ... ++ | semmle.label | ... ++ |
| test.cpp:656:3:656:6 | ... ++ | semmle.label | ... ++ |
| test.cpp:656:3:656:6 | ... ++ | semmle.label | ... ++ |
| test.cpp:657:7:657:8 | xs | semmle.label | xs |
| test.cpp:662:3:662:11 | Store: ... = ... | semmle.label | Store: ... = ... |
| test.cpp:667:14:667:31 | new[] | semmle.label | new[] |
| test.cpp:675:7:675:8 | xs | semmle.label | xs |
| test.cpp:675:7:675:19 | access to array | semmle.label | access to array |
| test.cpp:675:7:675:23 | Store: ... = ... | semmle.label | Store: ... = ... |
subpaths
#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 |
@@ -1558,14 +1111,5 @@ subpaths
| test.cpp:308:5:308:29 | Store: ... = ... | test.cpp:304:15:304:26 | new[] | test.cpp:308:5:308:29 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:304:15:304:26 | new[] | new[] | test.cpp:308:8:308:10 | ... + ... | ... + ... |
| test.cpp:358:14:358:26 | Load: * ... | test.cpp:355:14:355:27 | new[] | test.cpp:358:14:358:26 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:355:14:355:27 | new[] | new[] | test.cpp:356:20:356:23 | size | size |
| test.cpp:359:14:359:32 | Load: * ... | test.cpp:355:14:355:27 | new[] | test.cpp:359:14:359:32 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 2. | test.cpp:355:14:355:27 | new[] | new[] | test.cpp:356:20:356:23 | size | size |
| test.cpp:372:15:372:16 | Load: * ... | test.cpp:363:14:363:27 | new[] | test.cpp:372:15:372:16 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:363:14:363:27 | new[] | new[] | test.cpp:365:19:365:22 | size | size |
| test.cpp:384:13:384:16 | Load: * ... | test.cpp:377:14:377:27 | new[] | test.cpp:384:13:384:16 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:377:14:377:27 | new[] | new[] | test.cpp:378:20:378:23 | size | size |
| test.cpp:415:7:415:15 | Store: ... = ... | test.cpp:410:14:410:27 | new[] | test.cpp:415:7:415:15 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:410:14:410:27 | new[] | new[] | test.cpp:411:19:411:22 | size | size |
| test.cpp:426:7:426:15 | Store: ... = ... | test.cpp:421:14:421:27 | new[] | test.cpp:426:7:426:15 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:421:14:421:27 | new[] | new[] | test.cpp:422:19:422:22 | size | size |
| test.cpp:438:7:438:15 | Store: ... = ... | test.cpp:432:14:432:27 | new[] | test.cpp:438:7:438:15 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:432:14:432:27 | new[] | new[] | test.cpp:433:19:433:22 | size | size |
| test.cpp:450:7:450:15 | Store: ... = ... | test.cpp:444:14:444:27 | new[] | test.cpp:450:7:450:15 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:444:14:444:27 | new[] | new[] | test.cpp:445:19:445:22 | size | size |
| test.cpp:486:7:486:15 | Store: ... = ... | test.cpp:480:14:480:27 | new[] | test.cpp:486:7:486:15 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@ + 498. | test.cpp:480:14:480:27 | new[] | new[] | test.cpp:481:19:481:22 | size | size |
| test.cpp:548:5:548:19 | Store: ... = ... | test.cpp:543:14:543:27 | new[] | test.cpp:548:5:548:19 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:543:14:543:27 | new[] | new[] | test.cpp:548:8:548:14 | src_pos | src_pos |
| test.cpp:559:5:559:19 | Store: ... = ... | test.cpp:554:14:554:27 | new[] | test.cpp:559:5:559:19 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:554:14:554:27 | new[] | new[] | test.cpp:559:8:559:14 | src_pos | src_pos |
| test.cpp:647:5:647:19 | Store: ... = ... | test.cpp:642:14:642:31 | new[] | test.cpp:647:5:647:19 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:642:14:642:31 | new[] | new[] | test.cpp:647:8:647:14 | src_pos | src_pos |
| test.cpp:662:3:662:11 | Store: ... = ... | test.cpp:652:14:652:27 | new[] | test.cpp:662:3:662:11 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:652:14:652:27 | new[] | new[] | test.cpp:653:19:653:22 | size | size |
| test.cpp:675:7:675:23 | Store: ... = ... | test.cpp:667:14:667:31 | new[] | test.cpp:675:7:675:23 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:667:14:667:31 | new[] | new[] | test.cpp:675:10:675:18 | ... ++ | ... ++ |

View File

@@ -369,7 +369,7 @@ void test26(unsigned size) {
}
if (p < end) {
int val = *p; // GOOD
int val = *p; // GOOD [FALSE POSITIVE]
}
}
@@ -383,295 +383,3 @@ void test27(unsigned size, bool b) {
int val = *end; // BAD
}
void test28(unsigned size) {
char *xs = new char[size];
char *end = &xs[size];
if (xs >= end)
return;
xs++;
if (xs >= end)
return;
xs[0] = 0; // GOOD
}
void test28_simple(unsigned size) {
char *xs = new char[size];
char *end = &xs[size];
if (xs < end) {
xs++;
if (xs < end) {
xs[0] = 0; // GOOD
}
}
}
void test28_simple2(unsigned size) {
char *xs = new char[size];
char *end = &xs[size];
if (xs < end) {
xs++;
if (xs < end + 1) {
xs[0] = 0; // BAD
}
}
}
void test28_simple3(unsigned size) {
char *xs = new char[size];
char *end = &xs[size];
if (xs < end) {
xs++;
if (xs - 1 < end) {
xs[0] = 0; // BAD
}
}
}
void test28_simple4(unsigned size) {
char *xs = new char[size];
char *end = &xs[size];
if (xs < end) {
end++;
xs++;
if (xs < end) {
xs[0] = 0; // BAD
}
}
}
void test28_simple5(unsigned size) {
char *xs = new char[size];
char *end = &xs[size];
end++;
if (xs < end) {
xs++;
if (xs < end) {
xs[0] = 0; // BAD
}
}
}
void test28_simple6(unsigned size) {
char *xs = new char[size + 1];
char *end = &xs[size];
end++;
if (xs < end) {
xs++;
if (xs < end) {
xs[0] = 0; // GOOD
}
}
}
void test28_simple7(unsigned size) {
char *xs = new char[size];
char *end = &xs[size];
end++;
if (xs < end) {
xs++;
if (xs < end - 1) {
xs[0] = 0; // GOOD
}
}
}
void test28_simple8(unsigned size) {
char *xs = new char[size];
char *end = &xs[size];
end += 500;
if (xs < end) {
xs++;
if (xs < end - 1) {
xs[0] = 0; // BAD
}
}
}
struct test29_struct {
char* xs;
};
void test29(unsigned size) {
test29_struct val;
val.xs = new char[size];
size++;
val.xs = new char[size];
val.xs[size - 1] = 0; // GOOD
}
void test30(int *size)
{
int new_size = 0, tmp_size = 0;
test30(&tmp_size);
if (tmp_size + 1 > new_size) {
new_size = tmp_size + 1;
char *xs = new char[new_size];
for (int i = 0; i < new_size; i++) {
xs[i] = 0; // GOOD
}
}
*size = new_size;
}
void test31(unsigned size, unsigned src_pos)
{
char *xs = new char[size];
if (src_pos > size) {
src_pos = size;
}
unsigned dst_pos = src_pos;
if (dst_pos < size - 3) {
xs[dst_pos++] = 0; // GOOD
}
}
void test31_simple1(unsigned size, unsigned src_pos)
{
char *xs = new char[size];
if (src_pos > size) {
src_pos = size;
}
if (src_pos < size) {
xs[src_pos] = 0; // GOOD
}
}
void test31_simple2(unsigned size, unsigned src_pos)
{
char *xs = new char[size];
if (src_pos > size) {
src_pos = size;
}
if (src_pos < size + 1) {
xs[src_pos] = 0; // BAD
}
}
void test31_simple3(unsigned size, unsigned src_pos)
{
char *xs = new char[size];
if (src_pos > size) {
src_pos = size;
}
if (src_pos - 1 < size) {
xs[src_pos] = 0; // BAD
}
}
void test31_simple4(unsigned size, unsigned src_pos)
{
char *xs = new char[size];
if (src_pos > size) {
src_pos = size;
}
if (src_pos < size - 1) {
xs[src_pos] = 0; // GOOD
}
}
void test31_simple5(unsigned size, unsigned src_pos)
{
char *xs = new char[size];
if (src_pos > size) {
src_pos = size;
}
if (src_pos + 1 < size) {
xs[src_pos] = 0; // GOOD
}
}
void test31_simple1_plus1(unsigned size, unsigned src_pos)
{
char *xs = new char[size + 1];
if (src_pos > size) {
src_pos = size;
}
if (src_pos < size) {
xs[src_pos] = 0; // GOOD
}
}
void test31_simple2_plus1(unsigned size, unsigned src_pos)
{
char *xs = new char[size + 1];
if (src_pos > size) {
src_pos = size;
}
if (src_pos < size + 1) {
xs[src_pos] = 0; // GOOD
}
}
void test31_simple3_plus1(unsigned size, unsigned src_pos)
{
char *xs = new char[size + 1];
if (src_pos > size) {
src_pos = size;
}
if (src_pos - 1 < size) {
xs[src_pos] = 0; // GOOD
}
}
void test31_simple4_plus1(unsigned size, unsigned src_pos)
{
char *xs = new char[size + 1];
if (src_pos > size) {
src_pos = size;
}
if (src_pos < size - 1) {
xs[src_pos] = 0; // GOOD
}
}
void test31_simple5_plus1(unsigned size, unsigned src_pos)
{
char *xs = new char[size + 1];
if (src_pos > size) {
src_pos = size;
}
if (src_pos + 1 < size) {
xs[src_pos] = 0; // GOOD
}
}
void test31_simple1_sub1(unsigned size, unsigned src_pos)
{
char *xs = new char[size - 1];
if (src_pos > size) {
src_pos = size;
}
if (src_pos < size) {
xs[src_pos] = 0; // BAD
}
}
void test32(unsigned size) {
char *xs = new char[size];
char *end = &xs[size];
if (xs >= end)
return;
xs++;
if (xs >= end)
return;
xs++;
if (xs >= end)
return;
xs[0] = 0; // GOOD [FALSE POSITIVE]
}
void test33(unsigned size, unsigned src_pos)
{
char *xs = new char[size + 1];
if (src_pos > size) {
src_pos = size;
}
unsigned dst_pos = src_pos;
while (dst_pos < size - 1) {
dst_pos++;
if (true)
xs[dst_pos++] = 0; // GOOD [FALSE POSITIVE]
}
}

View File

@@ -151,19 +151,3 @@ void test5(int x) {
void test6(int x, int y) {
return x && y;
}
int ptr_test(int *x, int *y) {
if (x == y + 42) {
}
if (x == y - 42) {
}
if (x < y + 42) {
}
if (x < y - 42) {
}
return 0;
}

View File

@@ -30,10 +30,6 @@ astGuards
| test.c:152:10:152:10 | x |
| test.c:152:10:152:15 | ... && ... |
| test.c:152:15:152:15 | y |
| test.c:156:9:156:19 | ... == ... |
| test.c:159:9:159:19 | ... == ... |
| test.c:162:9:162:18 | ... < ... |
| test.c:165:9:165:18 | ... < ... |
| test.cpp:18:8:18:10 | call to get |
| test.cpp:31:7:31:13 | ... == ... |
| test.cpp:42:13:42:20 | call to getABool |
@@ -126,38 +122,6 @@ astGuardsCompare
| 109 | y < 0+0 when ... < ... is true |
| 109 | y >= 0+0 when ... < ... is false |
| 109 | y >= 0+0 when ... \|\| ... is false |
| 156 | ... + ... != x+0 when ... == ... is false |
| 156 | ... + ... == x+0 when ... == ... is true |
| 156 | x != ... + ...+0 when ... == ... is false |
| 156 | x != y+42 when ... == ... is false |
| 156 | x == ... + ...+0 when ... == ... is true |
| 156 | x == y+42 when ... == ... is true |
| 156 | y != x+-42 when ... == ... is false |
| 156 | y == x+-42 when ... == ... is true |
| 159 | ... - ... != x+0 when ... == ... is false |
| 159 | ... - ... == x+0 when ... == ... is true |
| 159 | x != ... - ...+0 when ... == ... is false |
| 159 | x != y+-42 when ... == ... is false |
| 159 | x == ... - ...+0 when ... == ... is true |
| 159 | x == y+-42 when ... == ... is true |
| 159 | y != x+42 when ... == ... is false |
| 159 | y == x+42 when ... == ... is true |
| 162 | ... + ... < x+1 when ... < ... is false |
| 162 | ... + ... >= x+1 when ... < ... is true |
| 162 | x < ... + ...+0 when ... < ... is true |
| 162 | x < y+42 when ... < ... is true |
| 162 | x >= ... + ...+0 when ... < ... is false |
| 162 | x >= y+42 when ... < ... is false |
| 162 | y < x+-41 when ... < ... is false |
| 162 | y >= x+-41 when ... < ... is true |
| 165 | ... - ... < x+1 when ... < ... is false |
| 165 | ... - ... >= x+1 when ... < ... is true |
| 165 | x < ... - ...+0 when ... < ... is true |
| 165 | x < y+-42 when ... < ... is true |
| 165 | x >= ... - ...+0 when ... < ... is false |
| 165 | x >= y+-42 when ... < ... is false |
| 165 | y < x+43 when ... < ... is false |
| 165 | y >= x+43 when ... < ... is true |
astGuardsControl
| test.c:7:9:7:13 | ... > ... | false | 10 | 11 |
| test.c:7:9:7:13 | ... > ... | true | 7 | 9 |
@@ -244,10 +208,6 @@ astGuardsControl
| test.c:152:10:152:10 | x | true | 152 | 152 |
| test.c:152:10:152:15 | ... && ... | true | 151 | 152 |
| test.c:152:15:152:15 | y | true | 151 | 152 |
| test.c:156:9:156:19 | ... == ... | true | 156 | 157 |
| test.c:159:9:159:19 | ... == ... | true | 159 | 160 |
| test.c:162:9:162:18 | ... < ... | true | 162 | 163 |
| test.c:165:9:165:18 | ... < ... | true | 165 | 166 |
| test.cpp:18:8:18:10 | call to get | true | 19 | 19 |
| test.cpp:31:7:31:13 | ... == ... | false | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | false | 34 | 34 |
@@ -404,22 +364,6 @@ astGuardsEnsure
| test.c:109:9:109:23 | ... \|\| ... | test.c:109:23:109:23 | 0 | < | test.c:109:19:109:19 | y | 1 | 113 | 113 |
| test.c:109:19:109:23 | ... < ... | test.c:109:19:109:19 | y | >= | test.c:109:23:109:23 | 0 | 0 | 113 | 113 |
| test.c:109:19:109:23 | ... < ... | test.c:109:23:109:23 | 0 | < | test.c:109:19:109:19 | y | 1 | 113 | 113 |
| test.c:156:9:156:19 | ... == ... | test.c:156:9:156:9 | x | == | test.c:156:14:156:14 | y | 42 | 156 | 157 |
| test.c:156:9:156:19 | ... == ... | test.c:156:9:156:9 | x | == | test.c:156:14:156:19 | ... + ... | 0 | 156 | 157 |
| test.c:156:9:156:19 | ... == ... | test.c:156:14:156:14 | y | == | test.c:156:9:156:9 | x | -42 | 156 | 157 |
| test.c:156:9:156:19 | ... == ... | test.c:156:14:156:19 | ... + ... | == | test.c:156:9:156:9 | x | 0 | 156 | 157 |
| test.c:159:9:159:19 | ... == ... | test.c:159:9:159:9 | x | == | test.c:159:14:159:14 | y | -42 | 159 | 160 |
| test.c:159:9:159:19 | ... == ... | test.c:159:9:159:9 | x | == | test.c:159:14:159:19 | ... - ... | 0 | 159 | 160 |
| test.c:159:9:159:19 | ... == ... | test.c:159:14:159:14 | y | == | test.c:159:9:159:9 | x | 42 | 159 | 160 |
| test.c:159:9:159:19 | ... == ... | test.c:159:14:159:19 | ... - ... | == | test.c:159:9:159:9 | x | 0 | 159 | 160 |
| test.c:162:9:162:18 | ... < ... | test.c:162:9:162:9 | x | < | test.c:162:13:162:13 | y | 42 | 162 | 163 |
| test.c:162:9:162:18 | ... < ... | test.c:162:9:162:9 | x | < | test.c:162:13:162:18 | ... + ... | 0 | 162 | 163 |
| test.c:162:9:162:18 | ... < ... | test.c:162:13:162:13 | y | >= | test.c:162:9:162:9 | x | -41 | 162 | 163 |
| test.c:162:9:162:18 | ... < ... | test.c:162:13:162:18 | ... + ... | >= | test.c:162:9:162:9 | x | 1 | 162 | 163 |
| test.c:165:9:165:18 | ... < ... | test.c:165:9:165:9 | x | < | test.c:165:13:165:13 | y | -42 | 165 | 166 |
| test.c:165:9:165:18 | ... < ... | test.c:165:9:165:9 | x | < | test.c:165:13:165:18 | ... - ... | 0 | 165 | 166 |
| test.c:165:9:165:18 | ... < ... | test.c:165:13:165:13 | y | >= | test.c:165:9:165:9 | x | 43 | 165 | 166 |
| test.c:165:9:165:18 | ... < ... | test.c:165:13:165:18 | ... - ... | >= | test.c:165:9:165:9 | x | 1 | 165 | 166 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | test.cpp:31:12:31:13 | - ... | 0 | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | test.cpp:31:12:31:13 | - ... | 0 | 34 | 34 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | == | test.cpp:31:12:31:13 | - ... | 0 | 30 | 30 |
@@ -453,10 +397,6 @@ irGuards
| test.c:146:8:146:8 | Load: x |
| test.c:152:10:152:10 | Load: x |
| test.c:152:15:152:15 | Load: y |
| test.c:156:9:156:19 | CompareEQ: ... == ... |
| test.c:159:9:159:19 | CompareEQ: ... == ... |
| test.c:162:9:162:18 | CompareLT: ... < ... |
| test.c:165:9:165:18 | CompareLT: ... < ... |
| test.cpp:18:8:18:12 | CompareNE: (bool)... |
| test.cpp:31:7:31:13 | CompareEQ: ... == ... |
| test.cpp:42:13:42:20 | Call: call to getABool |
@@ -533,38 +473,6 @@ irGuardsCompare
| 109 | x == 0+0 when CompareEQ: ... == ... is true |
| 109 | y < 0+0 when CompareLT: ... < ... is true |
| 109 | y >= 0+0 when CompareLT: ... < ... is false |
| 156 | ... + ... != x+0 when CompareEQ: ... == ... is false |
| 156 | ... + ... == x+0 when CompareEQ: ... == ... is true |
| 156 | x != ... + ...+0 when CompareEQ: ... == ... is false |
| 156 | x != y+42 when CompareEQ: ... == ... is false |
| 156 | x == ... + ...+0 when CompareEQ: ... == ... is true |
| 156 | x == y+42 when CompareEQ: ... == ... is true |
| 156 | y != x+-42 when CompareEQ: ... == ... is false |
| 156 | y == x+-42 when CompareEQ: ... == ... is true |
| 159 | ... - ... != x+0 when CompareEQ: ... == ... is false |
| 159 | ... - ... == x+0 when CompareEQ: ... == ... is true |
| 159 | x != ... - ...+0 when CompareEQ: ... == ... is false |
| 159 | x != y+-42 when CompareEQ: ... == ... is false |
| 159 | x == ... - ...+0 when CompareEQ: ... == ... is true |
| 159 | x == y+-42 when CompareEQ: ... == ... is true |
| 159 | y != x+42 when CompareEQ: ... == ... is false |
| 159 | y == x+42 when CompareEQ: ... == ... is true |
| 162 | ... + ... < x+1 when CompareLT: ... < ... is false |
| 162 | ... + ... >= x+1 when CompareLT: ... < ... is true |
| 162 | x < ... + ...+0 when CompareLT: ... < ... is true |
| 162 | x < y+42 when CompareLT: ... < ... is true |
| 162 | x >= ... + ...+0 when CompareLT: ... < ... is false |
| 162 | x >= y+42 when CompareLT: ... < ... is false |
| 162 | y < x+-41 when CompareLT: ... < ... is false |
| 162 | y >= x+-41 when CompareLT: ... < ... is true |
| 165 | ... - ... < x+1 when CompareLT: ... < ... is false |
| 165 | ... - ... >= x+1 when CompareLT: ... < ... is true |
| 165 | x < ... - ...+0 when CompareLT: ... < ... is true |
| 165 | x < y+-42 when CompareLT: ... < ... is true |
| 165 | x >= ... - ...+0 when CompareLT: ... < ... is false |
| 165 | x >= y+-42 when CompareLT: ... < ... is false |
| 165 | y < x+43 when CompareLT: ... < ... is false |
| 165 | y >= x+43 when CompareLT: ... < ... is true |
irGuardsControl
| test.c:7:9:7:13 | CompareGT: ... > ... | false | 11 | 11 |
| test.c:7:9:7:13 | CompareGT: ... > ... | true | 8 | 8 |
@@ -643,10 +551,6 @@ irGuardsControl
| test.c:146:8:146:8 | Load: x | false | 147 | 147 |
| test.c:152:10:152:10 | Load: x | true | 152 | 152 |
| test.c:152:15:152:15 | Load: y | true | 152 | 152 |
| test.c:156:9:156:19 | CompareEQ: ... == ... | true | 156 | 157 |
| test.c:159:9:159:19 | CompareEQ: ... == ... | true | 159 | 160 |
| test.c:162:9:162:18 | CompareLT: ... < ... | true | 162 | 163 |
| test.c:165:9:165:18 | CompareLT: ... < ... | true | 165 | 166 |
| test.cpp:18:8:18:12 | CompareNE: (bool)... | true | 19 | 19 |
| test.cpp:31:7:31:13 | CompareEQ: ... == ... | false | 34 | 34 |
| test.cpp:31:7:31:13 | CompareEQ: ... == ... | true | 30 | 30 |
@@ -786,22 +690,6 @@ irGuardsEnsure
| test.c:109:9:109:14 | CompareEQ: ... == ... | test.c:109:14:109:14 | Constant: 0 | != | test.c:109:9:109:9 | Load: x | 0 | 113 | 113 |
| test.c:109:19:109:23 | CompareLT: ... < ... | test.c:109:19:109:19 | Load: y | >= | test.c:109:23:109:23 | Constant: (long)... | 0 | 113 | 113 |
| test.c:109:19:109:23 | CompareLT: ... < ... | test.c:109:23:109:23 | Constant: (long)... | < | test.c:109:19:109:19 | Load: y | 1 | 113 | 113 |
| test.c:156:9:156:19 | CompareEQ: ... == ... | test.c:156:9:156:9 | Load: x | == | test.c:156:14:156:14 | Load: y | 42 | 156 | 157 |
| test.c:156:9:156:19 | CompareEQ: ... == ... | test.c:156:9:156:9 | Load: x | == | test.c:156:14:156:19 | PointerAdd: ... + ... | 0 | 156 | 157 |
| test.c:156:9:156:19 | CompareEQ: ... == ... | test.c:156:14:156:14 | Load: y | == | test.c:156:9:156:9 | Load: x | -42 | 156 | 157 |
| test.c:156:9:156:19 | CompareEQ: ... == ... | test.c:156:14:156:19 | PointerAdd: ... + ... | == | test.c:156:9:156:9 | Load: x | 0 | 156 | 157 |
| test.c:159:9:159:19 | CompareEQ: ... == ... | test.c:159:9:159:9 | Load: x | == | test.c:159:14:159:14 | Load: y | -42 | 159 | 160 |
| test.c:159:9:159:19 | CompareEQ: ... == ... | test.c:159:9:159:9 | Load: x | == | test.c:159:14:159:19 | PointerSub: ... - ... | 0 | 159 | 160 |
| test.c:159:9:159:19 | CompareEQ: ... == ... | test.c:159:14:159:14 | Load: y | == | test.c:159:9:159:9 | Load: x | 42 | 159 | 160 |
| test.c:159:9:159:19 | CompareEQ: ... == ... | test.c:159:14:159:19 | PointerSub: ... - ... | == | test.c:159:9:159:9 | Load: x | 0 | 159 | 160 |
| test.c:162:9:162:18 | CompareLT: ... < ... | test.c:162:9:162:9 | Load: x | < | test.c:162:13:162:13 | Load: y | 42 | 162 | 163 |
| test.c:162:9:162:18 | CompareLT: ... < ... | test.c:162:9:162:9 | Load: x | < | test.c:162:13:162:18 | PointerAdd: ... + ... | 0 | 162 | 163 |
| test.c:162:9:162:18 | CompareLT: ... < ... | test.c:162:13:162:13 | Load: y | >= | test.c:162:9:162:9 | Load: x | -41 | 162 | 163 |
| test.c:162:9:162:18 | CompareLT: ... < ... | test.c:162:13:162:18 | PointerAdd: ... + ... | >= | test.c:162:9:162:9 | Load: x | 1 | 162 | 163 |
| test.c:165:9:165:18 | CompareLT: ... < ... | test.c:165:9:165:9 | Load: x | < | test.c:165:13:165:13 | Load: y | -42 | 165 | 166 |
| test.c:165:9:165:18 | CompareLT: ... < ... | test.c:165:9:165:9 | Load: x | < | test.c:165:13:165:18 | PointerSub: ... - ... | 0 | 165 | 166 |
| test.c:165:9:165:18 | CompareLT: ... < ... | test.c:165:13:165:13 | Load: y | >= | test.c:165:9:165:9 | Load: x | 43 | 165 | 166 |
| test.c:165:9:165:18 | CompareLT: ... < ... | test.c:165:13:165:18 | PointerSub: ... - ... | >= | test.c:165:9:165:9 | Load: x | 1 | 165 | 166 |
| test.cpp:18:8:18:12 | CompareNE: (bool)... | test.cpp:18:8:18:10 | Call: call to get | != | test.cpp:18:8:18:12 | Constant: (bool)... | 0 | 19 | 19 |
| test.cpp:18:8:18:12 | CompareNE: (bool)... | test.cpp:18:8:18:12 | Constant: (bool)... | != | test.cpp:18:8:18:10 | Call: call to get | 0 | 19 | 19 |
| test.cpp:31:7:31:13 | CompareEQ: ... == ... | test.cpp:31:7:31:7 | Load: x | != | test.cpp:31:12:31:13 | Constant: - ... | 0 | 34 | 34 |

View File

@@ -67,8 +67,6 @@ postWithInFlow
| ref.cpp:109:9:109:11 | val [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:113:11:113:13 | val [post update] | PostUpdateNode should not be the target of local flow. |
| ref.cpp:115:11:115:13 | val [post update] | PostUpdateNode should not be the target of local flow. |
| self_parameter_flow.cpp:3:4:3:5 | ps [inner post update] | PostUpdateNode should not be the target of local flow. |
| self_parameter_flow.cpp:8:9:8:9 | s [inner post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:91:3:91:9 | source1 [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:115:3:115:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:115:4:115:6 | out [inner post update] | PostUpdateNode should not be the target of local flow. |
@@ -130,10 +128,6 @@ postWithInFlow
| test.cpp:690:3:690:3 | s [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:694:4:694:6 | buf [inner post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:704:23:704:25 | buf [inner post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:715:25:715:25 | c [inner post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:728:3:728:4 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:728:4:728:4 | p [inner post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:734:41:734:41 | x [inner post update] | PostUpdateNode should not be the target of local flow. |
viableImplInCallContextTooLarge
uniqueParameterNodeAtPosition
uniqueParameterNodePosition

View File

@@ -1,21 +0,0 @@
#include "../../../include/iterator.h"
int source();
template<typename T>
void sink(T);
template<> struct std::iterator_traits<unsigned long>
{ // get traits from integer type
typedef std::input_iterator_tag iterator_category;
typedef unsigned long value_type;
typedef unsigned long difference_type;
typedef unsigned long distance_type;
typedef unsigned long * pointer;
typedef unsigned long& reference;
};
int test() {
unsigned long x = source();
sink(x); // $ ast ir
}

View File

@@ -1,14 +0,0 @@
void incr(unsigned char **ps) // $ ast-def=ps ir-def=*ps ir-def=**ps
{
*ps += 1;
}
void callincr(unsigned char *s) // $ ast-def=s
{
incr(&s);
}
void test(unsigned char *s) // $ ast-def=s
{
callincr(s); // $ flow
}

View File

@@ -702,90 +702,4 @@ void call_increment_buf(int** buf) { // $ ast-def=buf
void test_conflation_regression(int* source) { // $ ast-def=source
int* buf = source;
call_increment_buf(&buf);
}
void write_to_star_star_p(unsigned char **p) // $ ast-def=p ir-def=**p ir-def=*p
{
**p = 0;
}
void write_to_star_buf(unsigned char *buf) // $ ast-def=buf
{
unsigned char *c = buf;
write_to_star_star_p(&c);
}
void test_write_to_star_buf(unsigned char *source) // $ ast-def=source
{
write_to_star_buf(source);
sink(*source); // clean
}
void does_not_write_source_to_dereference(int *p) // $ ast-def=p ir-def=*p
{
int x = source();
p = &x;
*p = 42;
}
void test_does_not_write_source_to_dereference()
{
int x;
does_not_write_source_to_dereference(&x);
sink(x); // $ ast,ir=733:7 SPURIOUS: ast,ir=726:11
}
void sometimes_calls_sink_eq(int x, int n) {
if(n == 0) {
sink(x); // $ ast,ir=751:27 ast,ir=755:32 SPURIOUS: ast=749:27 ast,ir=753:32 // IR spurious results because we only have call contexts of depth 1
}
}
void call_sometimes_calls_sink_eq(int x, int n) {
sometimes_calls_sink_eq(x, n);
}
void test_sometimes_calls_sink_eq_1() {
sometimes_calls_sink_eq(source(), 1);
sometimes_calls_sink_eq(0, 0);
sometimes_calls_sink_eq(source(), 0);
call_sometimes_calls_sink_eq(source(), 1);
call_sometimes_calls_sink_eq(0, 0);
call_sometimes_calls_sink_eq(source(), 0);
}
void sometimes_calls_sink_lt(int x, int n) {
if(n < 10) {
sink(x); // $ ast,ir=771:27 ast,ir=775:32 SPURIOUS: ast=769:27 ast,ir=773:32 // IR spurious results because we only have call contexts of depth 1
}
}
void call_sometimes_calls_sink_lt(int x, int n) {
sometimes_calls_sink_lt(x, n);
}
void test_sometimes_calls_sink_lt() {
sometimes_calls_sink_lt(source(), 10);
sometimes_calls_sink_lt(0, 0);
sometimes_calls_sink_lt(source(), 2);
call_sometimes_calls_sink_lt(source(), 10);
call_sometimes_calls_sink_lt(0, 0);
call_sometimes_calls_sink_lt(source(), 2);
}
void sometimes_calls_sink_switch(int x, int n) {
switch(n) {
case 0:
sink(x); // $ ast,ir=790:31 SPURIOUS: ast,ir=788:31 // IR spurious results because IRGuard doesn't understand switch statements.
break;
}
}
void test_sometimes_calls_sink_switch() {
sometimes_calls_sink_switch(source(), 1);
sometimes_calls_sink_switch(0, 0);
sometimes_calls_sink_switch(source(), 0);
}

View File

@@ -1,34 +0,0 @@
import cpp
import semmle.code.cpp.dataflow.new.DataFlow
import TestUtilities.InlineExpectationsTest
module TestConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.getLocation().getFile().getBaseName() = "self_parameter_flow.cpp" and
source.asIndirectArgument() =
any(Call call | call.getTarget().hasName("callincr")).getAnArgument()
}
predicate isSink(DataFlow::Node sink) {
sink.asDefiningArgument() =
any(Call call | call.getTarget().hasName("callincr")).getAnArgument()
}
}
import DataFlow::Global<TestConfig>
module TestSelfParameterFlow implements TestSig {
string getARelevantTag() { result = "flow" }
predicate hasActualResult(Location location, string element, string tag, string value) {
exists(DataFlow::Node sink |
flowTo(sink) and
location = sink.getLocation() and
element = sink.toString() and
tag = "flow" and
value = ""
)
}
}
import MakeTest<TestSelfParameterFlow>

View File

@@ -42,5 +42,3 @@
| test.cpp:551:9:551:9 | y | test.cpp:552:28:552:28 | y |
| test.cpp:595:8:595:9 | xs | test.cpp:596:3:596:4 | xs |
| test.cpp:595:8:595:9 | xs | test.cpp:597:9:597:10 | xs |
| test.cpp:733:7:733:7 | x | test.cpp:734:41:734:41 | x |
| test.cpp:733:7:733:7 | x | test.cpp:735:8:735:8 | x |

View File

@@ -1,182 +0,0 @@
// We want a source of user input that can be both a pointer and a non-pointer. So we
// hack the testing a bit by providing an overload that takes a boolean to distinguish
// between the two while still satisfying the test requirement that the function must
// be named `user_input`.
int user_input();
int* user_input(bool);
void sink(...);
void argument_source(int*);
struct S {
int** x;
};
void test()
{
{
S s;
**s.x = user_input();
*s.x = 0;
sink(**s.x); // clean, as *s.x was overwritten and that contains the tainted **s.x
}
{
S s;
**s.x = user_input();
**s.x = 0;
sink(**s.x); // clean, as **s.x was overwritten and tainted
}
{
S s;
*s.x = user_input(true);
**s.x = 0;
sink(*s.x); // $ ir // not clean, as **s.x was overwritten and is neither equal nor contains the tainted *s.x
}
{
S s;
*s.x = user_input(true);
s.x = 0;
sink(*s.x); // clean, as s.x was overwritten and contains the tainted *s.x
}
{
S s;
**s.x = user_input();
s.x = 0;
sink(*s.x); // clean, as s.x was overwritten and contains the tainted **s.x
}
{
S s;
*s.x = user_input(true);
s.x++;
sink(s.x); // $ SPURIOUS: ir ast // Cannot tell the difference with the whole array being tainted
}
{
S s;
**s.x = user_input();
s.x++;
sink(s.x); // $ SPURIOUS: ir // Cannot tell the difference with the whole array being tainted
}
}
struct S2
{
int* val;
};
void test_uncertain_write_is_not_clear()
{
S2 s;
argument_source(s.val);
s.val[10] = 0;
sink(*s.val); // $ ir MISSING: ast // not clean, as all elements of s.val are tainted and only one is overwitten
}
void test_indirection_should_not_be_cleared_with_write_1() {
S2 s;
argument_source(s.val); // *s.val is tainted
s.val[0] = 0;
s.val = s.val + 1;
sink(*s.val); // $ ir MISSING: ast // not clean, as all elements of s.val are tainted, only one if overwritten, and the updated pointer still points to tainted elements
}
void test_indirection_should_not_be_cleared_with_write_2() {
S2 s;
argument_source(s.val); // *s.val is tainted
*s.val++ = 0;
sink(*s.val); // $ ir MISSING: ast // not clean, as all elements of s.val are tainted, only one if overwritten, and the updated pointer still points to tainted elements
}
void test_indirection_should_not_be_cleared_without_write_1() {
S2 s;
argument_source(s.val); // *s.val is tainted
s.val = s.val + 1;
sink(*s.val); // $ ir MISSING: ast // not clean, as all elements of s.val are tainted and the updated pointer still points to tainted elements
}
void test_indirection_should_not_be_cleared_without_write_2() {
S2 s;
argument_source(s.val); // *s.val is tainted
s.val++;
sink(*s.val); // $ ir MISSING: ast // not clean, as all elements of s.val are tainted and the updated pointer still points to tainted elements
}
void test_indirection_should_not_be_cleared_without_write_3() {
S2 s;
argument_source(s.val); // *s.val is tainted
++s.val;
sink(*s.val); // $ ir MISSING: ast // not clean as the pointer is only moved to the next tainted element
}
void test_indirection_should_not_be_cleared_without_write_4() {
S2 s;
argument_source(s.val); // *s.val is tainted
s.val += 1;
sink(*s.val); // $ ir MISSING: ast // not clean as the pointer is only moved to the next tainted element
}
void test_direct_should_be_cleared() {
S2 s;
s.val = user_input(true); // s.val is tainted
s.val += 1;
sink(s.val); // $ SPURIOUS: ast // clean, as s.val was overwritten and tainted
}
void test_direct_should_be_cleared_post() {
S2 s;
s.val = user_input(true); // s.val is tainted
s.val++;
sink(s.val); // $ SPURIOUS: ast // clean, as s.val was overwritten and tainted
}
void test_direct_should_be_cleared_pre() {
S2 s;
s.val = user_input(true); // s.val is tainted
++s.val;
sink(s.val); // $ SPURIOUS: ast // // clean, as s.x was overwritten and tainted
}
struct S3
{
int val;
};
void test_direct() {
{
S3 s;
s.val = user_input();
sink(s.val); // $ ir ast
}
{
S3 s;
s.val = user_input();
s.val = 0;
sink(s.val); // $ SPURIOUS: ast // clean
}
{
S3 s;
s.val = user_input();
s.val++;
sink(s.val); // $ SPURIOUS: ast // clean
}
{
S3 s;
s.val = user_input();
s.val += 1;
sink(s.val); // $ SPURIOUS: ast // clean
}
{
S3 s;
s.val = user_input();
s.val = s.val + 1;
sink(s.val); // $ SPURIOUS: ast // clean
}
}

View File

@@ -43,9 +43,6 @@ argHasPostUpdate
| arrays.cpp:10:8:10:15 | * ... | ArgumentNode is missing PostUpdateNode. |
| arrays.cpp:16:8:16:13 | access to array | ArgumentNode is missing PostUpdateNode. |
| arrays.cpp:17:8:17:13 | access to array | ArgumentNode is missing PostUpdateNode. |
| clearning.cpp:34:8:34:11 | * ... | ArgumentNode is missing PostUpdateNode. |
| clearning.cpp:41:8:41:11 | * ... | ArgumentNode is missing PostUpdateNode. |
| clearning.cpp:48:8:48:11 | * ... | ArgumentNode is missing PostUpdateNode. |
postWithInFlow
| A.cpp:25:13:25:13 | c [post update] | PostUpdateNode should not be the target of local flow. |
| A.cpp:27:28:27:28 | c [post update] | PostUpdateNode should not be the target of local flow. |
@@ -126,32 +123,6 @@ postWithInFlow
| by_reference.cpp:108:24:108:24 | a [inner post update] | PostUpdateNode should not be the target of local flow. |
| by_reference.cpp:123:28:123:36 | inner_ptr [inner post update] | PostUpdateNode should not be the target of local flow. |
| by_reference.cpp:127:30:127:38 | inner_ptr [inner post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:19:3:19:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:19:6:19:6 | x [inner post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:32:3:32:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:32:6:32:6 | x [inner post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:39:3:39:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:39:6:39:6 | x [inner post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:40:5:40:5 | x [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:47:5:47:5 | x [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:53:3:53:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:53:6:53:6 | x [inner post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:75:2:75:10 | access to array [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:75:4:75:6 | val [inner post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:82:2:82:9 | access to array [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:82:4:82:6 | val [inner post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:83:7:83:9 | val [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:97:4:97:6 | val [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:124:4:124:6 | val [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:131:4:131:6 | val [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:138:4:138:6 | val [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:151:5:151:7 | val [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:157:5:157:7 | val [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:158:5:158:7 | val [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:164:5:164:7 | val [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:171:5:171:7 | val [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:178:5:178:7 | val [post update] | PostUpdateNode should not be the target of local flow. |
| clearning.cpp:179:5:179:7 | val [post update] | PostUpdateNode should not be the target of local flow. |
| complex.cpp:11:22:11:23 | a_ [post update] | PostUpdateNode should not be the target of local flow. |
| complex.cpp:12:22:12:23 | b_ [post update] | PostUpdateNode should not be the target of local flow. |
| conflated.cpp:10:3:10:7 | * ... [post update] | PostUpdateNode should not be the target of local flow. |

View File

@@ -19,17 +19,6 @@ uniquePostUpdate
| aliasing.cpp:77:11:77:11 | definition of w indirection | Node has multiple PostUpdateNodes. |
| aliasing.cpp:84:11:84:11 | definition of w indirection | Node has multiple PostUpdateNodes. |
| aliasing.cpp:91:11:91:11 | definition of w indirection | Node has multiple PostUpdateNodes. |
| clearning.cpp:54:3:54:3 | s indirection | Node has multiple PostUpdateNodes. |
| clearning.cpp:61:3:61:3 | s indirection | Node has multiple PostUpdateNodes. |
| clearning.cpp:90:3:90:3 | s indirection | Node has multiple PostUpdateNodes. |
| clearning.cpp:104:2:104:2 | s indirection | Node has multiple PostUpdateNodes. |
| clearning.cpp:111:4:111:4 | s indirection | Node has multiple PostUpdateNodes. |
| clearning.cpp:118:2:118:2 | s indirection | Node has multiple PostUpdateNodes. |
| clearning.cpp:125:2:125:2 | s indirection | Node has multiple PostUpdateNodes. |
| clearning.cpp:132:2:132:2 | s indirection | Node has multiple PostUpdateNodes. |
| clearning.cpp:139:4:139:4 | s indirection | Node has multiple PostUpdateNodes. |
| clearning.cpp:165:3:165:3 | s indirection | Node has multiple PostUpdateNodes. |
| clearning.cpp:172:3:172:3 | s indirection | Node has multiple PostUpdateNodes. |
| complex.cpp:22:3:22:5 | this indirection | Node has multiple PostUpdateNodes. |
| complex.cpp:25:7:25:7 | this indirection | Node has multiple PostUpdateNodes. |
| complex.cpp:42:10:42:14 | inner indirection | Node has multiple PostUpdateNodes. |

View File

@@ -572,136 +572,6 @@ edges
| by_reference.cpp:136:8:136:13 | pouter indirection [a] | by_reference.cpp:136:16:136:16 | a |
| by_reference.cpp:136:8:136:13 | pouter indirection [a] | by_reference.cpp:136:16:136:16 | a indirection |
| by_reference.cpp:136:16:136:16 | a indirection | by_reference.cpp:136:16:136:16 | a |
| clearning.cpp:32:3:32:25 | ... = ... | clearning.cpp:32:6:32:6 | s indirection [post update] [x indirection] |
| clearning.cpp:32:6:32:6 | s indirection [post update] [x indirection] | clearning.cpp:33:5:33:5 | s indirection [x indirection] |
| clearning.cpp:32:10:32:19 | call to user_input | clearning.cpp:32:3:32:25 | ... = ... |
| clearning.cpp:33:5:33:5 | s indirection [x indirection] | clearning.cpp:34:9:34:9 | s indirection [x indirection] |
| clearning.cpp:34:9:34:9 | s indirection [x indirection] | clearning.cpp:34:8:34:11 | * ... |
| clearning.cpp:34:9:34:9 | s indirection [x indirection] | clearning.cpp:34:11:34:11 | x indirection |
| clearning.cpp:34:9:34:9 | s indirection [x indirection] | clearning.cpp:34:11:34:11 | x indirection |
| clearning.cpp:34:11:34:11 | x indirection | clearning.cpp:34:8:34:11 | * ... |
| clearning.cpp:34:11:34:11 | x indirection | clearning.cpp:34:8:34:11 | * ... |
| clearning.cpp:53:3:53:25 | ... = ... | clearning.cpp:53:6:53:6 | s indirection [post update] [x indirection] |
| clearning.cpp:53:6:53:6 | s indirection [post update] [x indirection] | clearning.cpp:54:3:54:3 | s indirection [x indirection] |
| clearning.cpp:53:10:53:19 | call to user_input | clearning.cpp:53:3:53:25 | ... = ... |
| clearning.cpp:54:3:54:3 | s indirection [x indirection] | clearning.cpp:54:3:54:7 | ... ++ indirection |
| clearning.cpp:54:3:54:3 | s indirection [x indirection] | clearning.cpp:54:5:54:5 | x indirection |
| clearning.cpp:54:3:54:3 | s indirection [x indirection] | clearning.cpp:55:8:55:8 | s indirection [x indirection] |
| clearning.cpp:54:3:54:7 | ... ++ indirection | clearning.cpp:54:3:54:7 | ... ++ indirection |
| clearning.cpp:54:3:54:7 | ... ++ indirection | clearning.cpp:54:5:54:5 | s indirection [post update] [x indirection] |
| clearning.cpp:54:5:54:5 | s indirection [post update] [x indirection] | clearning.cpp:55:8:55:8 | s indirection [x indirection] |
| clearning.cpp:54:5:54:5 | x indirection | clearning.cpp:54:3:54:7 | ... ++ indirection |
| clearning.cpp:55:8:55:8 | s indirection [x indirection] | clearning.cpp:55:10:55:10 | x indirection |
| clearning.cpp:55:8:55:8 | s indirection [x indirection] | clearning.cpp:55:10:55:10 | x indirection |
| clearning.cpp:55:10:55:10 | x indirection | clearning.cpp:55:10:55:10 | x indirection |
| clearning.cpp:60:3:60:22 | ... = ... | clearning.cpp:60:7:60:7 | s indirection [post update] [x indirection] |
| clearning.cpp:60:7:60:7 | s indirection [post update] [x indirection] | clearning.cpp:61:3:61:3 | s indirection [x indirection] |
| clearning.cpp:60:11:60:20 | call to user_input | clearning.cpp:60:3:60:22 | ... = ... |
| clearning.cpp:61:3:61:3 | s indirection [x indirection] | clearning.cpp:61:3:61:7 | ... ++ indirection |
| clearning.cpp:61:3:61:3 | s indirection [x indirection] | clearning.cpp:61:5:61:5 | x indirection |
| clearning.cpp:61:3:61:3 | s indirection [x indirection] | clearning.cpp:62:8:62:8 | s indirection [x indirection] |
| clearning.cpp:61:3:61:7 | ... ++ indirection | clearning.cpp:61:3:61:7 | ... ++ indirection |
| clearning.cpp:61:3:61:7 | ... ++ indirection | clearning.cpp:61:5:61:5 | s indirection [post update] [x indirection] |
| clearning.cpp:61:5:61:5 | s indirection [post update] [x indirection] | clearning.cpp:62:8:62:8 | s indirection [x indirection] |
| clearning.cpp:61:5:61:5 | x indirection | clearning.cpp:61:3:61:7 | ... ++ indirection |
| clearning.cpp:62:8:62:8 | s indirection [x indirection] | clearning.cpp:62:10:62:10 | x indirection |
| clearning.cpp:62:8:62:8 | s indirection [x indirection] | clearning.cpp:62:10:62:10 | x indirection |
| clearning.cpp:62:10:62:10 | x indirection | clearning.cpp:62:10:62:10 | x indirection |
| clearning.cpp:74:20:74:22 | argument_source output argument | clearning.cpp:74:20:74:22 | s indirection [post update] [val indirection] |
| clearning.cpp:74:20:74:22 | s indirection [post update] [val indirection] | clearning.cpp:76:8:76:8 | s indirection [val indirection] |
| clearning.cpp:76:8:76:8 | s indirection [val indirection] | clearning.cpp:76:7:76:12 | * ... |
| clearning.cpp:76:8:76:8 | s indirection [val indirection] | clearning.cpp:76:10:76:12 | val indirection |
| clearning.cpp:76:8:76:8 | s indirection [val indirection] | clearning.cpp:76:10:76:12 | val indirection |
| clearning.cpp:76:10:76:12 | val indirection | clearning.cpp:76:7:76:12 | * ... |
| clearning.cpp:76:10:76:12 | val indirection | clearning.cpp:76:7:76:12 | * ... |
| clearning.cpp:81:20:81:22 | argument_source output argument | clearning.cpp:81:20:81:22 | s indirection [post update] [val indirection] |
| clearning.cpp:81:20:81:22 | s indirection [post update] [val indirection] | clearning.cpp:83:13:83:13 | s indirection [val indirection] |
| clearning.cpp:83:5:83:21 | ... = ... indirection | clearning.cpp:83:7:83:9 | s indirection [post update] [val indirection] |
| clearning.cpp:83:7:83:9 | s indirection [post update] [val indirection] | clearning.cpp:84:8:84:8 | s indirection [val indirection] |
| clearning.cpp:83:13:83:13 | s indirection [val indirection] | clearning.cpp:83:13:83:21 | ... + ... indirection |
| clearning.cpp:83:13:83:13 | s indirection [val indirection] | clearning.cpp:83:15:83:17 | val indirection |
| clearning.cpp:83:13:83:21 | ... + ... indirection | clearning.cpp:83:5:83:21 | ... = ... indirection |
| clearning.cpp:83:15:83:17 | val indirection | clearning.cpp:83:5:83:21 | ... = ... indirection |
| clearning.cpp:84:8:84:8 | s indirection [val indirection] | clearning.cpp:84:7:84:12 | * ... |
| clearning.cpp:84:8:84:8 | s indirection [val indirection] | clearning.cpp:84:10:84:12 | val indirection |
| clearning.cpp:84:8:84:8 | s indirection [val indirection] | clearning.cpp:84:10:84:12 | val indirection |
| clearning.cpp:84:10:84:12 | val indirection | clearning.cpp:84:7:84:12 | * ... |
| clearning.cpp:84:10:84:12 | val indirection | clearning.cpp:84:7:84:12 | * ... |
| clearning.cpp:89:20:89:22 | argument_source output argument | clearning.cpp:89:20:89:22 | s indirection [post update] [val indirection] |
| clearning.cpp:89:20:89:22 | s indirection [post update] [val indirection] | clearning.cpp:90:3:90:3 | s indirection [val indirection] |
| clearning.cpp:90:3:90:3 | s indirection [val indirection] | clearning.cpp:90:3:90:9 | ... ++ indirection |
| clearning.cpp:90:3:90:3 | s indirection [val indirection] | clearning.cpp:90:5:90:7 | val indirection |
| clearning.cpp:90:3:90:3 | s indirection [val indirection] | clearning.cpp:91:8:91:8 | s indirection [val indirection] |
| clearning.cpp:90:3:90:9 | ... ++ indirection | clearning.cpp:90:3:90:9 | ... ++ indirection |
| clearning.cpp:90:3:90:9 | ... ++ indirection | clearning.cpp:90:5:90:7 | s indirection [post update] [val indirection] |
| clearning.cpp:90:5:90:7 | s indirection [post update] [val indirection] | clearning.cpp:91:8:91:8 | s indirection [val indirection] |
| clearning.cpp:90:5:90:7 | val indirection | clearning.cpp:90:3:90:9 | ... ++ indirection |
| clearning.cpp:91:8:91:8 | s indirection [val indirection] | clearning.cpp:91:7:91:12 | * ... |
| clearning.cpp:91:8:91:8 | s indirection [val indirection] | clearning.cpp:91:10:91:12 | val indirection |
| clearning.cpp:91:8:91:8 | s indirection [val indirection] | clearning.cpp:91:10:91:12 | val indirection |
| clearning.cpp:91:10:91:12 | val indirection | clearning.cpp:91:7:91:12 | * ... |
| clearning.cpp:91:10:91:12 | val indirection | clearning.cpp:91:7:91:12 | * ... |
| clearning.cpp:96:20:96:22 | argument_source output argument | clearning.cpp:96:20:96:22 | s indirection [post update] [val indirection] |
| clearning.cpp:96:20:96:22 | s indirection [post update] [val indirection] | clearning.cpp:97:10:97:10 | s indirection [val indirection] |
| clearning.cpp:97:2:97:18 | ... = ... indirection | clearning.cpp:97:4:97:6 | s indirection [post update] [val indirection] |
| clearning.cpp:97:4:97:6 | s indirection [post update] [val indirection] | clearning.cpp:98:8:98:8 | s indirection [val indirection] |
| clearning.cpp:97:10:97:10 | s indirection [val indirection] | clearning.cpp:97:10:97:18 | ... + ... indirection |
| clearning.cpp:97:10:97:10 | s indirection [val indirection] | clearning.cpp:97:12:97:14 | val indirection |
| clearning.cpp:97:10:97:18 | ... + ... indirection | clearning.cpp:97:2:97:18 | ... = ... indirection |
| clearning.cpp:97:12:97:14 | val indirection | clearning.cpp:97:2:97:18 | ... = ... indirection |
| clearning.cpp:98:8:98:8 | s indirection [val indirection] | clearning.cpp:98:7:98:12 | * ... |
| clearning.cpp:98:8:98:8 | s indirection [val indirection] | clearning.cpp:98:10:98:12 | val indirection |
| clearning.cpp:98:8:98:8 | s indirection [val indirection] | clearning.cpp:98:10:98:12 | val indirection |
| clearning.cpp:98:10:98:12 | val indirection | clearning.cpp:98:7:98:12 | * ... |
| clearning.cpp:98:10:98:12 | val indirection | clearning.cpp:98:7:98:12 | * ... |
| clearning.cpp:103:20:103:22 | argument_source output argument | clearning.cpp:103:20:103:22 | s indirection [post update] [val indirection] |
| clearning.cpp:103:20:103:22 | s indirection [post update] [val indirection] | clearning.cpp:104:2:104:2 | s indirection [val indirection] |
| clearning.cpp:104:2:104:2 | s indirection [val indirection] | clearning.cpp:104:2:104:8 | ... ++ indirection |
| clearning.cpp:104:2:104:2 | s indirection [val indirection] | clearning.cpp:104:4:104:6 | val indirection |
| clearning.cpp:104:2:104:2 | s indirection [val indirection] | clearning.cpp:105:8:105:8 | s indirection [val indirection] |
| clearning.cpp:104:2:104:8 | ... ++ indirection | clearning.cpp:104:2:104:8 | ... ++ indirection |
| clearning.cpp:104:2:104:8 | ... ++ indirection | clearning.cpp:104:4:104:6 | s indirection [post update] [val indirection] |
| clearning.cpp:104:4:104:6 | s indirection [post update] [val indirection] | clearning.cpp:105:8:105:8 | s indirection [val indirection] |
| clearning.cpp:104:4:104:6 | val indirection | clearning.cpp:104:2:104:8 | ... ++ indirection |
| clearning.cpp:105:8:105:8 | s indirection [val indirection] | clearning.cpp:105:7:105:12 | * ... |
| clearning.cpp:105:8:105:8 | s indirection [val indirection] | clearning.cpp:105:10:105:12 | val indirection |
| clearning.cpp:105:8:105:8 | s indirection [val indirection] | clearning.cpp:105:10:105:12 | val indirection |
| clearning.cpp:105:10:105:12 | val indirection | clearning.cpp:105:7:105:12 | * ... |
| clearning.cpp:105:10:105:12 | val indirection | clearning.cpp:105:7:105:12 | * ... |
| clearning.cpp:110:20:110:22 | argument_source output argument | clearning.cpp:110:20:110:22 | s indirection [post update] [val indirection] |
| clearning.cpp:110:20:110:22 | s indirection [post update] [val indirection] | clearning.cpp:111:4:111:4 | s indirection [val indirection] |
| clearning.cpp:111:2:111:8 | ++ ... indirection | clearning.cpp:111:2:111:8 | ++ ... indirection |
| clearning.cpp:111:2:111:8 | ++ ... indirection | clearning.cpp:111:6:111:8 | s indirection [post update] [val indirection] |
| clearning.cpp:111:4:111:4 | s indirection [val indirection] | clearning.cpp:111:2:111:8 | ++ ... indirection |
| clearning.cpp:111:4:111:4 | s indirection [val indirection] | clearning.cpp:111:6:111:8 | val indirection |
| clearning.cpp:111:4:111:4 | s indirection [val indirection] | clearning.cpp:112:8:112:8 | s indirection [val indirection] |
| clearning.cpp:111:6:111:8 | s indirection [post update] [val indirection] | clearning.cpp:112:8:112:8 | s indirection [val indirection] |
| clearning.cpp:111:6:111:8 | val indirection | clearning.cpp:111:2:111:8 | ++ ... indirection |
| clearning.cpp:112:8:112:8 | s indirection [val indirection] | clearning.cpp:112:7:112:12 | * ... |
| clearning.cpp:112:8:112:8 | s indirection [val indirection] | clearning.cpp:112:10:112:12 | val indirection |
| clearning.cpp:112:8:112:8 | s indirection [val indirection] | clearning.cpp:112:10:112:12 | val indirection |
| clearning.cpp:112:10:112:12 | val indirection | clearning.cpp:112:7:112:12 | * ... |
| clearning.cpp:112:10:112:12 | val indirection | clearning.cpp:112:7:112:12 | * ... |
| clearning.cpp:117:20:117:22 | argument_source output argument | clearning.cpp:117:20:117:22 | s indirection [post update] [val indirection] |
| clearning.cpp:117:20:117:22 | s indirection [post update] [val indirection] | clearning.cpp:118:2:118:2 | s indirection [val indirection] |
| clearning.cpp:118:2:118:2 | s indirection [val indirection] | clearning.cpp:118:2:118:11 | ... += ... indirection |
| clearning.cpp:118:2:118:2 | s indirection [val indirection] | clearning.cpp:118:4:118:6 | val indirection |
| clearning.cpp:118:2:118:2 | s indirection [val indirection] | clearning.cpp:119:8:119:8 | s indirection [val indirection] |
| clearning.cpp:118:2:118:11 | ... += ... indirection | clearning.cpp:118:2:118:11 | ... += ... indirection |
| clearning.cpp:118:2:118:11 | ... += ... indirection | clearning.cpp:118:4:118:6 | s indirection [post update] [val indirection] |
| clearning.cpp:118:4:118:6 | s indirection [post update] [val indirection] | clearning.cpp:119:8:119:8 | s indirection [val indirection] |
| clearning.cpp:118:4:118:6 | val indirection | clearning.cpp:118:2:118:11 | ... += ... indirection |
| clearning.cpp:119:8:119:8 | s indirection [val indirection] | clearning.cpp:119:7:119:12 | * ... |
| clearning.cpp:119:8:119:8 | s indirection [val indirection] | clearning.cpp:119:10:119:12 | val indirection |
| clearning.cpp:119:8:119:8 | s indirection [val indirection] | clearning.cpp:119:10:119:12 | val indirection |
| clearning.cpp:119:10:119:12 | val indirection | clearning.cpp:119:7:119:12 | * ... |
| clearning.cpp:119:10:119:12 | val indirection | clearning.cpp:119:7:119:12 | * ... |
| clearning.cpp:151:3:151:22 | ... = ... | clearning.cpp:151:5:151:7 | s indirection [post update] [val] |
| clearning.cpp:151:5:151:7 | s indirection [post update] [val] | clearning.cpp:152:8:152:8 | s indirection [val] |
| clearning.cpp:151:11:151:20 | call to user_input | clearning.cpp:151:3:151:22 | ... = ... |
| clearning.cpp:152:8:152:8 | s indirection [val] | clearning.cpp:152:10:152:12 | val |
| clearning.cpp:152:8:152:8 | s indirection [val] | clearning.cpp:152:10:152:12 | val indirection |
| clearning.cpp:152:10:152:12 | val indirection | clearning.cpp:152:10:152:12 | val |
| complex.cpp:9:7:9:7 | this indirection [a_] | complex.cpp:9:20:9:21 | this indirection [a_] |
| complex.cpp:9:20:9:21 | a_ | complex.cpp:9:7:9:7 | a indirection |
| complex.cpp:9:20:9:21 | a_ indirection | complex.cpp:9:7:9:7 | a indirection |
@@ -991,20 +861,19 @@ edges
| struct_init.c:15:8:15:9 | ab indirection [a] | struct_init.c:15:12:15:12 | a |
| struct_init.c:15:8:15:9 | ab indirection [a] | struct_init.c:15:12:15:12 | a indirection |
| struct_init.c:15:12:15:12 | a indirection | struct_init.c:15:12:15:12 | a |
| struct_init.c:20:13:20:14 | definition of ab indirection [a] | struct_init.c:22:8:22:9 | ab indirection [a] |
| struct_init.c:20:13:20:14 | definition of ab indirection [a] | struct_init.c:24:10:24:12 | & ... indirection [a] |
| struct_init.c:20:13:20:14 | definition of ab indirection [a] | struct_init.c:28:5:28:7 | & ... indirection [a] |
| struct_init.c:20:17:20:36 | definition of ab indirection [post update] [a] | struct_init.c:20:13:20:14 | definition of ab indirection [a] |
| struct_init.c:20:17:20:36 | definition of ab indirection [post update] [a] | struct_init.c:22:8:22:9 | ab indirection [a] |
| struct_init.c:20:17:20:36 | definition of ab indirection [post update] [a] | struct_init.c:24:10:24:12 | & ... indirection [a] |
| struct_init.c:20:17:20:36 | definition of ab indirection [post update] [a] | struct_init.c:28:5:28:7 | & ... indirection [a] |
| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:20:17:20:36 | definition of ab indirection [post update] [a] |
| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:20:20:20:29 | call to user_input |
| struct_init.c:22:8:22:9 | ab indirection [a] | struct_init.c:22:11:22:11 | a |
| struct_init.c:22:8:22:9 | ab indirection [a] | struct_init.c:22:11:22:11 | a indirection |
| struct_init.c:22:11:22:11 | a indirection | struct_init.c:22:11:22:11 | a |
| struct_init.c:24:10:24:12 | & ... indirection [a] | struct_init.c:14:24:14:25 | ab indirection [a] |
| struct_init.c:26:16:26:20 | definition of outer indirection [nestedAB, a] | struct_init.c:31:8:31:12 | outer indirection [nestedAB, a] |
| struct_init.c:26:16:26:20 | definition of outer indirection [nestedAB, a] | struct_init.c:36:11:36:15 | outer indirection [nestedAB, a] |
| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] | struct_init.c:26:16:26:20 | definition of outer indirection [nestedAB, a] |
| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] | struct_init.c:26:16:26:20 | definition of outer indirection [nestedAB, a] |
| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] | struct_init.c:31:8:31:12 | outer indirection [nestedAB, a] |
| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] | struct_init.c:31:8:31:12 | outer indirection [nestedAB, a] |
| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] | struct_init.c:36:11:36:15 | outer indirection [nestedAB, a] |
| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] | struct_init.c:36:11:36:15 | outer indirection [nestedAB, a] |
| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [pointerAB indirection, a] | struct_init.c:33:8:33:12 | outer indirection [pointerAB indirection, a] |
| struct_init.c:27:5:27:23 | {...} indirection [post update] [a] | struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] |
| struct_init.c:27:5:27:23 | {...} indirection [post update] [a] | struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] |
@@ -1023,8 +892,7 @@ edges
| struct_init.c:33:25:33:25 | a indirection | struct_init.c:33:25:33:25 | a |
| struct_init.c:36:10:36:24 | & ... indirection [a] | struct_init.c:14:24:14:25 | ab indirection [a] |
| struct_init.c:36:11:36:15 | outer indirection [nestedAB, a] | struct_init.c:36:10:36:24 | & ... indirection [a] |
| struct_init.c:40:13:40:14 | definition of ab indirection [a] | struct_init.c:43:5:43:7 | & ... indirection [a] |
| struct_init.c:40:17:40:36 | definition of ab indirection [post update] [a] | struct_init.c:40:13:40:14 | definition of ab indirection [a] |
| struct_init.c:40:17:40:36 | definition of ab indirection [post update] [a] | struct_init.c:43:5:43:7 | & ... indirection [a] |
| struct_init.c:40:20:40:29 | call to user_input | struct_init.c:40:17:40:36 | definition of ab indirection [post update] [a] |
| struct_init.c:40:20:40:29 | call to user_input | struct_init.c:40:20:40:29 | call to user_input |
| struct_init.c:41:23:44:3 | definition of outer indirection [post update] [pointerAB indirection, a] | struct_init.c:46:10:46:14 | outer indirection [pointerAB indirection, a] |
@@ -1565,114 +1433,6 @@ nodes
| by_reference.cpp:136:8:136:13 | pouter indirection [a] | semmle.label | pouter indirection [a] |
| by_reference.cpp:136:16:136:16 | a | semmle.label | a |
| by_reference.cpp:136:16:136:16 | a indirection | semmle.label | a indirection |
| clearning.cpp:32:3:32:25 | ... = ... | semmle.label | ... = ... |
| clearning.cpp:32:6:32:6 | s indirection [post update] [x indirection] | semmle.label | s indirection [post update] [x indirection] |
| clearning.cpp:32:10:32:19 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:33:5:33:5 | s indirection [x indirection] | semmle.label | s indirection [x indirection] |
| clearning.cpp:34:8:34:11 | * ... | semmle.label | * ... |
| clearning.cpp:34:9:34:9 | s indirection [x indirection] | semmle.label | s indirection [x indirection] |
| clearning.cpp:34:11:34:11 | x indirection | semmle.label | x indirection |
| clearning.cpp:34:11:34:11 | x indirection | semmle.label | x indirection |
| clearning.cpp:53:3:53:25 | ... = ... | semmle.label | ... = ... |
| clearning.cpp:53:6:53:6 | s indirection [post update] [x indirection] | semmle.label | s indirection [post update] [x indirection] |
| clearning.cpp:53:10:53:19 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:54:3:54:3 | s indirection [x indirection] | semmle.label | s indirection [x indirection] |
| clearning.cpp:54:3:54:7 | ... ++ indirection | semmle.label | ... ++ indirection |
| clearning.cpp:54:3:54:7 | ... ++ indirection | semmle.label | ... ++ indirection |
| clearning.cpp:54:5:54:5 | s indirection [post update] [x indirection] | semmle.label | s indirection [post update] [x indirection] |
| clearning.cpp:54:5:54:5 | x indirection | semmle.label | x indirection |
| clearning.cpp:55:8:55:8 | s indirection [x indirection] | semmle.label | s indirection [x indirection] |
| clearning.cpp:55:10:55:10 | x indirection | semmle.label | x indirection |
| clearning.cpp:55:10:55:10 | x indirection | semmle.label | x indirection |
| clearning.cpp:60:3:60:22 | ... = ... | semmle.label | ... = ... |
| clearning.cpp:60:7:60:7 | s indirection [post update] [x indirection] | semmle.label | s indirection [post update] [x indirection] |
| clearning.cpp:60:11:60:20 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:61:3:61:3 | s indirection [x indirection] | semmle.label | s indirection [x indirection] |
| clearning.cpp:61:3:61:7 | ... ++ indirection | semmle.label | ... ++ indirection |
| clearning.cpp:61:3:61:7 | ... ++ indirection | semmle.label | ... ++ indirection |
| clearning.cpp:61:5:61:5 | s indirection [post update] [x indirection] | semmle.label | s indirection [post update] [x indirection] |
| clearning.cpp:61:5:61:5 | x indirection | semmle.label | x indirection |
| clearning.cpp:62:8:62:8 | s indirection [x indirection] | semmle.label | s indirection [x indirection] |
| clearning.cpp:62:10:62:10 | x indirection | semmle.label | x indirection |
| clearning.cpp:62:10:62:10 | x indirection | semmle.label | x indirection |
| clearning.cpp:74:20:74:22 | argument_source output argument | semmle.label | argument_source output argument |
| clearning.cpp:74:20:74:22 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:76:7:76:12 | * ... | semmle.label | * ... |
| clearning.cpp:76:8:76:8 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:76:10:76:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:76:10:76:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:81:20:81:22 | argument_source output argument | semmle.label | argument_source output argument |
| clearning.cpp:81:20:81:22 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:83:5:83:21 | ... = ... indirection | semmle.label | ... = ... indirection |
| clearning.cpp:83:7:83:9 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:83:13:83:13 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:83:13:83:21 | ... + ... indirection | semmle.label | ... + ... indirection |
| clearning.cpp:83:15:83:17 | val indirection | semmle.label | val indirection |
| clearning.cpp:84:7:84:12 | * ... | semmle.label | * ... |
| clearning.cpp:84:8:84:8 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:84:10:84:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:84:10:84:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:89:20:89:22 | argument_source output argument | semmle.label | argument_source output argument |
| clearning.cpp:89:20:89:22 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:90:3:90:3 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:90:3:90:9 | ... ++ indirection | semmle.label | ... ++ indirection |
| clearning.cpp:90:3:90:9 | ... ++ indirection | semmle.label | ... ++ indirection |
| clearning.cpp:90:5:90:7 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:90:5:90:7 | val indirection | semmle.label | val indirection |
| clearning.cpp:91:7:91:12 | * ... | semmle.label | * ... |
| clearning.cpp:91:8:91:8 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:91:10:91:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:91:10:91:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:96:20:96:22 | argument_source output argument | semmle.label | argument_source output argument |
| clearning.cpp:96:20:96:22 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:97:2:97:18 | ... = ... indirection | semmle.label | ... = ... indirection |
| clearning.cpp:97:4:97:6 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:97:10:97:10 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:97:10:97:18 | ... + ... indirection | semmle.label | ... + ... indirection |
| clearning.cpp:97:12:97:14 | val indirection | semmle.label | val indirection |
| clearning.cpp:98:7:98:12 | * ... | semmle.label | * ... |
| clearning.cpp:98:8:98:8 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:98:10:98:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:98:10:98:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:103:20:103:22 | argument_source output argument | semmle.label | argument_source output argument |
| clearning.cpp:103:20:103:22 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:104:2:104:2 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:104:2:104:8 | ... ++ indirection | semmle.label | ... ++ indirection |
| clearning.cpp:104:2:104:8 | ... ++ indirection | semmle.label | ... ++ indirection |
| clearning.cpp:104:4:104:6 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:104:4:104:6 | val indirection | semmle.label | val indirection |
| clearning.cpp:105:7:105:12 | * ... | semmle.label | * ... |
| clearning.cpp:105:8:105:8 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:105:10:105:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:105:10:105:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:110:20:110:22 | argument_source output argument | semmle.label | argument_source output argument |
| clearning.cpp:110:20:110:22 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:111:2:111:8 | ++ ... indirection | semmle.label | ++ ... indirection |
| clearning.cpp:111:2:111:8 | ++ ... indirection | semmle.label | ++ ... indirection |
| clearning.cpp:111:4:111:4 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:111:6:111:8 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:111:6:111:8 | val indirection | semmle.label | val indirection |
| clearning.cpp:112:7:112:12 | * ... | semmle.label | * ... |
| clearning.cpp:112:8:112:8 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:112:10:112:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:112:10:112:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:117:20:117:22 | argument_source output argument | semmle.label | argument_source output argument |
| clearning.cpp:117:20:117:22 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:118:2:118:2 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:118:2:118:11 | ... += ... indirection | semmle.label | ... += ... indirection |
| clearning.cpp:118:2:118:11 | ... += ... indirection | semmle.label | ... += ... indirection |
| clearning.cpp:118:4:118:6 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
| clearning.cpp:118:4:118:6 | val indirection | semmle.label | val indirection |
| clearning.cpp:119:7:119:12 | * ... | semmle.label | * ... |
| clearning.cpp:119:8:119:8 | s indirection [val indirection] | semmle.label | s indirection [val indirection] |
| clearning.cpp:119:10:119:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:119:10:119:12 | val indirection | semmle.label | val indirection |
| clearning.cpp:151:3:151:22 | ... = ... | semmle.label | ... = ... |
| clearning.cpp:151:5:151:7 | s indirection [post update] [val] | semmle.label | s indirection [post update] [val] |
| clearning.cpp:151:11:151:20 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:152:8:152:8 | s indirection [val] | semmle.label | s indirection [val] |
| clearning.cpp:152:10:152:12 | val | semmle.label | val |
| clearning.cpp:152:10:152:12 | val indirection | semmle.label | val indirection |
| complex.cpp:9:7:9:7 | a indirection | semmle.label | a indirection |
| complex.cpp:9:7:9:7 | this indirection [a_] | semmle.label | this indirection [a_] |
| complex.cpp:9:20:9:21 | a_ | semmle.label | a_ |
@@ -1939,7 +1699,6 @@ nodes
| struct_init.c:15:8:15:9 | ab indirection [a] | semmle.label | ab indirection [a] |
| struct_init.c:15:12:15:12 | a | semmle.label | a |
| struct_init.c:15:12:15:12 | a indirection | semmle.label | a indirection |
| struct_init.c:20:13:20:14 | definition of ab indirection [a] | semmle.label | definition of ab indirection [a] |
| struct_init.c:20:17:20:36 | definition of ab indirection [post update] [a] | semmle.label | definition of ab indirection [post update] [a] |
| struct_init.c:20:20:20:29 | call to user_input | semmle.label | call to user_input |
| struct_init.c:20:20:20:29 | call to user_input | semmle.label | call to user_input |
@@ -1947,7 +1706,6 @@ nodes
| struct_init.c:22:11:22:11 | a | semmle.label | a |
| struct_init.c:22:11:22:11 | a indirection | semmle.label | a indirection |
| struct_init.c:24:10:24:12 | & ... indirection [a] | semmle.label | & ... indirection [a] |
| struct_init.c:26:16:26:20 | definition of outer indirection [nestedAB, a] | semmle.label | definition of outer indirection [nestedAB, a] |
| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] | semmle.label | definition of outer indirection [post update] [nestedAB, a] |
| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] | semmle.label | definition of outer indirection [post update] [nestedAB, a] |
| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [pointerAB indirection, a] | semmle.label | definition of outer indirection [post update] [pointerAB indirection, a] |
@@ -1966,7 +1724,6 @@ nodes
| struct_init.c:33:25:33:25 | a indirection | semmle.label | a indirection |
| struct_init.c:36:10:36:24 | & ... indirection [a] | semmle.label | & ... indirection [a] |
| struct_init.c:36:11:36:15 | outer indirection [nestedAB, a] | semmle.label | outer indirection [nestedAB, a] |
| struct_init.c:40:13:40:14 | definition of ab indirection [a] | semmle.label | definition of ab indirection [a] |
| struct_init.c:40:17:40:36 | definition of ab indirection [post update] [a] | semmle.label | definition of ab indirection [post update] [a] |
| struct_init.c:40:20:40:29 | call to user_input | semmle.label | call to user_input |
| struct_init.c:40:20:40:29 | call to user_input | semmle.label | call to user_input |
@@ -2126,17 +1883,6 @@ subpaths
| by_reference.cpp:134:29:134:29 | a | by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:134:29:134:29 | a | a flows from $@ | by_reference.cpp:88:13:88:22 | call to user_input | call to user_input |
| by_reference.cpp:135:27:135:27 | a | by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:135:27:135:27 | a | a flows from $@ | by_reference.cpp:88:13:88:22 | call to user_input | call to user_input |
| by_reference.cpp:136:16:136:16 | a | by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:136:16:136:16 | a | a flows from $@ | by_reference.cpp:96:8:96:17 | call to user_input | call to user_input |
| clearning.cpp:34:8:34:11 | * ... | clearning.cpp:32:10:32:19 | call to user_input | clearning.cpp:34:8:34:11 | * ... | * ... flows from $@ | clearning.cpp:32:10:32:19 | call to user_input | call to user_input |
| clearning.cpp:55:10:55:10 | x indirection | clearning.cpp:53:10:53:19 | call to user_input | clearning.cpp:55:10:55:10 | x indirection | x indirection flows from $@ | clearning.cpp:53:10:53:19 | call to user_input | call to user_input |
| clearning.cpp:62:10:62:10 | x indirection | clearning.cpp:60:11:60:20 | call to user_input | clearning.cpp:62:10:62:10 | x indirection | x indirection flows from $@ | clearning.cpp:60:11:60:20 | call to user_input | call to user_input |
| clearning.cpp:76:7:76:12 | * ... | clearning.cpp:74:20:74:22 | argument_source output argument | clearning.cpp:76:7:76:12 | * ... | * ... flows from $@ | clearning.cpp:74:20:74:22 | argument_source output argument | argument_source output argument |
| clearning.cpp:84:7:84:12 | * ... | clearning.cpp:81:20:81:22 | argument_source output argument | clearning.cpp:84:7:84:12 | * ... | * ... flows from $@ | clearning.cpp:81:20:81:22 | argument_source output argument | argument_source output argument |
| clearning.cpp:91:7:91:12 | * ... | clearning.cpp:89:20:89:22 | argument_source output argument | clearning.cpp:91:7:91:12 | * ... | * ... flows from $@ | clearning.cpp:89:20:89:22 | argument_source output argument | argument_source output argument |
| clearning.cpp:98:7:98:12 | * ... | clearning.cpp:96:20:96:22 | argument_source output argument | clearning.cpp:98:7:98:12 | * ... | * ... flows from $@ | clearning.cpp:96:20:96:22 | argument_source output argument | argument_source output argument |
| clearning.cpp:105:7:105:12 | * ... | clearning.cpp:103:20:103:22 | argument_source output argument | clearning.cpp:105:7:105:12 | * ... | * ... flows from $@ | clearning.cpp:103:20:103:22 | argument_source output argument | argument_source output argument |
| clearning.cpp:112:7:112:12 | * ... | clearning.cpp:110:20:110:22 | argument_source output argument | clearning.cpp:112:7:112:12 | * ... | * ... flows from $@ | clearning.cpp:110:20:110:22 | argument_source output argument | argument_source output argument |
| clearning.cpp:119:7:119:12 | * ... | clearning.cpp:117:20:117:22 | argument_source output argument | clearning.cpp:119:7:119:12 | * ... | * ... flows from $@ | clearning.cpp:117:20:117:22 | argument_source output argument | argument_source output argument |
| clearning.cpp:152:10:152:12 | val | clearning.cpp:151:11:151:20 | call to user_input | clearning.cpp:152:10:152:12 | val | val flows from $@ | clearning.cpp:151:11:151:20 | call to user_input | call to user_input |
| complex.cpp:42:18:42:18 | call to a | complex.cpp:53:19:53:28 | call to user_input | complex.cpp:42:18:42:18 | call to a | call to a flows from $@ | complex.cpp:53:19:53:28 | call to user_input | call to user_input |
| complex.cpp:42:18:42:18 | call to a | complex.cpp:55:19:55:28 | call to user_input | complex.cpp:42:18:42:18 | call to a | call to a flows from $@ | complex.cpp:55:19:55:28 | call to user_input | call to user_input |
| complex.cpp:43:18:43:18 | call to b | complex.cpp:54:19:54:28 | call to user_input | complex.cpp:43:18:43:18 | call to b | call to b flows from $@ | complex.cpp:54:19:54:28 | call to user_input | call to user_input |

View File

@@ -167,66 +167,6 @@
| by_reference.cpp:88:9:88:9 | a | AST only |
| by_reference.cpp:92:3:92:5 | * ... | AST only |
| by_reference.cpp:96:3:96:4 | pa | AST only |
| clearning.cpp:18:7:18:7 | s | IR only |
| clearning.cpp:19:3:19:6 | * ... | AST only |
| clearning.cpp:20:12:20:12 | s | IR only |
| clearning.cpp:25:7:25:7 | s | IR only |
| clearning.cpp:26:7:26:7 | s | IR only |
| clearning.cpp:27:12:27:12 | s | IR only |
| clearning.cpp:32:3:32:6 | * ... | AST only |
| clearning.cpp:33:7:33:7 | s | IR only |
| clearning.cpp:34:8:34:11 | * ... | IR only |
| clearning.cpp:34:11:34:11 | s | IR only |
| clearning.cpp:39:3:39:6 | * ... | AST only |
| clearning.cpp:40:5:40:5 | x | AST only |
| clearning.cpp:41:8:41:11 | * ... | IR only |
| clearning.cpp:41:11:41:11 | s | IR only |
| clearning.cpp:46:7:46:7 | s | IR only |
| clearning.cpp:47:5:47:5 | x | AST only |
| clearning.cpp:48:8:48:11 | * ... | IR only |
| clearning.cpp:48:11:48:11 | s | IR only |
| clearning.cpp:53:3:53:6 | * ... | AST only |
| clearning.cpp:54:5:54:5 | x | AST only |
| clearning.cpp:60:7:60:7 | s | IR only |
| clearning.cpp:61:5:61:5 | x | AST only |
| clearning.cpp:75:2:75:10 | access to array | AST only |
| clearning.cpp:76:10:76:12 | s | IR only |
| clearning.cpp:82:2:82:9 | access to array | AST only |
| clearning.cpp:83:7:83:9 | val | AST only |
| clearning.cpp:83:15:83:17 | s | IR only |
| clearning.cpp:84:10:84:12 | s | IR only |
| clearning.cpp:90:5:90:7 | val | AST only |
| clearning.cpp:91:10:91:12 | s | IR only |
| clearning.cpp:97:4:97:6 | val | AST only |
| clearning.cpp:97:12:97:14 | s | IR only |
| clearning.cpp:98:10:98:12 | s | IR only |
| clearning.cpp:104:4:104:6 | val | AST only |
| clearning.cpp:105:10:105:12 | s | IR only |
| clearning.cpp:111:6:111:8 | val | AST only |
| clearning.cpp:112:10:112:12 | s | IR only |
| clearning.cpp:118:4:118:6 | val | AST only |
| clearning.cpp:119:10:119:12 | s | IR only |
| clearning.cpp:124:4:124:6 | val | AST only |
| clearning.cpp:125:4:125:6 | val | AST only |
| clearning.cpp:131:4:131:6 | val | AST only |
| clearning.cpp:132:4:132:6 | val | AST only |
| clearning.cpp:138:4:138:6 | val | AST only |
| clearning.cpp:139:6:139:8 | val | AST only |
| clearning.cpp:151:5:151:7 | val | AST only |
| clearning.cpp:152:10:152:12 | s | IR only |
| clearning.cpp:157:5:157:7 | val | AST only |
| clearning.cpp:158:5:158:7 | val | AST only |
| clearning.cpp:159:10:159:12 | s | IR only |
| clearning.cpp:164:5:164:7 | val | AST only |
| clearning.cpp:165:5:165:7 | val | AST only |
| clearning.cpp:166:10:166:12 | s | IR only |
| clearning.cpp:171:5:171:7 | val | AST only |
| clearning.cpp:172:5:172:7 | val | AST only |
| clearning.cpp:173:10:173:12 | s | IR only |
| clearning.cpp:178:5:178:7 | val | AST only |
| clearning.cpp:179:5:179:7 | val | AST only |
| clearning.cpp:179:13:179:15 | s | IR only |
| clearning.cpp:180:10:180:12 | s | IR only |
| complex.cpp:9:20:9:21 | this | IR only |
| complex.cpp:10:20:10:21 | this | IR only |
| complex.cpp:11:22:11:23 | a_ | AST only |

View File

@@ -408,90 +408,6 @@
| by_reference.cpp:135:27:135:27 | a |
| by_reference.cpp:136:8:136:13 | pouter |
| by_reference.cpp:136:16:136:16 | a |
| clearning.cpp:18:5:18:5 | s |
| clearning.cpp:19:4:19:4 | s |
| clearning.cpp:20:10:20:10 | s |
| clearning.cpp:25:5:25:5 | s |
| clearning.cpp:26:5:26:5 | s |
| clearning.cpp:27:10:27:10 | s |
| clearning.cpp:32:4:32:4 | s |
| clearning.cpp:33:5:33:5 | s |
| clearning.cpp:34:8:34:11 | * ... |
| clearning.cpp:34:9:34:9 | s |
| clearning.cpp:39:4:39:4 | s |
| clearning.cpp:40:3:40:3 | s |
| clearning.cpp:41:8:41:11 | * ... |
| clearning.cpp:41:9:41:9 | s |
| clearning.cpp:46:5:46:5 | s |
| clearning.cpp:47:3:47:3 | s |
| clearning.cpp:48:8:48:11 | * ... |
| clearning.cpp:48:9:48:9 | s |
| clearning.cpp:53:4:53:4 | s |
| clearning.cpp:54:3:54:3 | s |
| clearning.cpp:55:8:55:8 | s |
| clearning.cpp:55:10:55:10 | x |
| clearning.cpp:60:5:60:5 | s |
| clearning.cpp:61:3:61:3 | s |
| clearning.cpp:62:8:62:8 | s |
| clearning.cpp:62:10:62:10 | x |
| clearning.cpp:74:18:74:18 | s |
| clearning.cpp:74:20:74:22 | val |
| clearning.cpp:75:2:75:2 | s |
| clearning.cpp:76:8:76:8 | s |
| clearning.cpp:81:18:81:18 | s |
| clearning.cpp:81:20:81:22 | val |
| clearning.cpp:82:2:82:2 | s |
| clearning.cpp:83:5:83:5 | s |
| clearning.cpp:83:13:83:13 | s |
| clearning.cpp:84:8:84:8 | s |
| clearning.cpp:89:18:89:18 | s |
| clearning.cpp:89:20:89:22 | val |
| clearning.cpp:90:3:90:3 | s |
| clearning.cpp:91:8:91:8 | s |
| clearning.cpp:96:18:96:18 | s |
| clearning.cpp:96:20:96:22 | val |
| clearning.cpp:97:2:97:2 | s |
| clearning.cpp:97:10:97:10 | s |
| clearning.cpp:98:8:98:8 | s |
| clearning.cpp:103:18:103:18 | s |
| clearning.cpp:103:20:103:22 | val |
| clearning.cpp:104:2:104:2 | s |
| clearning.cpp:105:8:105:8 | s |
| clearning.cpp:110:18:110:18 | s |
| clearning.cpp:110:20:110:22 | val |
| clearning.cpp:111:4:111:4 | s |
| clearning.cpp:112:8:112:8 | s |
| clearning.cpp:117:18:117:18 | s |
| clearning.cpp:117:20:117:22 | val |
| clearning.cpp:118:2:118:2 | s |
| clearning.cpp:119:8:119:8 | s |
| clearning.cpp:124:2:124:2 | s |
| clearning.cpp:125:2:125:2 | s |
| clearning.cpp:126:7:126:7 | s |
| clearning.cpp:126:9:126:11 | val |
| clearning.cpp:131:2:131:2 | s |
| clearning.cpp:132:2:132:2 | s |
| clearning.cpp:133:7:133:7 | s |
| clearning.cpp:133:9:133:11 | val |
| clearning.cpp:138:2:138:2 | s |
| clearning.cpp:139:4:139:4 | s |
| clearning.cpp:140:7:140:7 | s |
| clearning.cpp:140:9:140:11 | val |
| clearning.cpp:151:3:151:3 | s |
| clearning.cpp:152:8:152:8 | s |
| clearning.cpp:157:3:157:3 | s |
| clearning.cpp:158:3:158:3 | s |
| clearning.cpp:159:8:159:8 | s |
| clearning.cpp:164:3:164:3 | s |
| clearning.cpp:165:3:165:3 | s |
| clearning.cpp:166:8:166:8 | s |
| clearning.cpp:171:3:171:3 | s |
| clearning.cpp:172:3:172:3 | s |
| clearning.cpp:173:8:173:8 | s |
| clearning.cpp:178:3:178:3 | s |
| clearning.cpp:179:3:179:3 | s |
| clearning.cpp:179:11:179:11 | s |
| clearning.cpp:180:8:180:8 | s |
| complex.cpp:9:20:9:21 | this |
| complex.cpp:10:20:10:21 | this |
| complex.cpp:11:22:11:23 | this |

View File

@@ -348,92 +348,6 @@
| by_reference.cpp:135:27:135:27 | a |
| by_reference.cpp:136:8:136:13 | pouter |
| by_reference.cpp:136:16:136:16 | a |
| clearning.cpp:19:3:19:6 | * ... |
| clearning.cpp:19:4:19:4 | s |
| clearning.cpp:32:3:32:6 | * ... |
| clearning.cpp:32:4:32:4 | s |
| clearning.cpp:39:3:39:6 | * ... |
| clearning.cpp:39:4:39:4 | s |
| clearning.cpp:40:3:40:3 | s |
| clearning.cpp:40:5:40:5 | x |
| clearning.cpp:47:3:47:3 | s |
| clearning.cpp:47:5:47:5 | x |
| clearning.cpp:53:3:53:6 | * ... |
| clearning.cpp:53:4:53:4 | s |
| clearning.cpp:54:3:54:3 | s |
| clearning.cpp:54:5:54:5 | x |
| clearning.cpp:55:8:55:8 | s |
| clearning.cpp:55:10:55:10 | x |
| clearning.cpp:61:3:61:3 | s |
| clearning.cpp:61:5:61:5 | x |
| clearning.cpp:62:8:62:8 | s |
| clearning.cpp:62:10:62:10 | x |
| clearning.cpp:74:18:74:18 | s |
| clearning.cpp:74:20:74:22 | val |
| clearning.cpp:75:2:75:2 | s |
| clearning.cpp:75:2:75:10 | access to array |
| clearning.cpp:81:18:81:18 | s |
| clearning.cpp:81:20:81:22 | val |
| clearning.cpp:82:2:82:2 | s |
| clearning.cpp:82:2:82:9 | access to array |
| clearning.cpp:83:5:83:5 | s |
| clearning.cpp:83:7:83:9 | val |
| clearning.cpp:89:18:89:18 | s |
| clearning.cpp:89:20:89:22 | val |
| clearning.cpp:90:3:90:3 | s |
| clearning.cpp:90:5:90:7 | val |
| clearning.cpp:96:18:96:18 | s |
| clearning.cpp:96:20:96:22 | val |
| clearning.cpp:97:2:97:2 | s |
| clearning.cpp:97:4:97:6 | val |
| clearning.cpp:103:18:103:18 | s |
| clearning.cpp:103:20:103:22 | val |
| clearning.cpp:104:2:104:2 | s |
| clearning.cpp:104:4:104:6 | val |
| clearning.cpp:110:18:110:18 | s |
| clearning.cpp:110:20:110:22 | val |
| clearning.cpp:111:4:111:4 | s |
| clearning.cpp:111:6:111:8 | val |
| clearning.cpp:117:18:117:18 | s |
| clearning.cpp:117:20:117:22 | val |
| clearning.cpp:118:2:118:2 | s |
| clearning.cpp:118:4:118:6 | val |
| clearning.cpp:124:2:124:2 | s |
| clearning.cpp:124:4:124:6 | val |
| clearning.cpp:125:2:125:2 | s |
| clearning.cpp:125:4:125:6 | val |
| clearning.cpp:126:7:126:7 | s |
| clearning.cpp:126:9:126:11 | val |
| clearning.cpp:131:2:131:2 | s |
| clearning.cpp:131:4:131:6 | val |
| clearning.cpp:132:2:132:2 | s |
| clearning.cpp:132:4:132:6 | val |
| clearning.cpp:133:7:133:7 | s |
| clearning.cpp:133:9:133:11 | val |
| clearning.cpp:138:2:138:2 | s |
| clearning.cpp:138:4:138:6 | val |
| clearning.cpp:139:4:139:4 | s |
| clearning.cpp:139:6:139:8 | val |
| clearning.cpp:140:7:140:7 | s |
| clearning.cpp:140:9:140:11 | val |
| clearning.cpp:151:3:151:3 | s |
| clearning.cpp:151:5:151:7 | val |
| clearning.cpp:157:3:157:3 | s |
| clearning.cpp:157:5:157:7 | val |
| clearning.cpp:158:3:158:3 | s |
| clearning.cpp:158:5:158:7 | val |
| clearning.cpp:164:3:164:3 | s |
| clearning.cpp:164:5:164:7 | val |
| clearning.cpp:165:3:165:3 | s |
| clearning.cpp:165:5:165:7 | val |
| clearning.cpp:171:3:171:3 | s |
| clearning.cpp:171:5:171:7 | val |
| clearning.cpp:172:3:172:3 | s |
| clearning.cpp:172:5:172:7 | val |
| clearning.cpp:178:3:178:3 | s |
| clearning.cpp:178:5:178:7 | val |
| clearning.cpp:179:3:179:3 | s |
| clearning.cpp:179:5:179:7 | val |
| complex.cpp:11:22:11:23 | a_ |
| complex.cpp:11:22:11:23 | this |
| complex.cpp:12:22:12:23 | b_ |

View File

@@ -448,42 +448,6 @@ edges
| by_reference.cpp:135:8:135:13 | pouter [inner_ptr, a] | by_reference.cpp:135:16:135:24 | inner_ptr [a] |
| by_reference.cpp:135:16:135:24 | inner_ptr [a] | by_reference.cpp:135:27:135:27 | a |
| by_reference.cpp:136:8:136:13 | pouter [a] | by_reference.cpp:136:16:136:16 | a |
| clearning.cpp:53:4:53:4 | s [post update] [x] | clearning.cpp:55:8:55:8 | s [x] |
| clearning.cpp:53:6:53:6 | x [inner post update] | clearning.cpp:53:4:53:4 | s [post update] [x] |
| clearning.cpp:53:10:53:19 | call to user_input | clearning.cpp:53:6:53:6 | x [inner post update] |
| clearning.cpp:55:8:55:8 | s [x] | clearning.cpp:55:10:55:10 | x |
| clearning.cpp:124:2:124:2 | s [post update] [val] | clearning.cpp:126:7:126:7 | s [val] |
| clearning.cpp:124:2:124:25 | ... = ... | clearning.cpp:124:2:124:2 | s [post update] [val] |
| clearning.cpp:124:10:124:19 | call to user_input | clearning.cpp:124:2:124:25 | ... = ... |
| clearning.cpp:126:7:126:7 | s [val] | clearning.cpp:126:9:126:11 | val |
| clearning.cpp:131:2:131:2 | s [post update] [val] | clearning.cpp:133:7:133:7 | s [val] |
| clearning.cpp:131:2:131:25 | ... = ... | clearning.cpp:131:2:131:2 | s [post update] [val] |
| clearning.cpp:131:10:131:19 | call to user_input | clearning.cpp:131:2:131:25 | ... = ... |
| clearning.cpp:133:7:133:7 | s [val] | clearning.cpp:133:9:133:11 | val |
| clearning.cpp:138:2:138:2 | s [post update] [val] | clearning.cpp:140:7:140:7 | s [val] |
| clearning.cpp:138:2:138:25 | ... = ... | clearning.cpp:138:2:138:2 | s [post update] [val] |
| clearning.cpp:138:10:138:19 | call to user_input | clearning.cpp:138:2:138:25 | ... = ... |
| clearning.cpp:140:7:140:7 | s [val] | clearning.cpp:140:9:140:11 | val |
| clearning.cpp:151:3:151:3 | s [post update] [val] | clearning.cpp:152:8:152:8 | s [val] |
| clearning.cpp:151:3:151:22 | ... = ... | clearning.cpp:151:3:151:3 | s [post update] [val] |
| clearning.cpp:151:11:151:20 | call to user_input | clearning.cpp:151:3:151:22 | ... = ... |
| clearning.cpp:152:8:152:8 | s [val] | clearning.cpp:152:10:152:12 | val |
| clearning.cpp:157:3:157:3 | s [post update] [val] | clearning.cpp:159:8:159:8 | s [val] |
| clearning.cpp:157:3:157:22 | ... = ... | clearning.cpp:157:3:157:3 | s [post update] [val] |
| clearning.cpp:157:11:157:20 | call to user_input | clearning.cpp:157:3:157:22 | ... = ... |
| clearning.cpp:159:8:159:8 | s [val] | clearning.cpp:159:10:159:12 | val |
| clearning.cpp:164:3:164:3 | s [post update] [val] | clearning.cpp:166:8:166:8 | s [val] |
| clearning.cpp:164:3:164:22 | ... = ... | clearning.cpp:164:3:164:3 | s [post update] [val] |
| clearning.cpp:164:11:164:20 | call to user_input | clearning.cpp:164:3:164:22 | ... = ... |
| clearning.cpp:166:8:166:8 | s [val] | clearning.cpp:166:10:166:12 | val |
| clearning.cpp:171:3:171:3 | s [post update] [val] | clearning.cpp:173:8:173:8 | s [val] |
| clearning.cpp:171:3:171:22 | ... = ... | clearning.cpp:171:3:171:3 | s [post update] [val] |
| clearning.cpp:171:11:171:20 | call to user_input | clearning.cpp:171:3:171:22 | ... = ... |
| clearning.cpp:173:8:173:8 | s [val] | clearning.cpp:173:10:173:12 | val |
| clearning.cpp:178:3:178:3 | s [post update] [val] | clearning.cpp:180:8:180:8 | s [val] |
| clearning.cpp:178:3:178:22 | ... = ... | clearning.cpp:178:3:178:3 | s [post update] [val] |
| clearning.cpp:178:11:178:20 | call to user_input | clearning.cpp:178:3:178:22 | ... = ... |
| clearning.cpp:180:8:180:8 | s [val] | clearning.cpp:180:10:180:12 | val |
| complex.cpp:9:7:9:7 | this [a_] | complex.cpp:9:20:9:21 | this [a_] |
| complex.cpp:9:20:9:21 | this [a_] | complex.cpp:9:20:9:21 | a_ |
| complex.cpp:10:7:10:7 | this [b_] | complex.cpp:10:20:10:21 | this [b_] |
@@ -1191,51 +1155,6 @@ nodes
| by_reference.cpp:135:27:135:27 | a | semmle.label | a |
| by_reference.cpp:136:8:136:13 | pouter [a] | semmle.label | pouter [a] |
| by_reference.cpp:136:16:136:16 | a | semmle.label | a |
| clearning.cpp:53:4:53:4 | s [post update] [x] | semmle.label | s [post update] [x] |
| clearning.cpp:53:6:53:6 | x [inner post update] | semmle.label | x [inner post update] |
| clearning.cpp:53:10:53:19 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:55:8:55:8 | s [x] | semmle.label | s [x] |
| clearning.cpp:55:10:55:10 | x | semmle.label | x |
| clearning.cpp:124:2:124:2 | s [post update] [val] | semmle.label | s [post update] [val] |
| clearning.cpp:124:2:124:25 | ... = ... | semmle.label | ... = ... |
| clearning.cpp:124:10:124:19 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:126:7:126:7 | s [val] | semmle.label | s [val] |
| clearning.cpp:126:9:126:11 | val | semmle.label | val |
| clearning.cpp:131:2:131:2 | s [post update] [val] | semmle.label | s [post update] [val] |
| clearning.cpp:131:2:131:25 | ... = ... | semmle.label | ... = ... |
| clearning.cpp:131:10:131:19 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:133:7:133:7 | s [val] | semmle.label | s [val] |
| clearning.cpp:133:9:133:11 | val | semmle.label | val |
| clearning.cpp:138:2:138:2 | s [post update] [val] | semmle.label | s [post update] [val] |
| clearning.cpp:138:2:138:25 | ... = ... | semmle.label | ... = ... |
| clearning.cpp:138:10:138:19 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:140:7:140:7 | s [val] | semmle.label | s [val] |
| clearning.cpp:140:9:140:11 | val | semmle.label | val |
| clearning.cpp:151:3:151:3 | s [post update] [val] | semmle.label | s [post update] [val] |
| clearning.cpp:151:3:151:22 | ... = ... | semmle.label | ... = ... |
| clearning.cpp:151:11:151:20 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:152:8:152:8 | s [val] | semmle.label | s [val] |
| clearning.cpp:152:10:152:12 | val | semmle.label | val |
| clearning.cpp:157:3:157:3 | s [post update] [val] | semmle.label | s [post update] [val] |
| clearning.cpp:157:3:157:22 | ... = ... | semmle.label | ... = ... |
| clearning.cpp:157:11:157:20 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:159:8:159:8 | s [val] | semmle.label | s [val] |
| clearning.cpp:159:10:159:12 | val | semmle.label | val |
| clearning.cpp:164:3:164:3 | s [post update] [val] | semmle.label | s [post update] [val] |
| clearning.cpp:164:3:164:22 | ... = ... | semmle.label | ... = ... |
| clearning.cpp:164:11:164:20 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:166:8:166:8 | s [val] | semmle.label | s [val] |
| clearning.cpp:166:10:166:12 | val | semmle.label | val |
| clearning.cpp:171:3:171:3 | s [post update] [val] | semmle.label | s [post update] [val] |
| clearning.cpp:171:3:171:22 | ... = ... | semmle.label | ... = ... |
| clearning.cpp:171:11:171:20 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:173:8:173:8 | s [val] | semmle.label | s [val] |
| clearning.cpp:173:10:173:12 | val | semmle.label | val |
| clearning.cpp:178:3:178:3 | s [post update] [val] | semmle.label | s [post update] [val] |
| clearning.cpp:178:3:178:22 | ... = ... | semmle.label | ... = ... |
| clearning.cpp:178:11:178:20 | call to user_input | semmle.label | call to user_input |
| clearning.cpp:180:8:180:8 | s [val] | semmle.label | s [val] |
| clearning.cpp:180:10:180:12 | val | semmle.label | val |
| complex.cpp:9:7:9:7 | this [a_] | semmle.label | this [a_] |
| complex.cpp:9:20:9:21 | a_ | semmle.label | a_ |
| complex.cpp:9:20:9:21 | this [a_] | semmle.label | this [a_] |
@@ -1632,15 +1551,6 @@ subpaths
| by_reference.cpp:134:29:134:29 | a | by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:134:29:134:29 | a | a flows from $@ | by_reference.cpp:88:13:88:22 | call to user_input | call to user_input |
| by_reference.cpp:135:27:135:27 | a | by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:135:27:135:27 | a | a flows from $@ | by_reference.cpp:88:13:88:22 | call to user_input | call to user_input |
| by_reference.cpp:136:16:136:16 | a | by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:136:16:136:16 | a | a flows from $@ | by_reference.cpp:96:8:96:17 | call to user_input | call to user_input |
| clearning.cpp:55:10:55:10 | x | clearning.cpp:53:10:53:19 | call to user_input | clearning.cpp:55:10:55:10 | x | x flows from $@ | clearning.cpp:53:10:53:19 | call to user_input | call to user_input |
| clearning.cpp:126:9:126:11 | val | clearning.cpp:124:10:124:19 | call to user_input | clearning.cpp:126:9:126:11 | val | val flows from $@ | clearning.cpp:124:10:124:19 | call to user_input | call to user_input |
| clearning.cpp:133:9:133:11 | val | clearning.cpp:131:10:131:19 | call to user_input | clearning.cpp:133:9:133:11 | val | val flows from $@ | clearning.cpp:131:10:131:19 | call to user_input | call to user_input |
| clearning.cpp:140:9:140:11 | val | clearning.cpp:138:10:138:19 | call to user_input | clearning.cpp:140:9:140:11 | val | val flows from $@ | clearning.cpp:138:10:138:19 | call to user_input | call to user_input |
| clearning.cpp:152:10:152:12 | val | clearning.cpp:151:11:151:20 | call to user_input | clearning.cpp:152:10:152:12 | val | val flows from $@ | clearning.cpp:151:11:151:20 | call to user_input | call to user_input |
| clearning.cpp:159:10:159:12 | val | clearning.cpp:157:11:157:20 | call to user_input | clearning.cpp:159:10:159:12 | val | val flows from $@ | clearning.cpp:157:11:157:20 | call to user_input | call to user_input |
| clearning.cpp:166:10:166:12 | val | clearning.cpp:164:11:164:20 | call to user_input | clearning.cpp:166:10:166:12 | val | val flows from $@ | clearning.cpp:164:11:164:20 | call to user_input | call to user_input |
| clearning.cpp:173:10:173:12 | val | clearning.cpp:171:11:171:20 | call to user_input | clearning.cpp:173:10:173:12 | val | val flows from $@ | clearning.cpp:171:11:171:20 | call to user_input | call to user_input |
| clearning.cpp:180:10:180:12 | val | clearning.cpp:178:11:178:20 | call to user_input | clearning.cpp:180:10:180:12 | val | val flows from $@ | clearning.cpp:178:11:178:20 | call to user_input | call to user_input |
| complex.cpp:42:18:42:18 | call to a | complex.cpp:53:19:53:28 | call to user_input | complex.cpp:42:18:42:18 | call to a | call to a flows from $@ | complex.cpp:53:19:53:28 | call to user_input | call to user_input |
| complex.cpp:42:18:42:18 | call to a | complex.cpp:55:19:55:28 | call to user_input | complex.cpp:42:18:42:18 | call to a | call to a flows from $@ | complex.cpp:55:19:55:28 | call to user_input | call to user_input |
| complex.cpp:43:18:43:18 | call to b | complex.cpp:54:19:54:28 | call to user_input | complex.cpp:43:18:43:18 | call to b | call to b flows from $@ | complex.cpp:54:19:54:28 | call to user_input | call to user_input |

View File

@@ -6591,20 +6591,6 @@
| taint.cpp:702:4:702:6 | ... ++ | taint.cpp:703:8:703:8 | p | TAINT |
| taint.cpp:702:10:702:11 | * ... | taint.cpp:702:3:702:11 | ... = ... | |
| taint.cpp:702:11:702:11 | s | taint.cpp:702:10:702:11 | * ... | TAINT |
| taint.cpp:709:25:709:25 | d | taint.cpp:709:25:709:25 | d | |
| taint.cpp:709:25:709:25 | d | taint.cpp:711:10:711:10 | d | |
| taint.cpp:709:25:709:25 | d | taint.cpp:712:7:712:7 | d | |
| taint.cpp:709:34:709:34 | s | taint.cpp:709:34:709:34 | s | |
| taint.cpp:709:34:709:34 | s | taint.cpp:710:18:710:18 | s | |
| taint.cpp:709:34:709:34 | s | taint.cpp:711:13:711:13 | s | |
| taint.cpp:710:18:710:18 | ref arg s | taint.cpp:709:34:709:34 | s | |
| taint.cpp:710:18:710:18 | ref arg s | taint.cpp:711:13:711:13 | s | |
| taint.cpp:711:10:711:10 | d | taint.cpp:711:2:711:8 | call to strncpy | |
| taint.cpp:711:10:711:10 | ref arg d | taint.cpp:709:25:709:25 | d | |
| taint.cpp:711:10:711:10 | ref arg d | taint.cpp:712:7:712:7 | d | |
| taint.cpp:711:13:711:13 | s | taint.cpp:711:2:711:8 | call to strncpy | TAINT |
| taint.cpp:711:13:711:13 | s | taint.cpp:711:10:711:10 | ref arg d | TAINT |
| taint.cpp:712:7:712:7 | ref arg d | taint.cpp:709:25:709:25 | d | |
| vector.cpp:16:43:16:49 | source1 | vector.cpp:17:26:17:32 | source1 | |
| vector.cpp:16:43:16:49 | source1 | vector.cpp:31:38:31:44 | source1 | |
| vector.cpp:17:21:17:33 | call to vector | vector.cpp:19:14:19:14 | v | |

View File

@@ -702,12 +702,4 @@ namespace strings {
*p++ = *s;
sink(p); // $ ast ir
}
}
char * strncpy (char *, const char *, unsigned long);
void test_strncpy(char* d, char* s) {
argument_source(s);
strncpy(d, s, 16);
sink(d); // $ ast ir
}

View File

@@ -14462,106 +14462,6 @@ ir.cpp:
# 1911| getExpr(): [VariableAccess] x
# 1911| Type = [IntType] int
# 1911| ValueCategory = prvalue(load)
# 1914| [TopLevelFunction] int static_function(int)
# 1914| <params>:
# 1914| getParameter(0): [Parameter] x
# 1914| Type = [IntType] int
# 1914| getEntryPoint(): [BlockStmt] { ... }
# 1915| getStmt(0): [ReturnStmt] return ...
# 1915| getExpr(): [VariableAccess] x
# 1915| Type = [IntType] int
# 1915| ValueCategory = prvalue(load)
# 1918| [TopLevelFunction] void test_static_functions_with_assignments()
# 1918| <params>:
# 1918| getEntryPoint(): [BlockStmt] { ... }
# 1919| getStmt(0): [DeclStmt] declaration
# 1919| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c
# 1919| Type = [Class] C
# 1919| getVariable().getInitializer(): [Initializer] initializer for c
# 1919| getExpr(): [ConstructorCall] call to C
# 1919| Type = [VoidType] void
# 1919| ValueCategory = prvalue
# 1920| getStmt(1): [DeclStmt] declaration
# 1920| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
# 1920| Type = [IntType] int
# 1921| getStmt(2): [ExprStmt] ExprStmt
# 1921| getExpr(): [AssignExpr] ... = ...
# 1921| Type = [IntType] int
# 1921| ValueCategory = lvalue
# 1921| getLValue(): [VariableAccess] x
# 1921| Type = [IntType] int
# 1921| ValueCategory = lvalue
# 1921| getRValue(): [FunctionCall] call to StaticMemberFunction
# 1921| Type = [IntType] int
# 1921| ValueCategory = prvalue
# 1921| getQualifier(): [VariableAccess] c
# 1921| Type = [Class] C
# 1921| ValueCategory = lvalue
# 1921| getArgument(0): [Literal] 10
# 1921| Type = [IntType] int
# 1921| Value = [Literal] 10
# 1921| ValueCategory = prvalue
# 1922| getStmt(3): [DeclStmt] declaration
# 1922| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y
# 1922| Type = [IntType] int
# 1923| getStmt(4): [ExprStmt] ExprStmt
# 1923| getExpr(): [AssignExpr] ... = ...
# 1923| Type = [IntType] int
# 1923| ValueCategory = lvalue
# 1923| getLValue(): [VariableAccess] y
# 1923| Type = [IntType] int
# 1923| ValueCategory = lvalue
# 1923| getRValue(): [FunctionCall] call to StaticMemberFunction
# 1923| Type = [IntType] int
# 1923| ValueCategory = prvalue
# 1923| getArgument(0): [Literal] 10
# 1923| Type = [IntType] int
# 1923| Value = [Literal] 10
# 1923| ValueCategory = prvalue
# 1924| getStmt(5): [DeclStmt] declaration
# 1924| getDeclarationEntry(0): [VariableDeclarationEntry] definition of z
# 1924| Type = [IntType] int
# 1925| getStmt(6): [ExprStmt] ExprStmt
# 1925| getExpr(): [AssignExpr] ... = ...
# 1925| Type = [IntType] int
# 1925| ValueCategory = lvalue
# 1925| getLValue(): [VariableAccess] z
# 1925| Type = [IntType] int
# 1925| ValueCategory = lvalue
# 1925| getRValue(): [FunctionCall] call to static_function
# 1925| Type = [IntType] int
# 1925| ValueCategory = prvalue
# 1925| getArgument(0): [Literal] 10
# 1925| Type = [IntType] int
# 1925| Value = [Literal] 10
# 1925| ValueCategory = prvalue
# 1926| getStmt(7): [ReturnStmt] return ...
# 1928| [TopLevelFunction] void test_double_assign()
# 1928| <params>:
# 1928| getEntryPoint(): [BlockStmt] { ... }
# 1929| getStmt(0): [DeclStmt] declaration
# 1929| getDeclarationEntry(0): [VariableDeclarationEntry] definition of i
# 1929| Type = [IntType] int
# 1929| getDeclarationEntry(1): [VariableDeclarationEntry] definition of j
# 1929| Type = [IntType] int
# 1930| getStmt(1): [ExprStmt] ExprStmt
# 1930| getExpr(): [AssignExpr] ... = ...
# 1930| Type = [IntType] int
# 1930| ValueCategory = lvalue
# 1930| getLValue(): [VariableAccess] i
# 1930| Type = [IntType] int
# 1930| ValueCategory = lvalue
# 1930| getRValue(): [AssignExpr] ... = ...
# 1930| Type = [IntType] int
# 1930| ValueCategory = prvalue
# 1930| getLValue(): [VariableAccess] j
# 1930| Type = [IntType] int
# 1930| ValueCategory = lvalue
# 1930| getRValue(): [Literal] 40
# 1930| Type = [IntType] int
# 1930| Value = [Literal] 40
# 1930| ValueCategory = prvalue
# 1931| getStmt(2): [ReturnStmt] return ...
perf-regression.cpp:
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
# 4| <params>:

View File

@@ -1911,23 +1911,4 @@ int noreturnTest2(int x) {
return x;
}
int static_function(int x) {
return x;
}
void test_static_functions_with_assignments() {
C c;
int x;
x = c.StaticMemberFunction(10);
int y;
y = C::StaticMemberFunction(10);
int z;
z = static_function(10);
}
void test_double_assign() {
int i, j;
i = j = 40;
}
// semmle-extractor-options: -std=c++17 --clang

View File

@@ -8821,62 +8821,6 @@
| ir.cpp:1911:12:1911:12 | Address | &:r1911_2 |
| ir.cpp:1911:12:1911:12 | Load | m1907_6 |
| ir.cpp:1911:12:1911:12 | StoreValue | r1911_3 |
| ir.cpp:1914:5:1914:19 | Address | &:r1914_7 |
| ir.cpp:1914:5:1914:19 | ChiPartial | partial:m1914_3 |
| ir.cpp:1914:5:1914:19 | ChiTotal | total:m1914_2 |
| ir.cpp:1914:5:1914:19 | Load | m1915_4 |
| ir.cpp:1914:5:1914:19 | SideEffect | m1914_3 |
| ir.cpp:1914:25:1914:25 | Address | &:r1914_5 |
| ir.cpp:1915:5:1915:13 | Address | &:r1915_1 |
| ir.cpp:1915:12:1915:12 | Address | &:r1915_2 |
| ir.cpp:1915:12:1915:12 | Load | m1914_6 |
| ir.cpp:1915:12:1915:12 | StoreValue | r1915_3 |
| ir.cpp:1918:6:1918:43 | ChiPartial | partial:m1918_3 |
| ir.cpp:1918:6:1918:43 | ChiTotal | total:m1918_2 |
| ir.cpp:1918:6:1918:43 | SideEffect | ~m1925_5 |
| ir.cpp:1919:7:1919:7 | Address | &:r1919_1 |
| ir.cpp:1919:7:1919:7 | Address | &:r1919_1 |
| ir.cpp:1919:7:1919:7 | Arg(this) | this:r1919_1 |
| ir.cpp:1919:7:1919:7 | CallTarget | func:r1919_3 |
| ir.cpp:1919:7:1919:7 | ChiPartial | partial:m1919_5 |
| ir.cpp:1919:7:1919:7 | ChiPartial | partial:m1919_7 |
| ir.cpp:1919:7:1919:7 | ChiTotal | total:m1918_4 |
| ir.cpp:1919:7:1919:7 | ChiTotal | total:m1919_2 |
| ir.cpp:1919:7:1919:7 | SideEffect | ~m1918_4 |
| ir.cpp:1920:9:1920:9 | Address | &:r1920_1 |
| ir.cpp:1921:5:1921:5 | Address | &:r1921_7 |
| ir.cpp:1921:11:1921:30 | CallTarget | func:r1921_2 |
| ir.cpp:1921:11:1921:30 | ChiPartial | partial:m1921_5 |
| ir.cpp:1921:11:1921:30 | ChiTotal | total:m1919_6 |
| ir.cpp:1921:11:1921:30 | SideEffect | ~m1919_6 |
| ir.cpp:1921:11:1921:30 | StoreValue | r1921_4 |
| ir.cpp:1921:32:1921:33 | Arg(0) | 0:r1921_3 |
| ir.cpp:1922:9:1922:9 | Address | &:r1922_1 |
| ir.cpp:1923:5:1923:5 | Address | &:r1923_6 |
| ir.cpp:1923:9:1923:31 | CallTarget | func:r1923_1 |
| ir.cpp:1923:9:1923:31 | ChiPartial | partial:m1923_4 |
| ir.cpp:1923:9:1923:31 | ChiTotal | total:m1921_6 |
| ir.cpp:1923:9:1923:31 | SideEffect | ~m1921_6 |
| ir.cpp:1923:9:1923:31 | StoreValue | r1923_3 |
| ir.cpp:1923:33:1923:34 | Arg(0) | 0:r1923_2 |
| ir.cpp:1924:9:1924:9 | Address | &:r1924_1 |
| ir.cpp:1925:5:1925:5 | Address | &:r1925_6 |
| ir.cpp:1925:9:1925:23 | CallTarget | func:r1925_1 |
| ir.cpp:1925:9:1925:23 | ChiPartial | partial:m1925_4 |
| ir.cpp:1925:9:1925:23 | ChiTotal | total:m1923_5 |
| ir.cpp:1925:9:1925:23 | SideEffect | ~m1923_5 |
| ir.cpp:1925:9:1925:23 | StoreValue | r1925_3 |
| ir.cpp:1925:25:1925:26 | Arg(0) | 0:r1925_2 |
| ir.cpp:1928:6:1928:23 | ChiPartial | partial:m1928_3 |
| ir.cpp:1928:6:1928:23 | ChiTotal | total:m1928_2 |
| ir.cpp:1928:6:1928:23 | SideEffect | m1928_3 |
| ir.cpp:1929:7:1929:7 | Address | &:r1929_1 |
| ir.cpp:1929:10:1929:10 | Address | &:r1929_3 |
| ir.cpp:1930:3:1930:3 | Address | &:r1930_5 |
| ir.cpp:1930:7:1930:7 | Address | &:r1930_2 |
| ir.cpp:1930:7:1930:12 | StoreValue | r1930_4 |
| ir.cpp:1930:11:1930:12 | StoreValue | r1930_1 |
| ir.cpp:1930:11:1930:12 | Unary | r1930_1 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_7 |

View File

@@ -10167,83 +10167,6 @@ ir.cpp:
# 1907| v1907_9(void) = AliasedUse : ~m?
# 1907| v1907_10(void) = ExitFunction :
# 1914| int static_function(int)
# 1914| Block 0
# 1914| v1914_1(void) = EnterFunction :
# 1914| mu1914_2(unknown) = AliasedDefinition :
# 1914| mu1914_3(unknown) = InitializeNonLocal :
# 1914| r1914_4(glval<int>) = VariableAddress[x] :
# 1914| mu1914_5(int) = InitializeParameter[x] : &:r1914_4
# 1915| r1915_1(glval<int>) = VariableAddress[#return] :
# 1915| r1915_2(glval<int>) = VariableAddress[x] :
# 1915| r1915_3(int) = Load[x] : &:r1915_2, ~m?
# 1915| mu1915_4(int) = Store[#return] : &:r1915_1, r1915_3
# 1914| r1914_6(glval<int>) = VariableAddress[#return] :
# 1914| v1914_7(void) = ReturnValue : &:r1914_6, ~m?
# 1914| v1914_8(void) = AliasedUse : ~m?
# 1914| v1914_9(void) = ExitFunction :
# 1918| void test_static_functions_with_assignments()
# 1918| Block 0
# 1918| v1918_1(void) = EnterFunction :
# 1918| mu1918_2(unknown) = AliasedDefinition :
# 1918| mu1918_3(unknown) = InitializeNonLocal :
# 1919| r1919_1(glval<C>) = VariableAddress[c] :
# 1919| mu1919_2(C) = Uninitialized[c] : &:r1919_1
# 1919| r1919_3(glval<unknown>) = FunctionAddress[C] :
# 1919| v1919_4(void) = Call[C] : func:r1919_3, this:r1919_1
# 1919| mu1919_5(unknown) = ^CallSideEffect : ~m?
# 1919| mu1919_6(C) = ^IndirectMayWriteSideEffect[-1] : &:r1919_1
# 1920| r1920_1(glval<int>) = VariableAddress[x] :
# 1920| mu1920_2(int) = Uninitialized[x] : &:r1920_1
# 1921| r1921_1(glval<C>) = VariableAddress[c] :
# 1921| r1921_2(glval<unknown>) = FunctionAddress[StaticMemberFunction] :
# 1921| r1921_3(int) = Constant[10] :
# 1921| r1921_4(int) = Call[StaticMemberFunction] : func:r1921_2, 0:r1921_3
# 1921| mu1921_5(unknown) = ^CallSideEffect : ~m?
# 1921| r1921_6(glval<int>) = VariableAddress[x] :
# 1921| mu1921_7(int) = Store[x] : &:r1921_6, r1921_4
# 1922| r1922_1(glval<int>) = VariableAddress[y] :
# 1922| mu1922_2(int) = Uninitialized[y] : &:r1922_1
# 1923| r1923_1(glval<unknown>) = FunctionAddress[StaticMemberFunction] :
# 1923| r1923_2(int) = Constant[10] :
# 1923| r1923_3(int) = Call[StaticMemberFunction] : func:r1923_1, 0:r1923_2
# 1923| mu1923_4(unknown) = ^CallSideEffect : ~m?
# 1923| r1923_5(glval<int>) = VariableAddress[y] :
# 1923| mu1923_6(int) = Store[y] : &:r1923_5, r1923_3
# 1924| r1924_1(glval<int>) = VariableAddress[z] :
# 1924| mu1924_2(int) = Uninitialized[z] : &:r1924_1
# 1925| r1925_1(glval<unknown>) = FunctionAddress[static_function] :
# 1925| r1925_2(int) = Constant[10] :
# 1925| r1925_3(int) = Call[static_function] : func:r1925_1, 0:r1925_2
# 1925| mu1925_4(unknown) = ^CallSideEffect : ~m?
# 1925| r1925_5(glval<int>) = VariableAddress[z] :
# 1925| mu1925_6(int) = Store[z] : &:r1925_5, r1925_3
# 1926| v1926_1(void) = NoOp :
# 1918| v1918_4(void) = ReturnVoid :
# 1918| v1918_5(void) = AliasedUse : ~m?
# 1918| v1918_6(void) = ExitFunction :
# 1928| void test_double_assign()
# 1928| Block 0
# 1928| v1928_1(void) = EnterFunction :
# 1928| mu1928_2(unknown) = AliasedDefinition :
# 1928| mu1928_3(unknown) = InitializeNonLocal :
# 1929| r1929_1(glval<int>) = VariableAddress[i] :
# 1929| mu1929_2(int) = Uninitialized[i] : &:r1929_1
# 1929| r1929_3(glval<int>) = VariableAddress[j] :
# 1929| mu1929_4(int) = Uninitialized[j] : &:r1929_3
# 1930| r1930_1(int) = Constant[40] :
# 1930| r1930_2(glval<int>) = VariableAddress[j] :
# 1930| mu1930_3(int) = Store[j] : &:r1930_2, r1930_1
# 1930| r1930_4(int) = CopyValue : r1930_1
# 1930| r1930_5(glval<int>) = VariableAddress[i] :
# 1930| mu1930_6(int) = Store[i] : &:r1930_5, r1930_4
# 1931| v1931_1(void) = NoOp :
# 1928| v1928_4(void) = ReturnVoid :
# 1928| v1928_5(void) = AliasedUse : ~m?
# 1928| v1928_6(void) = ExitFunction :
perf-regression.cpp:
# 6| void Big::Big()
# 6| Block 0

View File

@@ -70,28 +70,3 @@ int f4(int x) {
}
}
}
// No interesting ranges to check here - this irreducible CFG caused an infinite loop due to back edge detection
void gotoLoop(bool b1, bool b2)
{
int j;
if (b1)
return;
if (!b2)
{
for (j = 0; j < 10; ++j)
{
goto main_decode_loop;
}
}
else
{
for (j = 0; j < 10; ++j)
{
int x;
main_decode_loop:
}
}
}

View File

@@ -1,9 +1,8 @@
edges
| test.cpp:16:11:16:21 | mk_string_t indirection [string] | test.cpp:39:21:39:31 | call to mk_string_t indirection [string] |
| test.cpp:18:5:18:30 | ... = ... | test.cpp:18:10:18:15 | str indirection [post update] [string] |
| test.cpp:18:10:18:15 | str indirection [post update] [string] | test.cpp:19:5:19:7 | str indirection [string] |
| test.cpp:18:10:18:15 | str indirection [post update] [string] | test.cpp:16:11:16:21 | mk_string_t indirection [string] |
| test.cpp:18:19:18:24 | call to malloc | test.cpp:18:5:18:30 | ... = ... |
| test.cpp:19:5:19:7 | str indirection [string] | test.cpp:16:11:16:21 | mk_string_t indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:42:13:42:15 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:72:17:72:19 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:80:17:80:19 | str indirection [string] |
@@ -18,9 +17,8 @@ edges
| test.cpp:80:22:80:27 | string indirection | test.cpp:80:22:80:27 | string |
| test.cpp:88:11:88:30 | mk_string_t_plus_one indirection [string] | test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] |
| test.cpp:90:5:90:34 | ... = ... | test.cpp:90:10:90:15 | str indirection [post update] [string] |
| test.cpp:90:10:90:15 | str indirection [post update] [string] | test.cpp:91:5:91:7 | str indirection [string] |
| test.cpp:90:10:90:15 | str indirection [post update] [string] | test.cpp:88:11:88:30 | mk_string_t_plus_one indirection [string] |
| test.cpp:90:19:90:24 | call to malloc | test.cpp:90:5:90:34 | ... = ... |
| test.cpp:91:5:91:7 | str indirection [string] | test.cpp:88:11:88:30 | mk_string_t_plus_one indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:99:13:99:15 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:129:17:129:19 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:137:17:137:19 | str indirection [string] |
@@ -34,17 +32,16 @@ edges
| test.cpp:137:17:137:19 | str indirection [string] | test.cpp:137:22:137:27 | string indirection |
| test.cpp:137:22:137:27 | string indirection | test.cpp:137:22:137:27 | string |
| test.cpp:147:5:147:34 | ... = ... | test.cpp:147:10:147:15 | str indirection [post update] [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:148:5:148:7 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:152:13:152:15 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:154:13:154:15 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:156:13:156:15 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:175:17:175:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:187:17:187:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:195:17:195:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:199:17:199:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:203:17:203:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:207:17:207:19 | str indirection [string] |
| test.cpp:147:19:147:24 | call to malloc | test.cpp:147:5:147:34 | ... = ... |
| test.cpp:148:5:148:7 | str indirection [string] | test.cpp:152:13:152:15 | str indirection [string] |
| test.cpp:148:5:148:7 | str indirection [string] | test.cpp:154:13:154:15 | str indirection [string] |
| test.cpp:148:5:148:7 | str indirection [string] | test.cpp:156:13:156:15 | str indirection [string] |
| test.cpp:148:5:148:7 | str indirection [string] | test.cpp:175:17:175:19 | str indirection [string] |
| test.cpp:148:5:148:7 | str indirection [string] | test.cpp:187:17:187:19 | str indirection [string] |
| test.cpp:148:5:148:7 | str indirection [string] | test.cpp:195:17:195:19 | str indirection [string] |
| test.cpp:148:5:148:7 | str indirection [string] | test.cpp:199:17:199:19 | str indirection [string] |
| test.cpp:148:5:148:7 | str indirection [string] | test.cpp:203:17:203:19 | str indirection [string] |
| test.cpp:148:5:148:7 | str indirection [string] | test.cpp:207:17:207:19 | str indirection [string] |
| test.cpp:152:13:152:15 | str indirection [string] | test.cpp:152:18:152:23 | string |
| test.cpp:152:13:152:15 | str indirection [string] | test.cpp:152:18:152:23 | string indirection |
| test.cpp:152:18:152:23 | string indirection | test.cpp:152:18:152:23 | string |
@@ -94,7 +91,6 @@ nodes
| test.cpp:18:5:18:30 | ... = ... | semmle.label | ... = ... |
| test.cpp:18:10:18:15 | str indirection [post update] [string] | semmle.label | str indirection [post update] [string] |
| test.cpp:18:19:18:24 | call to malloc | semmle.label | call to malloc |
| test.cpp:19:5:19:7 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | semmle.label | call to mk_string_t indirection [string] |
| test.cpp:42:13:42:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:42:18:42:23 | string | semmle.label | string |
@@ -109,7 +105,6 @@ nodes
| test.cpp:90:5:90:34 | ... = ... | semmle.label | ... = ... |
| test.cpp:90:10:90:15 | str indirection [post update] [string] | semmle.label | str indirection [post update] [string] |
| test.cpp:90:19:90:24 | call to malloc | semmle.label | call to malloc |
| test.cpp:91:5:91:7 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | semmle.label | call to mk_string_t_plus_one indirection [string] |
| test.cpp:99:13:99:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:99:18:99:23 | string | semmle.label | string |
@@ -123,7 +118,6 @@ nodes
| test.cpp:147:5:147:34 | ... = ... | semmle.label | ... = ... |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | semmle.label | str indirection [post update] [string] |
| test.cpp:147:19:147:24 | call to malloc | semmle.label | call to malloc |
| test.cpp:148:5:148:7 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:152:13:152:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:152:18:152:23 | string | semmle.label | string |
| test.cpp:152:18:152:23 | string indirection | semmle.label | string indirection |

View File

@@ -8,19 +8,13 @@ edges
| overflowdestination.cpp:23:45:23:48 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection |
| overflowdestination.cpp:23:45:23:48 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection |
| overflowdestination.cpp:43:8:43:10 | fgets output argument | overflowdestination.cpp:46:15:46:17 | src indirection |
| overflowdestination.cpp:50:52:50:54 | src indirection | overflowdestination.cpp:53:9:53:12 | memcpy output argument |
| overflowdestination.cpp:50:52:50:54 | src indirection | overflowdestination.cpp:53:15:53:17 | src indirection |
| overflowdestination.cpp:50:52:50:54 | src indirection | overflowdestination.cpp:53:15:53:17 | src indirection |
| overflowdestination.cpp:50:52:50:54 | src indirection | overflowdestination.cpp:54:9:54:12 | memcpy output argument |
| overflowdestination.cpp:53:9:53:12 | memcpy output argument | overflowdestination.cpp:54:9:54:12 | memcpy output argument |
| overflowdestination.cpp:54:9:54:12 | memcpy output argument | overflowdestination.cpp:54:9:54:12 | memcpy output argument |
| overflowdestination.cpp:57:52:57:54 | src indirection | overflowdestination.cpp:64:16:64:19 | src2 indirection |
| overflowdestination.cpp:57:52:57:54 | src indirection | overflowdestination.cpp:64:16:64:19 | src2 indirection |
| overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:75:30:75:32 | src indirection |
| overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:76:30:76:32 | src indirection |
| overflowdestination.cpp:75:30:75:32 | overflowdest_test2 output argument | overflowdestination.cpp:76:30:76:32 | src indirection |
| overflowdestination.cpp:75:30:75:32 | src indirection | overflowdestination.cpp:50:52:50:54 | src indirection |
| overflowdestination.cpp:75:30:75:32 | src indirection | overflowdestination.cpp:75:30:75:32 | overflowdest_test2 output argument |
| overflowdestination.cpp:76:30:76:32 | src indirection | overflowdestination.cpp:57:52:57:54 | src indirection |
nodes
| main.cpp:6:27:6:30 | argv indirection | semmle.label | argv indirection |
@@ -34,20 +28,15 @@ nodes
| overflowdestination.cpp:43:8:43:10 | fgets output argument | semmle.label | fgets output argument |
| overflowdestination.cpp:46:15:46:17 | src indirection | semmle.label | src indirection |
| overflowdestination.cpp:50:52:50:54 | src indirection | semmle.label | src indirection |
| overflowdestination.cpp:53:9:53:12 | memcpy output argument | semmle.label | memcpy output argument |
| overflowdestination.cpp:53:15:53:17 | src indirection | semmle.label | src indirection |
| overflowdestination.cpp:53:15:53:17 | src indirection | semmle.label | src indirection |
| overflowdestination.cpp:54:9:54:12 | memcpy output argument | semmle.label | memcpy output argument |
| overflowdestination.cpp:57:52:57:54 | src indirection | semmle.label | src indirection |
| overflowdestination.cpp:64:16:64:19 | src2 indirection | semmle.label | src2 indirection |
| overflowdestination.cpp:64:16:64:19 | src2 indirection | semmle.label | src2 indirection |
| overflowdestination.cpp:73:8:73:10 | fgets output argument | semmle.label | fgets output argument |
| overflowdestination.cpp:75:30:75:32 | overflowdest_test2 output argument | semmle.label | overflowdest_test2 output argument |
| overflowdestination.cpp:75:30:75:32 | src indirection | semmle.label | src indirection |
| overflowdestination.cpp:76:30:76:32 | src indirection | semmle.label | src indirection |
subpaths
| overflowdestination.cpp:75:30:75:32 | src indirection | overflowdestination.cpp:50:52:50:54 | src indirection | overflowdestination.cpp:53:9:53:12 | memcpy output argument | overflowdestination.cpp:75:30:75:32 | overflowdest_test2 output argument |
| overflowdestination.cpp:75:30:75:32 | src indirection | overflowdestination.cpp:50:52:50:54 | src indirection | overflowdestination.cpp:54:9:54:12 | memcpy output argument | overflowdestination.cpp:75:30:75:32 | overflowdest_test2 output argument |
#select
| overflowdestination.cpp:30:2:30:8 | call to strncpy | main.cpp:6:27:6:30 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |
| overflowdestination.cpp:30:2:30:8 | call to strncpy | main.cpp:6:27:6:30 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. |

View File

@@ -1,7 +1,6 @@
| test.c:4:14:4:18 | ... < ... | Comparison between $@ of type char and $@ of wider type int. | test.c:3:7:3:7 | c | c | test.c:2:17:2:17 | x | x |
| test.c:9:14:9:18 | ... > ... | Comparison between $@ of type char and $@ of wider type int. | test.c:8:7:8:7 | c | c | test.c:7:17:7:17 | x | x |
| test.c:14:14:14:18 | ... < ... | Comparison between $@ of type short and $@ of wider type int. | test.c:13:8:13:8 | s | s | test.c:12:17:12:17 | x | x |
| test.c:42:15:42:29 | ... < ... | Comparison between $@ of type short and $@ of wider type int. | test.c:41:9:41:10 | s1 | s1 | test.c:42:20:42:29 | 65535 | 65535 |
| test.c:65:14:65:18 | ... < ... | Comparison between $@ of type short and $@ of wider type int. | test.c:64:8:64:8 | s | s | test.c:63:17:63:17 | x | x |
| test.c:87:14:87:18 | ... < ... | Comparison between $@ of type unsigned char and $@ of wider type unsigned int. | test.c:83:16:83:16 | c | c | test.c:84:15:84:15 | x | x |
| test.c:91:14:91:23 | ... < ... | Comparison between $@ of type unsigned char and $@ of wider type int. | test.c:83:16:83:16 | c | c | test.c:91:18:91:23 | 65280 | 65280 |
@@ -14,4 +13,3 @@
| test.c:107:14:107:26 | ... < ... | Comparison between $@ of type unsigned char and $@ of wider type unsigned int. | test.c:83:16:83:16 | c | c | test.c:107:19:107:25 | ... >> ... | ... >> ... |
| test.c:128:15:128:21 | ... < ... | Comparison between $@ of type unsigned char and $@ of wider type unsigned int. | test.c:121:16:121:17 | uc | uc | test.c:123:19:123:20 | sz | sz |
| test.c:139:15:139:21 | ... < ... | Comparison between $@ of type unsigned char and $@ of wider type unsigned int. | test.c:121:16:121:17 | uc | uc | test.c:123:19:123:20 | sz | sz |
| test.c:156:9:156:14 | ... < ... | Comparison between $@ of type short and $@ of wider type int. | test.c:150:8:150:8 | s | s | test.c:151:6:151:7 | sx | sx |

View File

@@ -39,7 +39,7 @@ void test5 () {
void test6() {
short s1;
for (s1 = 0; s1 < 0x0000ffff; s1++) {} // BAD
for (s1 = 0; s1 < 0x0000ffff; s1++) {}
}
void test7(long long l) {
@@ -145,22 +145,3 @@ void test13() {
sz = (unsigned)sx & (unsigned)sy;
for (uc = 0; uc < sz; uc++) {} // GOOD
}
void test14() {
short s = 0;
int sx = 0x7FFF + 1;
// BAD: 's' is compared with a value of a wider type.
// 's' overflows before reaching 'sx',
// causing an infinite loop
while (s < sx) {
s += 1;
}
unsigned int ux = 0;
// GOOD: 'ux' has a type at least as wide as 'max_get'
while (ux < sx) {
ux += 1;
}
}

View File

@@ -6,4 +6,3 @@ dependencies:
codeql/cpp-queries: ${workspace}
extractor: cpp
tests: .
warnOnImplicitThis: true

View File

@@ -24,5 +24,5 @@ Microsoft.Win32,,,8,,,,,,,,,,,,,,8,
MySql.Data.MySqlClient,48,,,,,,,,,,,48,,,,,,
Newtonsoft.Json,,,91,,,,,,,,,,,,,,73,18
ServiceStack,194,,7,27,,,,,75,,,92,,,,,7,
System,65,25,12148,,8,8,9,,,4,3,33,1,17,3,4,10163,1985
System,65,25,12157,,8,8,9,,,4,3,33,1,17,3,4,10163,1994
Windows.Security.Cryptography.Core,1,,,,,,,1,,,,,,,,,,
1 package sink source summary sink:code-injection sink:encryption-decryptor sink:encryption-encryptor sink:encryption-keyprop sink:encryption-symmetrickey sink:file-content-store sink:html-injection sink:js-injection sink:sql-injection source:file source:file-write source:local source:remote summary:taint summary:value
24 MySql.Data.MySqlClient 48 48
25 Newtonsoft.Json 91 73 18
26 ServiceStack 194 7 27 75 92 7
27 System 65 25 12148 12157 8 8 9 4 3 33 1 17 3 4 10163 1985 1994
28 Windows.Security.Cryptography.Core 1 1

View File

@@ -8,7 +8,7 @@ C# framework & library support
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE-079` :sub:`Cross-site scripting`
`ServiceStack <https://servicestack.net/>`_,"``ServiceStack.*``, ``ServiceStack``",,7,194,
System,"``System.*``, ``System``",25,12148,65,7
System,"``System.*``, ``System``",25,12157,65,7
Others,"``Dapper``, ``JsonToItemsTaskFactory``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.CSharp``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Caching.Distributed``, ``Microsoft.Extensions.Caching.Memory``, ``Microsoft.Extensions.Configuration``, ``Microsoft.Extensions.DependencyInjection``, ``Microsoft.Extensions.DependencyModel``, ``Microsoft.Extensions.FileProviders``, ``Microsoft.Extensions.FileSystemGlobbing``, ``Microsoft.Extensions.Hosting``, ``Microsoft.Extensions.Http``, ``Microsoft.Extensions.Logging``, ``Microsoft.Extensions.Options``, ``Microsoft.Extensions.Primitives``, ``Microsoft.Interop``, ``Microsoft.NET.Build.Tasks``, ``Microsoft.NETCore.Platforms.BuildTasks``, ``Microsoft.VisualBasic``, ``Microsoft.Win32``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``, ``Windows.Security.Cryptography.Core``",,568,138,
Totals,,25,12723,397,7
Totals,,25,12732,397,7

View File

@@ -2,4 +2,3 @@ name: codeql/csharp-downgrades
groups: csharp
downgrades: .
library: true
warnOnImplicitThis: true

View File

@@ -16,12 +16,12 @@ namespace Semmle.BuildAnalyser
/// Locate all reference files and index them.
/// </summary>
/// <param name="dirs">Directories to search.</param>
/// <param name="progressMonitor">Callback for progress.</param>
public AssemblyCache(IEnumerable<string> dirs, ProgressMonitor progressMonitor)
/// <param name="progress">Callback for progress.</param>
public AssemblyCache(IEnumerable<string> dirs, IProgressMonitor progress)
{
foreach (var dir in dirs)
{
progressMonitor.FindingFiles(dir);
progress.FindingFiles(dir);
AddReferenceDirectory(dir);
}
IndexReferences();
@@ -41,8 +41,6 @@ namespace Semmle.BuildAnalyser
}
}
private static readonly Version emptyVersion = new Version(0, 0, 0, 0);
/// <summary>
/// Indexes all DLLs we have located.
/// Because this is a potentially time-consuming operation, it is put into a separate stage.
@@ -57,9 +55,7 @@ namespace Semmle.BuildAnalyser
// Index "assemblyInfo" by version string
// The OrderBy is used to ensure that we by default select the highest version number.
foreach (var info in assemblyInfoByFileName.Values
.OrderBy(info => info.Name)
.ThenBy(info => info.Version ?? emptyVersion))
foreach (var info in assemblyInfoByFileName.Values.OrderBy(info => info.Id))
{
foreach (var index in info.IndexStrings)
assemblyInfoById[index] = info;

View File

@@ -8,104 +8,121 @@ using System.Threading.Tasks;
using System.Collections.Concurrent;
using System.Text;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
namespace Semmle.BuildAnalyser
{
/// <summary>
/// The output of a build analysis.
/// </summary>
internal interface IBuildAnalysis
{
/// <summary>
/// Full filepaths of external references.
/// </summary>
IEnumerable<string> ReferenceFiles { get; }
/// <summary>
/// Full filepaths of C# source files from project files.
/// </summary>
IEnumerable<string> ProjectSourceFiles { get; }
/// <summary>
/// Full filepaths of C# source files in the filesystem.
/// </summary>
IEnumerable<string> AllSourceFiles { get; }
/// <summary>
/// The assembly IDs which could not be resolved.
/// </summary>
IEnumerable<string> UnresolvedReferences { get; }
/// <summary>
/// List of source files referenced by projects but
/// which were not found in the filesystem.
/// </summary>
IEnumerable<string> MissingSourceFiles { get; }
}
/// <summary>
/// Main implementation of the build analysis.
/// </summary>
internal sealed partial class BuildAnalysis : IDisposable
internal sealed class BuildAnalysis : IBuildAnalysis, IDisposable
{
private readonly AssemblyCache assemblyCache;
private readonly ProgressMonitor progressMonitor;
private readonly IProgressMonitor progressMonitor;
private readonly IDictionary<string, bool> usedReferences = new ConcurrentDictionary<string, bool>();
private readonly IDictionary<string, bool> sources = new ConcurrentDictionary<string, bool>();
private readonly IDictionary<string, string> unresolvedReferences = new ConcurrentDictionary<string, string>();
private int failedProjects;
private int succeededProjects;
private int failedProjects, succeededProjects;
private readonly string[] allSources;
private int conflictedReferences = 0;
private readonly Options options;
private readonly DirectoryInfo sourceDir;
private readonly DotNet dotnet;
/// <summary>
/// Performs a C# build analysis.
/// </summary>
/// <param name="options">Analysis options from the command line.</param>
/// <param name="progressMonitor">Display of analysis progress.</param>
public BuildAnalysis(Options options, ProgressMonitor progressMonitor)
/// <param name="progress">Display of analysis progress.</param>
public BuildAnalysis(Options options, IProgressMonitor progress)
{
var startTime = DateTime.Now;
this.options = options;
this.progressMonitor = progressMonitor;
this.sourceDir = new DirectoryInfo(options.SrcDir);
progressMonitor = progress;
var sourceDir = new DirectoryInfo(options.SrcDir);
try
{
this.dotnet = new DotNet(progressMonitor);
}
catch
{
progressMonitor.MissingDotNet();
throw;
}
progressMonitor.FindingFiles(options.SrcDir);
this.progressMonitor.FindingFiles(options.SrcDir);
this.allSources = GetFiles("*.cs").ToArray();
var allProjects = GetFiles("*.csproj");
var solutions = options.SolutionFile is not null
? new[] { options.SolutionFile }
: GetFiles("*.sln");
allSources = sourceDir.GetFiles("*.cs", SearchOption.AllDirectories)
.Select(d => d.FullName)
.Where(d => !options.ExcludesFile(d))
.ToArray();
var dllDirNames = options.DllDirs.Select(Path.GetFullPath).ToList();
// Find DLLs in the .Net Framework
if (options.ScanNetFrameworkDlls)
{
var runtimeLocation = new Runtime(dotnet).GetRuntime(options.UseSelfContainedDotnet);
progressMonitor.Log(Util.Logging.Severity.Debug, $"Runtime location selected: {runtimeLocation}");
dllDirNames.Add(runtimeLocation);
}
if (options.UseMscorlib)
{
UseReference(typeof(object).Assembly.Location);
}
packageDirectory = new TemporaryDirectory(ComputeTempDirectory(sourceDir.FullName));
if (options.UseNuGet)
{
dllDirNames.Add(packageDirectory.DirInfo.FullName);
try
{
var nuget = new NugetPackages(sourceDir.FullName, packageDirectory, progressMonitor);
nuget.InstallPackages();
var nuget = new NugetPackages(sourceDir.FullName, packageDirectory);
nuget.InstallPackages(progressMonitor);
}
catch (FileNotFoundException)
{
progressMonitor.MissingNuGet();
}
// TODO: remove the below when the required SDK is installed
using (new FileRenamer(sourceDir.GetFiles("global.json", SearchOption.AllDirectories)))
{
Restore(solutions);
Restore(allProjects);
DownloadMissingPackages(allProjects);
}
}
assemblyCache = new AssemblyCache(dllDirNames, progressMonitor);
AnalyseSolutions(solutions);
foreach (var filename in assemblyCache.AllAssemblies.Select(a => a.Filename))
// Find DLLs in the .Net Framework
if (options.ScanNetFrameworkDlls)
{
UseReference(filename);
var runtimeLocation = Runtime.GetRuntime(options.UseSelfContainedDotnet);
progressMonitor.Log(Util.Logging.Severity.Debug, $"Runtime location selected: {runtimeLocation}");
dllDirNames.Add(runtimeLocation);
}
// These files can sometimes prevent `dotnet restore` from working correctly.
using (new FileRenamer(sourceDir.GetFiles("global.json", SearchOption.AllDirectories)))
using (new FileRenamer(sourceDir.GetFiles("Directory.Build.props", SearchOption.AllDirectories)))
{
var solutions = options.SolutionFile is not null ?
new[] { options.SolutionFile } :
sourceDir.GetFiles("*.sln", SearchOption.AllDirectories).Select(d => d.FullName);
if (options.UseNuGet)
{
RestoreSolutions(solutions);
}
dllDirNames.Add(packageDirectory.DirInfo.FullName);
assemblyCache = new BuildAnalyser.AssemblyCache(dllDirNames, progress);
AnalyseSolutions(solutions);
foreach (var filename in assemblyCache.AllAssemblies.Select(a => a.Filename))
UseReference(filename);
}
if (options.UseMscorlib)
{
UseReference(typeof(object).Assembly.Location);
}
ResolveConflicts();
@@ -133,13 +150,6 @@ namespace Semmle.BuildAnalyser
DateTime.Now - startTime);
}
private IEnumerable<string> GetFiles(string pattern, bool recurseSubdirectories = true)
{
return sourceDir.GetFiles(pattern, new EnumerationOptions { RecurseSubdirectories = recurseSubdirectories, MatchCasing = MatchCasing.CaseInsensitive })
.Select(d => d.FullName)
.Where(d => !options.ExcludesFile(d));
}
/// <summary>
/// Computes a unique temp directory for the packages associated
/// with this source tree. Use a SHA1 of the directory name.
@@ -149,7 +159,9 @@ namespace Semmle.BuildAnalyser
private static string ComputeTempDirectory(string srcDir)
{
var bytes = Encoding.Unicode.GetBytes(srcDir);
var sha = SHA1.HashData(bytes);
using var sha1 = SHA1.Create();
var sha = sha1.ComputeHash(bytes);
var sb = new StringBuilder();
foreach (var b in sha.Take(8))
sb.AppendFormat("{0:x2}", b);
@@ -184,15 +196,12 @@ namespace Semmle.BuildAnalyser
// Pick the highest version for each assembly name
foreach (var r in sortedReferences)
{
finalAssemblyList[r.Name] = r;
}
// Update the used references list
usedReferences.Clear();
foreach (var r in finalAssemblyList.Select(r => r.Value.Filename))
{
UseReference(r);
}
// Report the results
foreach (var r in sortedReferences)
@@ -270,9 +279,7 @@ namespace Semmle.BuildAnalyser
private void AnalyseProjectFiles(IEnumerable<FileInfo> projectFiles)
{
foreach (var proj in projectFiles)
{
AnalyseProject(proj);
}
}
private void AnalyseProject(FileInfo project)
@@ -318,106 +325,36 @@ namespace Semmle.BuildAnalyser
}
private bool Restore(string target, string? pathToNugetConfig = null)
private void Restore(string projectOrSolution)
{
return dotnet.RestoreToDirectory(target, packageDirectory.DirInfo.FullName, pathToNugetConfig);
}
private void Restore(IEnumerable<string> targets, string? pathToNugetConfig = null)
{
foreach (var target in targets)
int exit;
try
{
Restore(target, pathToNugetConfig);
exit = DotNet.RestoreToDirectory(projectOrSolution, packageDirectory.DirInfo.FullName);
}
catch (FileNotFoundException)
{
exit = 2;
}
switch (exit)
{
case 0:
case 1:
// No errors
break;
default:
progressMonitor.CommandFailed("dotnet", $"restore \"{projectOrSolution}\"", exit);
break;
}
}
private void DownloadMissingPackages(IEnumerable<string> restoreTargets)
public void RestoreSolutions(IEnumerable<string> solutions)
{
var alreadyDownloadedPackages = Directory.GetDirectories(packageDirectory.DirInfo.FullName).Select(d => Path.GetFileName(d).ToLowerInvariant()).ToHashSet();
var notYetDownloadedPackages = new HashSet<string>();
var nugetConfigs = GetFiles("nuget.config", recurseSubdirectories: true).ToArray();
string? nugetConfig = null;
if (nugetConfigs.Length > 1)
{
progressMonitor.MultipleNugetConfig(nugetConfigs);
nugetConfig = GetFiles("nuget.config", recurseSubdirectories: false).FirstOrDefault();
if (nugetConfig == null)
{
progressMonitor.NoTopLevelNugetConfig();
}
}
else
{
nugetConfig = nugetConfigs.FirstOrDefault();
}
var allFiles = GetFiles("*.*");
foreach (var file in allFiles)
{
try
{
using var sr = new StreamReader(file);
ReadOnlySpan<char> line;
while ((line = sr.ReadLine()) != null)
{
foreach (var valueMatch in PackageReference().EnumerateMatches(line))
{
// We can't get the group from the ValueMatch, so doing it manually:
var match = line.Slice(valueMatch.Index, valueMatch.Length);
var includeIndex = match.IndexOf("Include", StringComparison.InvariantCultureIgnoreCase);
if (includeIndex == -1)
{
continue;
}
match = match.Slice(includeIndex + "Include".Length + 1);
var quoteIndex1 = match.IndexOf("\"");
var quoteIndex2 = match.Slice(quoteIndex1 + 1).IndexOf("\"");
var packageName = match.Slice(quoteIndex1 + 1, quoteIndex2).ToString().ToLowerInvariant();
if (!alreadyDownloadedPackages.Contains(packageName))
{
notYetDownloadedPackages.Add(packageName);
}
}
}
}
catch (Exception ex)
{
progressMonitor.FailedToReadFile(file, ex);
continue;
}
}
foreach (var package in notYetDownloadedPackages)
{
progressMonitor.NugetInstall(package);
using var tempDir = new TemporaryDirectory(ComputeTempDirectory(package));
var success = dotnet.New(tempDir.DirInfo.FullName);
if (!success)
{
continue;
}
success = dotnet.AddPackage(tempDir.DirInfo.FullName, package);
if (!success)
{
continue;
}
success = Restore(tempDir.DirInfo.FullName, nugetConfig);
// TODO: the restore might fail, we could retry with a prerelease (*-* instead of *) version of the package.
if (!success)
{
progressMonitor.FailedToRestoreNugetPackage(package);
}
}
Parallel.ForEach(solutions, new ParallelOptions { MaxDegreeOfParallelism = 4 }, Restore);
}
private void AnalyseSolutions(IEnumerable<string> solutions)
public void AnalyseSolutions(IEnumerable<string> solutions)
{
Parallel.ForEach(solutions, new ParallelOptions { MaxDegreeOfParallelism = 4 }, solutionFile =>
{
@@ -438,8 +375,5 @@ namespace Semmle.BuildAnalyser
{
packageDirectory?.Dispose();
}
[GeneratedRegex("<PackageReference .*Include=\"(.*?)\".*/>", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline)]
private static partial Regex PackageReference();
}
}

View File

@@ -1,96 +1,17 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Semmle.Util;
using System.Diagnostics;
namespace Semmle.BuildAnalyser
{
internal interface IDotNet
{
bool RestoreToDirectory(string project, string directory, string? pathToNugetConfig = null);
bool New(string folder);
bool AddPackage(string folder, string package);
public IList<string> GetListedRuntimes();
}
/// <summary>
/// Utilities to run the "dotnet" command.
/// </summary>
internal class DotNet : IDotNet
internal static class DotNet
{
private const string dotnet = "dotnet";
private readonly ProgressMonitor progressMonitor;
public DotNet(ProgressMonitor progressMonitor)
public static int RestoreToDirectory(string projectOrSolutionFile, string packageDirectory)
{
this.progressMonitor = progressMonitor;
Info();
}
private void Info()
{
// TODO: make sure the below `dotnet` version is matching the one specified in global.json
progressMonitor.RunningProcess($"{dotnet} --info");
using var proc = Process.Start(dotnet, "--info");
using var proc = Process.Start("dotnet", $"restore --no-dependencies \"{projectOrSolutionFile}\" --packages \"{packageDirectory}\" /p:DisableImplicitNuGetFallbackFolder=true");
proc.WaitForExit();
var ret = proc.ExitCode;
if (ret != 0)
{
progressMonitor.CommandFailed(dotnet, "--info", ret);
throw new Exception($"{dotnet} --info failed with exit code {ret}.");
}
}
private bool RunCommand(string args)
{
progressMonitor.RunningProcess($"{dotnet} {args}");
using var proc = Process.Start(dotnet, args);
proc.WaitForExit();
if (proc.ExitCode != 0)
{
progressMonitor.CommandFailed(dotnet, args, proc.ExitCode);
return false;
}
return true;
}
public bool RestoreToDirectory(string projectOrSolutionFile, string packageDirectory, string? pathToNugetConfig = null)
{
var args = $"restore --no-dependencies \"{projectOrSolutionFile}\" --packages \"{packageDirectory}\" /p:DisableImplicitNuGetFallbackFolder=true";
if (pathToNugetConfig != null)
args += $" --configfile \"{pathToNugetConfig}\"";
return RunCommand(args);
}
public bool New(string folder)
{
var args = $"new console --no-restore --output \"{folder}\"";
return RunCommand(args);
}
public bool AddPackage(string folder, string package)
{
var args = $"add \"{folder}\" package \"{package}\" --no-restore";
return RunCommand(args);
}
public IList<string> GetListedRuntimes()
{
var args = "--list-runtimes";
var pi = new ProcessStartInfo(dotnet, args)
{
RedirectStandardOutput = true,
UseShellExecute = false
};
var exitCode = pi.ReadOutput(out var runtimes);
if (exitCode != 0)
{
progressMonitor.CommandFailed(dotnet, args, exitCode);
return new List<string>();
}
return runtimes;
return proc.ExitCode;
}
}
}

View File

@@ -17,24 +17,26 @@ namespace Semmle.BuildAnalyser
/// <summary>
/// Create the package manager for a specified source tree.
/// </summary>
public NugetPackages(string sourceDir, TemporaryDirectory packageDirectory, ProgressMonitor progressMonitor)
/// <param name="sourceDir">The source directory.</param>
public NugetPackages(string sourceDir, TemporaryDirectory packageDirectory)
{
SourceDirectory = sourceDir;
PackageDirectory = packageDirectory;
this.progressMonitor = progressMonitor;
// Expect nuget.exe to be in a `nuget` directory under the directory containing this exe.
var currentAssembly = System.Reflection.Assembly.GetExecutingAssembly().Location;
var directory = Path.GetDirectoryName(currentAssembly)
?? throw new FileNotFoundException($"Directory path '{currentAssembly}' of current assembly is null");
var directory = Path.GetDirectoryName(currentAssembly);
if (directory is null)
throw new FileNotFoundException($"Directory path '{currentAssembly}' of current assembly is null");
nugetExe = Path.Combine(directory, "nuget", "nuget.exe");
if (!File.Exists(nugetExe))
throw new FileNotFoundException(string.Format("NuGet could not be found at {0}", nugetExe));
packages = new DirectoryInfo(SourceDirectory)
.EnumerateFiles("packages.config", SearchOption.AllDirectories)
.ToArray();
packages = new DirectoryInfo(SourceDirectory).
EnumerateFiles("packages.config", SearchOption.AllDirectories).
ToArray();
}
// List of package files to download.
@@ -49,11 +51,11 @@ namespace Semmle.BuildAnalyser
/// Download the packages to the temp folder.
/// </summary>
/// <param name="pm">The progress monitor used for reporting errors etc.</param>
public void InstallPackages()
public void InstallPackages(IProgressMonitor pm)
{
foreach (var package in packages)
{
RestoreNugetPackage(package.FullName);
RestoreNugetPackage(package.FullName, pm);
}
}
@@ -78,9 +80,9 @@ namespace Semmle.BuildAnalyser
/// </summary>
/// <param name="package">The package file.</param>
/// <param name="pm">Where to log progress/errors.</param>
private void RestoreNugetPackage(string package)
private void RestoreNugetPackage(string package, IProgressMonitor pm)
{
progressMonitor.NugetInstall(package);
pm.NugetInstall(package);
/* Use nuget.exe to install a package.
* Note that there is a clutch of NuGet assemblies which could be used to
@@ -113,7 +115,7 @@ namespace Semmle.BuildAnalyser
if (p is null)
{
progressMonitor.FailedNugetCommand(pi.FileName, pi.Arguments, "Couldn't start process.");
pm.FailedNugetCommand(pi.FileName, pi.Arguments, "Couldn't start process.");
return;
}
@@ -123,17 +125,16 @@ namespace Semmle.BuildAnalyser
p.WaitForExit();
if (p.ExitCode != 0)
{
progressMonitor.FailedNugetCommand(pi.FileName, pi.Arguments, output + error);
pm.FailedNugetCommand(pi.FileName, pi.Arguments, output + error);
}
}
catch (Exception ex)
when (ex is System.ComponentModel.Win32Exception || ex is FileNotFoundException)
{
progressMonitor.FailedNugetCommand(pi.FileName, pi.Arguments, ex.Message);
pm.FailedNugetCommand(pi.FileName, pi.Arguments, ex.Message);
}
}
private readonly string nugetExe;
private readonly ProgressMonitor progressMonitor;
}
}

View File

@@ -3,7 +3,27 @@ using System;
namespace Semmle.BuildAnalyser
{
internal class ProgressMonitor
/// <summary>
/// Callback for various events that may happen during the build analysis.
/// </summary>
internal interface IProgressMonitor
{
void FindingFiles(string dir);
void UnresolvedReference(string id, string project);
void AnalysingSolution(string filename);
void FailedProjectFile(string filename, string reason);
void FailedNugetCommand(string exe, string args, string message);
void NugetInstall(string package);
void ResolvedReference(string filename);
void Summary(int existingSources, int usedSources, int missingSources, int references, int unresolvedReferences, int resolvedConflicts, int totalProjects, int failedProjects, TimeSpan analysisTime);
void Log(Severity severity, string message);
void ResolvedConflict(string asm1, string asm2);
void MissingProject(string projectFile);
void CommandFailed(string exe, string arguments, int exitCode);
void MissingNuGet();
}
internal class ProgressMonitor : IProgressMonitor
{
private readonly ILogger logger;
@@ -97,36 +117,5 @@ namespace Semmle.BuildAnalyser
{
logger.Log(Severity.Error, "Missing nuget.exe");
}
public void MissingDotNet()
{
logger.Log(Severity.Error, "Missing dotnet CLI");
}
public void RunningProcess(string command)
{
logger.Log(Severity.Info, $"Running {command}");
}
public void FailedToRestoreNugetPackage(string package)
{
logger.Log(Severity.Info, $"Failed to restore nuget package {package}");
}
public void FailedToReadFile(string file, Exception ex)
{
logger.Log(Severity.Info, $"Failed to read file {file}");
logger.Log(Severity.Debug, $"Failed to read file {file}, exception: {ex}");
}
public void MultipleNugetConfig(string[] nugetConfigs)
{
logger.Log(Severity.Info, $"Found multiple nuget.config files: {string.Join(", ", nugetConfigs)}.");
}
internal void NoTopLevelNugetConfig()
{
logger.Log(Severity.Info, $"Could not find a top-level nuget.config file.");
}
}
}

View File

@@ -1,5 +1,4 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
@@ -14,9 +13,6 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Expose internals for testing purposes.
[assembly: InternalsVisibleTo("Semmle.Extraction.Tests")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.

View File

@@ -3,8 +3,6 @@ using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Semmle.BuildAnalyser;
using Semmle.Util;
namespace Semmle.Extraction.CSharp.Standalone
@@ -12,105 +10,31 @@ namespace Semmle.Extraction.CSharp.Standalone
/// <summary>
/// Locates .NET Runtimes.
/// </summary>
internal partial class Runtime
internal static class Runtime
{
private const string netCoreApp = "Microsoft.NETCore.App";
private const string aspNetCoreApp = "Microsoft.AspNetCore.App";
private readonly IDotNet dotNet;
private static string ExecutingRuntime => RuntimeEnvironment.GetRuntimeDirectory();
public Runtime(IDotNet dotNet) => this.dotNet = dotNet;
internal sealed class RuntimeVersion : IComparable<RuntimeVersion>
{
private readonly string dir;
private readonly Version version;
private readonly Version? preReleaseVersion;
private readonly string? preReleaseVersionType;
private bool IsPreRelease => preReleaseVersionType is not null && preReleaseVersion is not null;
public string FullPath
{
get
{
var preRelease = IsPreRelease ? $"-{preReleaseVersionType}.{preReleaseVersion}" : "";
var version = this.version + preRelease;
return Path.Combine(dir, version);
}
}
public RuntimeVersion(string dir, string version, string preReleaseVersionType, string preReleaseVersion)
{
this.dir = dir;
this.version = Version.Parse(version);
if (!string.IsNullOrEmpty(preReleaseVersion) && !string.IsNullOrEmpty(preReleaseVersionType))
{
this.preReleaseVersionType = preReleaseVersionType;
this.preReleaseVersion = Version.Parse(preReleaseVersion);
}
}
public int CompareTo(RuntimeVersion? other)
{
var c = version.CompareTo(other?.version);
if (c == 0 && IsPreRelease)
{
if (!other!.IsPreRelease)
{
return -1;
}
// Both are pre-release like runtime versions.
// The pre-release version types are sorted alphabetically (e.g. alpha, beta, preview, rc)
// and the pre-release version types are more important that the pre-release version numbers.
return preReleaseVersionType != other!.preReleaseVersionType
? preReleaseVersionType!.CompareTo(other!.preReleaseVersionType)
: preReleaseVersion!.CompareTo(other!.preReleaseVersion);
}
return c;
}
public override bool Equals(object? obj) =>
obj is not null && obj is RuntimeVersion other && other.FullPath == FullPath;
public override int GetHashCode() => FullPath.GetHashCode();
public override string ToString() => FullPath;
}
[GeneratedRegex(@"^(\S+)\s(\d+\.\d+\.\d+)(-([a-z]+)\.(\d+\.\d+\.\d+))?\s\[(\S+)\]$")]
private static partial Regex RuntimeRegex();
/// <summary>
/// Parses the output of `dotnet --list-runtimes` to get a map from a runtime to the location of
/// the newest version of the runtime.
/// It is assume that the format of a listed runtime is something like:
/// Microsoft.NETCore.App 7.0.2 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
/// Locates .NET Core Runtimes.
/// </summary>
private static Dictionary<string, RuntimeVersion> ParseRuntimes(IList<string> listed)
private static IEnumerable<string> CoreRuntimes
{
// Parse listed runtimes.
var runtimes = new Dictionary<string, RuntimeVersion>();
listed.ForEach(r =>
get
{
var match = RuntimeRegex().Match(r);
if (match.Success)
var dotnetPath = FileUtils.FindProgramOnPath(Win32.IsWindows() ? "dotnet.exe" : "dotnet");
var dotnetDirs = dotnetPath is not null
? new[] { dotnetPath }
: new[] { "/usr/share/dotnet", @"C:\Program Files\dotnet" };
var coreDirs = dotnetDirs.Select(d => Path.Combine(d, "shared", "Microsoft.NETCore.App"));
var dir = coreDirs.FirstOrDefault(Directory.Exists);
if (dir is not null)
{
runtimes.AddOrUpdate(match.Groups[1].Value, new RuntimeVersion(match.Groups[6].Value, match.Groups[2].Value, match.Groups[4].Value, match.Groups[5].Value));
return Directory.EnumerateDirectories(dir).OrderByDescending(Path.GetFileName);
}
});
return runtimes;
}
/// <summary>
/// Returns a dictionary mapping runtimes to their newest version.
/// </summary>
internal Dictionary<string, RuntimeVersion> GetNewestRuntimes()
{
var listed = dotNet.GetListedRuntimes();
return ParseRuntimes(listed);
return Enumerable.Empty<string>();
}
}
/// <summary>
@@ -145,33 +69,24 @@ namespace Semmle.Extraction.CSharp.Standalone
}
}
private IEnumerable<string> GetRuntimes()
{
// Gets the newest version of the installed runtimes.
var newestRuntimes = GetNewestRuntimes();
// Location of the newest .NET Core Runtime.
if (newestRuntimes.TryGetValue(netCoreApp, out var netCoreVersion))
{
yield return netCoreVersion.FullPath;
}
// Location of the newest ASP.NET Core Runtime.
if (newestRuntimes.TryGetValue(aspNetCoreApp, out var aspNetCoreVersion))
{
yield return aspNetCoreVersion.FullPath;
}
foreach (var r in DesktopRuntimes)
yield return r;
// A bad choice if it's the self-contained runtime distributed in codeql dist.
yield return ExecutingRuntime;
}
/// <summary>
/// Gets the .NET runtime location to use for extraction
/// </summary>
public string GetRuntime(bool useSelfContained) => useSelfContained ? ExecutingRuntime : GetRuntimes().First();
public static string GetRuntime(bool useSelfContained) => useSelfContained ? ExecutingRuntime : Runtimes.First();
private static IEnumerable<string> Runtimes
{
get
{
foreach (var r in CoreRuntimes)
yield return r;
foreach (var r in DesktopRuntimes)
yield return r;
// A bad choice if it's the self-contained runtime distributed in codeql dist.
yield return ExecutingRuntime;
}
}
}
}

View File

@@ -100,7 +100,7 @@ namespace Semmle.Extraction.CSharp
// Figure out if it's dotnet core
var netCoreProjectFile = root.GetAttribute("Sdk").StartsWith("Microsoft.NET.Sdk");
var netCoreProjectFile = root.GetAttribute("Sdk") == "Microsoft.NET.Sdk";
if (netCoreProjectFile)
{

View File

@@ -1,102 +0,0 @@
using Xunit;
using System.Collections.Generic;
using Semmle.BuildAnalyser;
using Semmle.Extraction.CSharp.Standalone;
namespace Semmle.Extraction.Tests
{
internal class DotNetStub : IDotNet
{
private readonly IList<string> runtimes;
public DotNetStub(IList<string> runtimes) => this.runtimes = runtimes;
public bool AddPackage(string folder, string package) => true;
public bool New(string folder) => true;
public bool RestoreToDirectory(string project, string directory, string? pathToNugetConfig = null) => true;
public IList<string> GetListedRuntimes() => runtimes;
}
public class RuntimeTests
{
[Fact]
public void TestRuntime1()
{
// Setup
var listedRuntimes = new List<string> {
"Microsoft.AspNetCore.App 5.0.12 [/path/dotnet/shared/Microsoft.AspNetCore.App]",
"Microsoft.AspNetCore.App 6.0.4 [/path/dotnet/shared/Microsoft.AspNetCore.App]",
"Microsoft.AspNetCore.App 7.0.0 [/path/dotnet/shared/Microsoft.AspNetCore.App]",
"Microsoft.AspNetCore.App 7.0.2 [/path/dotnet/shared/Microsoft.AspNetCore.App]",
"Microsoft.NETCore.App 5.0.12 [/path/dotnet/shared/Microsoft.NETCore.App]",
"Microsoft.NETCore.App 6.0.4 [/path/dotnet/shared/Microsoft.NETCore.App]",
"Microsoft.NETCore.App 7.0.0 [/path/dotnet/shared/Microsoft.NETCore.App]",
"Microsoft.NETCore.App 7.0.2 [/path/dotnet/shared/Microsoft.NETCore.App]"
};
var dotnet = new DotNetStub(listedRuntimes);
var runtime = new Runtime(dotnet);
// Execute
var runtimes = runtime.GetNewestRuntimes();
// Verify
Assert.Equal(2, runtimes.Count);
Assert.True(runtimes.TryGetValue("Microsoft.AspNetCore.App", out var aspNetCoreApp));
Assert.Equal("/path/dotnet/shared/Microsoft.AspNetCore.App/7.0.2", aspNetCoreApp.FullPath);
Assert.True(runtimes.TryGetValue("Microsoft.NETCore.App", out var netCoreApp));
Assert.Equal("/path/dotnet/shared/Microsoft.NETCore.App/7.0.2", netCoreApp.FullPath);
}
[Fact]
public void TestRuntime2()
{
// Setup
var listedRuntimes = new List<string>
{
"Microsoft.NETCore.App 7.0.2 [/path/dotnet/shared/Microsoft.NETCore.App]",
"Microsoft.NETCore.App 8.0.0-preview.5.43280.8 [/path/dotnet/shared/Microsoft.NETCore.App]",
"Microsoft.NETCore.App 8.0.0-preview.5.23280.8 [/path/dotnet/shared/Microsoft.NETCore.App]"
};
var dotnet = new DotNetStub(listedRuntimes);
var runtime = new Runtime(dotnet);
// Execute
var runtimes = runtime.GetNewestRuntimes();
// Verify
Assert.Single(runtimes);
Assert.True(runtimes.TryGetValue("Microsoft.NETCore.App", out var netCoreApp));
Assert.Equal("/path/dotnet/shared/Microsoft.NETCore.App/8.0.0-preview.5.43280.8", netCoreApp.FullPath);
}
[Fact]
public void TestRuntime3()
{
// Setup
var listedRuntimes = new List<string>
{
"Microsoft.NETCore.App 7.0.2 [/path/dotnet/shared/Microsoft.NETCore.App]",
"Microsoft.NETCore.App 8.0.0-rc.4.43280.8 [/path/dotnet/shared/Microsoft.NETCore.App]",
"Microsoft.NETCore.App 8.0.0-preview.5.23280.8 [/path/dotnet/shared/Microsoft.NETCore.App]"
};
var dotnet = new DotNetStub(listedRuntimes);
var runtime = new Runtime(dotnet);
// Execute
var runtimes = runtime.GetNewestRuntimes();
// Verify
Assert.Single(runtimes);
Assert.True(runtimes.TryGetValue("Microsoft.NETCore.App", out var netCoreApp));
Assert.Equal("/path/dotnet/shared/Microsoft.NETCore.App/8.0.0-rc.4.43280.8", netCoreApp.FullPath);
}
}
}

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
namespace Semmle.Util
{
@@ -19,17 +18,5 @@ namespace Semmle.Util
}
list.Add(element);
}
/// <summary>
/// Adds a new value or replaces the existing value (if the new value is greater than the existing)
/// in dictionary for the given key.
/// </summary>
public static void AddOrUpdate<T1, T2>(this Dictionary<T1, T2> dict, T1 key, T2 value) where T1 : notnull where T2 : IComparable<T2>
{
if (!dict.TryGetValue(key, out var existing) || existing.CompareTo(value) < 0)
{
dict[key] = value;
}
}
}
}

View File

@@ -1,15 +1,3 @@
## 1.6.0
No user-facing changes.
## 1.5.4
No user-facing changes.
## 1.5.3
No user-facing changes.
## 1.5.2
No user-facing changes.

View File

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

View File

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

View File

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

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.6.0
lastReleaseVersion: 1.5.2

View File

@@ -1,9 +1,8 @@
name: codeql/csharp-solorigate-all
version: 1.6.1-dev
version: 1.5.3-dev
groups:
- csharp
- solorigate
library: true
dependencies:
codeql/csharp-all: ${workspace}
warnOnImplicitThis: true

View File

@@ -1,15 +1,3 @@
## 1.6.0
No user-facing changes.
## 1.5.4
No user-facing changes.
## 1.5.3
No user-facing changes.
## 1.5.2
No user-facing changes.

View File

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

View File

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

View File

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

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