mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Merge branch 'main' into rdmarsh2/cpp/output-iterators-1
Fix merge conflict in test expectations
This commit is contained in:
49
.github/workflows/query-list.yml
vendored
Normal file
49
.github/workflows/query-list.yml
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
name: Build code scanning query list
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- 'rc/**'
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/query-list.yml'
|
||||
- 'misc/scripts/generate-code-scanning-query-list.py'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Clone self (github/codeql)
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: codeql
|
||||
- name: Clone github/codeql-go
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: 'github/codeql-go'
|
||||
path: codeql-go
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Download CodeQL CLI
|
||||
uses: dsaltares/fetch-gh-release-asset@aa37ae5c44d3c9820bc12fe675e8670ecd93bd1c
|
||||
with:
|
||||
repo: "github/codeql-cli-binaries"
|
||||
version: "latest"
|
||||
file: "codeql-linux64.zip"
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Unzip CodeQL CLI
|
||||
run: unzip -d codeql-cli codeql-linux64.zip
|
||||
- name: Build code scanning query list
|
||||
run: |
|
||||
PATH="$PATH:codeql-cli/codeql" python codeql/misc/scripts/generate-code-scanning-query-list.py > code-scanning-query-list.csv
|
||||
- name: Upload code scanning query list
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: code-scanning-query-list
|
||||
path: code-scanning-query-list.csv
|
||||
|
||||
@@ -20,7 +20,10 @@ The following changes in version 1.26 affect C/C++ analysis in all applications.
|
||||
|
||||
## Changes to libraries
|
||||
|
||||
* The QL class `Block`, denoting the `{ ... }` statement, is renamed to `BlockStmt`.
|
||||
* The models library now models many taint flows through `std::array`, `std::vector`, `std::deque`, `std::list` and `std::forward_list`.
|
||||
* The models library now models many more taint flows through `std::string`.
|
||||
* The models library now models some taint flows through `std::ostream`.
|
||||
* The models library now models some taint flows through `std::shared_ptr`, `std::unique_ptr`, `std::make_shared` and `std::make_unique`.
|
||||
* The `SimpleRangeAnalysis` library now supports multiplications of the form
|
||||
`e1 * e2` and `x *= e2` when `e1` and `e2` are unsigned or constant.
|
||||
|
||||
21
change-notes/1.26/analysis-java.md
Normal file
21
change-notes/1.26/analysis-java.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Improvements to Java analysis
|
||||
|
||||
The following changes in version 1.26 affect Java analysis in all applications.
|
||||
|
||||
## General improvements
|
||||
|
||||
## New queries
|
||||
|
||||
| **Query** | **Tags** | **Purpose** |
|
||||
|-----------------------------|-----------|--------------------------------------------------------------------|
|
||||
|
||||
|
||||
## Changes to existing queries
|
||||
|
||||
| **Query** | **Expected impact** | **Change** |
|
||||
|------------------------------|------------------------|-----------------------------------|
|
||||
|
||||
|
||||
## Changes to libraries
|
||||
|
||||
* The QL class `Block`, denoting the `{ ... }` statement, is renamed to `BlockStmt`.
|
||||
@@ -3,6 +3,7 @@
|
||||
## General improvements
|
||||
|
||||
* Support for the following frameworks and libraries has been improved:
|
||||
- [bluebird](https://www.npmjs.com/package/bluebird)
|
||||
- [fast-json-stable-stringify](https://www.npmjs.com/package/fast-json-stable-stringify)
|
||||
- [fast-safe-stringify](https://www.npmjs.com/package/fast-safe-stringify)
|
||||
- [javascript-stringify](https://www.npmjs.com/package/javascript-stringify)
|
||||
@@ -10,9 +11,11 @@
|
||||
- [json-stable-stringify](https://www.npmjs.com/package/json-stable-stringify)
|
||||
- [json-stringify-safe](https://www.npmjs.com/package/json-stringify-safe)
|
||||
- [json3](https://www.npmjs.com/package/json3)
|
||||
- [lodash](https://www.npmjs.com/package/lodash)
|
||||
- [object-inspect](https://www.npmjs.com/package/object-inspect)
|
||||
- [pretty-format](https://www.npmjs.com/package/pretty-format)
|
||||
- [stringify-object](https://www.npmjs.com/package/stringify-object)
|
||||
- [underscore](https://www.npmjs.com/package/underscore)
|
||||
|
||||
* Analyzing files with the ".cjs" extension is now supported.
|
||||
|
||||
@@ -30,7 +33,9 @@
|
||||
| Incomplete URL substring sanitization (`js/incomplete-url-substring-sanitization`) | More results | This query now recognizes additional URLs when the substring check is an inclusion check. |
|
||||
| Ambiguous HTML id attribute (`js/duplicate-html-id`) | Results no longer shown | Precision tag reduced to "low". The query is no longer run by default. |
|
||||
| Unused loop iteration variable (`js/unused-loop-variable`) | Fewer results | This query no longer flags variables in a destructuring array assignment that are not the last variable in the destructed array. |
|
||||
| Unsafe shell command constructed from library input (`js/shell-command-constructed-from-input`) | More results | This query now recognizes more commands where colon, dash, and underscore are used. |
|
||||
| Unsafe jQuery plugin (`js/unsafe-jquery-plugin`) | More results | This query now detects more unsafe uses of nested option properties. |
|
||||
| Client-side URL redirect (`js/client-side-unvalidated-url-redirection`) | More results | This query now recognizes some unsafe uses of `importScripts()` inside WebWorkers. |
|
||||
|
||||
|
||||
## Changes to libraries
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
|
||||
import cpp
|
||||
|
||||
from Block blk
|
||||
from BlockStmt blk
|
||||
where blk.getNumStmt() = 0
|
||||
select blk
|
||||
|
||||
@@ -13,5 +13,5 @@
|
||||
import cpp
|
||||
|
||||
from IfStmt i
|
||||
where i.getThen().(Block).getNumStmt() = 0
|
||||
where i.getThen().(BlockStmt).getNumStmt() = 0
|
||||
select i
|
||||
|
||||
@@ -8,6 +8,6 @@
|
||||
|
||||
import cpp
|
||||
|
||||
from Block b
|
||||
from BlockStmt b
|
||||
where b.getNumStmt() = 1
|
||||
select b
|
||||
|
||||
@@ -14,7 +14,7 @@ import cpp
|
||||
|
||||
class ComplexStmt extends Stmt {
|
||||
ComplexStmt() {
|
||||
exists(Block body |
|
||||
exists(BlockStmt body |
|
||||
body = this.(Loop).getStmt() or
|
||||
body = this.(SwitchStmt).getStmt()
|
||||
|
|
||||
@@ -24,7 +24,7 @@ class ComplexStmt extends Stmt {
|
||||
}
|
||||
}
|
||||
|
||||
from Block b, int n, ComplexStmt complexStmt
|
||||
from BlockStmt b, int n, ComplexStmt complexStmt
|
||||
where
|
||||
n = strictcount(ComplexStmt s | s = b.getAStmt()) and
|
||||
n > 3 and
|
||||
|
||||
@@ -17,7 +17,7 @@ where
|
||||
shadowing(lv1, lv2) and
|
||||
not lv1.isCompilerGenerated() and
|
||||
not lv2.isCompilerGenerated() and
|
||||
not lv1.getParentScope().(Block).isInMacroExpansion() and
|
||||
not lv2.getParentScope().(Block).isInMacroExpansion()
|
||||
not lv1.getParentScope().(BlockStmt).isInMacroExpansion() and
|
||||
not lv2.getParentScope().(BlockStmt).isInMacroExpansion()
|
||||
select lv1, "Variable " + lv1.getName() + " hides another variable of the same name (on $@).", lv2,
|
||||
"line " + lv2.getLocation().getStartLine().toString()
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
import cpp
|
||||
|
||||
predicate emptyBlock(ControlStructure s, Block b) {
|
||||
predicate emptyBlock(ControlStructure s, BlockStmt b) {
|
||||
b = s.getAChild() and
|
||||
not exists(b.getAChild()) and
|
||||
not b.isInMacroExpansion() and
|
||||
@@ -23,7 +23,7 @@ predicate emptyBlock(ControlStructure s, Block b) {
|
||||
|
||||
class AffectedFile extends File {
|
||||
AffectedFile() {
|
||||
exists(Block b |
|
||||
exists(BlockStmt b |
|
||||
emptyBlock(_, b) and
|
||||
this = b.getFile()
|
||||
)
|
||||
@@ -37,7 +37,7 @@ class AffectedFile extends File {
|
||||
class BlockOrNonChild extends Element {
|
||||
BlockOrNonChild() {
|
||||
(
|
||||
this instanceof Block
|
||||
this instanceof BlockStmt
|
||||
or
|
||||
this instanceof Comment
|
||||
or
|
||||
@@ -78,7 +78,7 @@ class BlockOrNonChild extends Element {
|
||||
/**
|
||||
* A block that contains a non-child element.
|
||||
*/
|
||||
predicate emptyBlockContainsNonchild(Block b) {
|
||||
predicate emptyBlockContainsNonchild(BlockStmt b) {
|
||||
emptyBlock(_, b) and
|
||||
exists(BlockOrNonChild c, AffectedFile file |
|
||||
c.(BlockOrNonChild).getStartRankIn(file) = 1 + b.(BlockOrNonChild).getStartRankIn(file) and
|
||||
@@ -91,7 +91,7 @@ predicate emptyBlockContainsNonchild(Block b) {
|
||||
* A block that is entirely on one line, which also contains a comment. Chances
|
||||
* are the comment is intended to refer to the block.
|
||||
*/
|
||||
predicate lineComment(Block b) {
|
||||
predicate lineComment(BlockStmt b) {
|
||||
emptyBlock(_, b) and
|
||||
exists(Location bLocation, File f, int line |
|
||||
bLocation = b.getLocation() and
|
||||
@@ -106,7 +106,7 @@ predicate lineComment(Block b) {
|
||||
)
|
||||
}
|
||||
|
||||
from ControlStructure s, Block eb
|
||||
from ControlStructure s, BlockStmt eb
|
||||
where
|
||||
emptyBlock(s, eb) and
|
||||
not emptyBlockContainsNonchild(eb) and
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.commons.Exclusions
|
||||
|
||||
Stmt getNextRealStmt(Block b, int i) {
|
||||
Stmt getNextRealStmt(BlockStmt b, int i) {
|
||||
result = b.getStmt(i + 1) and
|
||||
not result instanceof EmptyStmt
|
||||
or
|
||||
@@ -20,7 +20,7 @@ Stmt getNextRealStmt(Block b, int i) {
|
||||
result = getNextRealStmt(b, i + 1)
|
||||
}
|
||||
|
||||
from JumpStmt js, Block b, int i, Stmt s
|
||||
from JumpStmt js, BlockStmt b, int i, Stmt s
|
||||
where
|
||||
b.getStmt(i) = js and
|
||||
s = getNextRealStmt(b, i) and
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
import cpp
|
||||
|
||||
int lineInBlock(File f) {
|
||||
exists(Block block, Location blockLocation |
|
||||
exists(BlockStmt block, Location blockLocation |
|
||||
block.getFile() = f and blockLocation = block.getLocation()
|
||||
|
|
||||
result in [blockLocation.getStartLine() .. blockLocation.getEndLine()]
|
||||
|
||||
@@ -27,11 +27,11 @@ predicate macroUseLocation(File f, int start, int end) {
|
||||
}
|
||||
|
||||
pragma[noopt]
|
||||
predicate emptyIf(IfStmt s, Block b, File f, int start, int end) {
|
||||
predicate emptyIf(IfStmt s, BlockStmt b, File f, int start, int end) {
|
||||
s instanceof IfStmt and
|
||||
not exists(s.getElse()) and
|
||||
b = s.getThen() and
|
||||
b instanceof Block and
|
||||
b instanceof BlockStmt and
|
||||
not exists(b.getAChild()) and
|
||||
f = b.getFile() and
|
||||
exists(Location l |
|
||||
@@ -42,7 +42,7 @@ predicate emptyIf(IfStmt s, Block b, File f, int start, int end) {
|
||||
}
|
||||
|
||||
pragma[noopt]
|
||||
predicate query(IfStmt s, Block b) {
|
||||
predicate query(IfStmt s, BlockStmt b) {
|
||||
exists(File f, int blockStart, int blockEnd |
|
||||
emptyIf(s, b, f, blockStart, blockEnd) and
|
||||
not exists(int macroStart, int macroEnd |
|
||||
@@ -53,7 +53,7 @@ predicate query(IfStmt s, Block b) {
|
||||
)
|
||||
}
|
||||
|
||||
from IfStmt s, Block b
|
||||
from IfStmt s, BlockStmt b
|
||||
where
|
||||
query(s, b) and
|
||||
not b.isInMacroExpansion()
|
||||
|
||||
@@ -27,7 +27,7 @@ int logicalLength(FunctionDeclarationEntry f) {
|
||||
count(Stmt s |
|
||||
s.getEnclosingFunction() = f.getFunction() and
|
||||
s.getFile() = f.getFile() and
|
||||
not s instanceof Block and
|
||||
not s instanceof BlockStmt and
|
||||
not s instanceof EmptyStmt and
|
||||
not exists(ForStmt for | s = for.getInitialization()) and
|
||||
not s.isAffectedByMacro()
|
||||
|
||||
@@ -14,7 +14,7 @@ import cpp
|
||||
class OneLineStmt extends Stmt {
|
||||
OneLineStmt() {
|
||||
this.getLocation().getStartLine() = this.getLocation().getEndLine() and
|
||||
not this instanceof Block and
|
||||
not this instanceof BlockStmt and
|
||||
not exists(ForStmt for | this = for.getInitialization()) and
|
||||
(
|
||||
// Either this statement is not touched by a macro at all...
|
||||
|
||||
@@ -27,7 +27,7 @@ int logicalLength(FunctionDeclarationEntry f) {
|
||||
count(Stmt s |
|
||||
s.getEnclosingFunction() = f.getFunction() and
|
||||
s.getFile() = f.getFile() and
|
||||
not s instanceof Block and
|
||||
not s instanceof BlockStmt and
|
||||
not s instanceof EmptyStmt and
|
||||
not exists(ForStmt for | s = for.getInitialization()) and
|
||||
not s.isAffectedByMacro()
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
import cpp
|
||||
|
||||
predicate blockDominates(Block check, Block access) {
|
||||
predicate blockDominates(BlockStmt check, BlockStmt access) {
|
||||
check.getLocation().getStartLine() <= access.getLocation().getStartLine() and
|
||||
check.getLocation().getEndLine() >= access.getLocation().getEndLine()
|
||||
}
|
||||
|
||||
2
cpp/ql/src/external/CodeDuplication.qll
vendored
2
cpp/ql/src/external/CodeDuplication.qll
vendored
@@ -117,7 +117,7 @@ private predicate blockCoversStatement(int equivClass, int first, int last, Stmt
|
||||
private Stmt statementInMethod(FunctionDeclarationEntry m) {
|
||||
result.getParent+() = m.getBlock() and
|
||||
not result.getLocation() instanceof UnknownStmtLocation and
|
||||
not result instanceof Block
|
||||
not result instanceof BlockStmt
|
||||
}
|
||||
|
||||
private predicate duplicateStatement(
|
||||
|
||||
@@ -18,6 +18,7 @@ from Include i, File f, string extension
|
||||
where
|
||||
f = i.getIncludedFile() and
|
||||
extension = f.getExtension().toLowerCase() and
|
||||
extension != "inc" and
|
||||
extension != "inl" and
|
||||
extension != "tcc" and
|
||||
extension != "tpp" and
|
||||
|
||||
@@ -13,7 +13,7 @@ import cpp
|
||||
|
||||
from Stmt parent, Stmt child
|
||||
where
|
||||
not child instanceof Block and
|
||||
not child instanceof BlockStmt and
|
||||
(
|
||||
child = parent.(IfStmt).getThen()
|
||||
or
|
||||
|
||||
@@ -28,7 +28,7 @@ predicate oppositeOperators(string op1, string op2) {
|
||||
* `!op2(_, _)`.
|
||||
*/
|
||||
predicate implementedAsNegationOf(Operator op1, Operator op2) {
|
||||
exists(Block b, ReturnStmt r, NotExpr n, Expr o |
|
||||
exists(BlockStmt b, ReturnStmt r, NotExpr n, Expr o |
|
||||
b = op1.getBlock() and
|
||||
b.getNumStmt() = 1 and
|
||||
r = b.getStmt(0) and
|
||||
|
||||
@@ -29,7 +29,7 @@ predicate localShadowsParameter(LocalVariable lv, Parameter p) {
|
||||
|
||||
from Variable v, Variable shadowed
|
||||
where
|
||||
not v.getParentScope().(Block).isInMacroExpansion() and
|
||||
not v.getParentScope().(BlockStmt).isInMacroExpansion() and
|
||||
(
|
||||
v.(LocalVariableOrParameter).shadowsGlobal(shadowed.(GlobalVariable)) or
|
||||
localShadowsParameter(v, shadowed) or
|
||||
|
||||
@@ -38,7 +38,7 @@ predicate noDefUsePath(LocalVariable lv, ControlFlowNode n) {
|
||||
}
|
||||
|
||||
predicate neighbouringStmts(Stmt s1, Stmt s2) {
|
||||
exists(Block b, int i |
|
||||
exists(BlockStmt b, int i |
|
||||
i in [0 .. b.getNumStmt() - 2] and
|
||||
s1 = b.getStmt(i) and
|
||||
s2 = b.getStmt(i + 1)
|
||||
|
||||
@@ -22,6 +22,6 @@ where
|
||||
not s instanceof ControlStructure and
|
||||
// Exclude blocks; if a child of the block violates the rule that will still
|
||||
// be picked up so there is no point in blaming the block as well
|
||||
not s instanceof Block and
|
||||
not s instanceof BlockStmt and
|
||||
s.isPure()
|
||||
select s, "AV Rule 187: All non-null statements shall potentially have a side-effect."
|
||||
|
||||
@@ -18,7 +18,7 @@ import cpp
|
||||
|
||||
// whether t is the last statement of s, possibly peeling off blocks
|
||||
predicate isTerminatingStmt(Stmt s, Stmt t) {
|
||||
s = t or isTerminatingStmt(s.(Block).getLastStmt(), t)
|
||||
s = t or isTerminatingStmt(s.(BlockStmt).getLastStmt(), t)
|
||||
}
|
||||
|
||||
from BreakStmt s
|
||||
|
||||
@@ -128,7 +128,7 @@ class Element extends ElementBase {
|
||||
|
||||
/**
|
||||
* Gets the parent scope of this `Element`, if any.
|
||||
* A scope is a `Type` (`Class` / `Enum`), a `Namespace`, a `Block`, a `Function`,
|
||||
* A scope is a `Type` (`Class` / `Enum`), a `Namespace`, a `BlockStmt`, a `Function`,
|
||||
* or certain kinds of `Statement`.
|
||||
*/
|
||||
Element getParentScope() {
|
||||
@@ -161,7 +161,7 @@ class Element extends ElementBase {
|
||||
exists(EnumConstant e | this = e and result = e.getDeclaringEnum())
|
||||
or
|
||||
// result instanceof block|function
|
||||
exists(Block b | this = b and blockscope(unresolveElement(b), unresolveElement(result)))
|
||||
exists(BlockStmt b | this = b and blockscope(unresolveElement(b), unresolveElement(result)))
|
||||
or
|
||||
exists(TemplateFunction tf | this = tf.getATemplateArgument() and result = tf)
|
||||
or
|
||||
|
||||
@@ -268,7 +268,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
|
||||
* block, this gives the block guarded by the try statement. See
|
||||
* `FunctionTryStmt` for further information.
|
||||
*/
|
||||
Block getBlock() { result.getParentScope() = this }
|
||||
BlockStmt getBlock() { result.getParentScope() = this }
|
||||
|
||||
/** Holds if this function has an entry point. */
|
||||
predicate hasEntryPoint() { exists(getEntryPoint()) }
|
||||
@@ -276,7 +276,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
|
||||
/**
|
||||
* Gets the first node in this function's control flow graph.
|
||||
*
|
||||
* For most functions, this first node will be the `Block` returned by
|
||||
* For most functions, this first node will be the `BlockStmt` returned by
|
||||
* `getBlock`. However in C++, the first node can also be a
|
||||
* `FunctionTryStmt`.
|
||||
*/
|
||||
@@ -564,7 +564,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
|
||||
* If this is a function definition, get the block containing the
|
||||
* function body.
|
||||
*/
|
||||
Block getBlock() {
|
||||
BlockStmt getBlock() {
|
||||
this.isDefinition() and
|
||||
result = getFunction().getBlock() and
|
||||
result.getFile() = this.getFile()
|
||||
@@ -576,7 +576,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
|
||||
*/
|
||||
pragma[noopt]
|
||||
int getNumberOfLines() {
|
||||
exists(Block b, Location l, int start, int end, int diff | b = getBlock() |
|
||||
exists(BlockStmt b, Location l, int start, int end, int diff | b = getBlock() |
|
||||
l = b.getLocation() and
|
||||
start = l.getStartLine() and
|
||||
end = l.getEndLine() and
|
||||
|
||||
@@ -105,16 +105,23 @@ class Location extends @location {
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `Location` instead.
|
||||
* A location of an element. Not used for expressions or statements, which
|
||||
* instead use LocationExpr and LocationStmt respectively.
|
||||
*/
|
||||
library class LocationDefault extends Location, @location_default { }
|
||||
deprecated library class LocationDefault extends Location, @location_default { }
|
||||
|
||||
/** A location of a statement. */
|
||||
library class LocationStmt extends Location, @location_stmt { }
|
||||
/**
|
||||
* DEPRECATED: Use `Location` instead.
|
||||
* A location of a statement.
|
||||
*/
|
||||
deprecated library class LocationStmt extends Location, @location_stmt { }
|
||||
|
||||
/** A location of an expression. */
|
||||
library class LocationExpr extends Location, @location_expr { }
|
||||
/**
|
||||
* DEPRECATED: Use `Location` instead.
|
||||
* A location of an expression.
|
||||
*/
|
||||
deprecated library class LocationExpr extends Location, @location_expr { }
|
||||
|
||||
/**
|
||||
* Gets the length of the longest line in file `f`.
|
||||
|
||||
@@ -136,7 +136,7 @@ deprecated class ObjcTryStmt extends TryStmt {
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C `@finally` block.
|
||||
*/
|
||||
deprecated class FinallyBlock extends Block {
|
||||
deprecated class FinallyBlock extends BlockStmt {
|
||||
FinallyBlock() { none() }
|
||||
|
||||
/** Gets the try statement corresponding to this finally block. */
|
||||
|
||||
@@ -98,7 +98,7 @@ class Parameter extends LocalScopeVariable, @parameter {
|
||||
* DEPRECATED: this method was used in a previous implementation of
|
||||
* getName, but is no longer in use.
|
||||
*/
|
||||
deprecated string getNameInBlock(Block b) {
|
||||
deprecated string getNameInBlock(BlockStmt b) {
|
||||
exists(ParameterDeclarationEntry pde |
|
||||
pde.getFunctionDeclarationEntry().getBlock() = b and
|
||||
this.getFunction().getBlock() = b and
|
||||
@@ -127,7 +127,7 @@ class Parameter extends LocalScopeVariable, @parameter {
|
||||
* Gets the catch block to which this parameter belongs, if it is a catch
|
||||
* block parameter.
|
||||
*/
|
||||
Block getCatchBlock() { params(underlyingElement(this), unresolveElement(result), _, _) }
|
||||
BlockStmt getCatchBlock() { params(underlyingElement(this), unresolveElement(result), _, _) }
|
||||
|
||||
/**
|
||||
* Gets the zero-based index of this parameter.
|
||||
|
||||
@@ -25,7 +25,7 @@ private predicate exprInVoidContext(Expr e) {
|
||||
(
|
||||
exists(ExprStmt s |
|
||||
s = e.getParent() and
|
||||
not exists(StmtExpr se | s = se.getStmt().(Block).getLastStmt())
|
||||
not exists(StmtExpr se | s = se.getStmt().(BlockStmt).getLastStmt())
|
||||
)
|
||||
or
|
||||
exists(ConditionalExpr c | c.getThen() = e and c instanceof ExprInVoidContext)
|
||||
|
||||
@@ -118,7 +118,7 @@ private predicate excludeNodeAndNodesBelow(Expr e) {
|
||||
or
|
||||
// Constructor init lists should be evaluated, and we can change this in
|
||||
// the future, but it would mean that a `Function` entry point is not
|
||||
// always a `Block` or `FunctionTryStmt`.
|
||||
// always a `BlockStmt` or `FunctionTryStmt`.
|
||||
e instanceof ConstructorInit
|
||||
or
|
||||
// Destructor field destructions should also be hooked into the CFG
|
||||
@@ -408,10 +408,10 @@ private Node getControlOrderChildSparse(Node n, int i) {
|
||||
// in-line in the block containing their corresponding DeclStmt but should
|
||||
// not be evaluated in the order implied by their position in the block. We
|
||||
// do the following.
|
||||
// - Block skips all the VlaDeclStmt and VlaDimensionStmt children.
|
||||
// - BlockStmt skips all the VlaDeclStmt and VlaDimensionStmt children.
|
||||
// - VlaDeclStmt is inserted as a child of DeclStmt
|
||||
// - VlaDimensionStmt is inserted as a child of VlaDeclStmt
|
||||
result = n.(Block).getChild(i) and
|
||||
result = n.(BlockStmt).getChild(i) and
|
||||
not result instanceof VlaDeclStmt and
|
||||
not result instanceof VlaDimensionStmt
|
||||
or
|
||||
@@ -557,7 +557,7 @@ private class Spec extends Pos {
|
||||
*/
|
||||
private predicate straightLineSparse(Node scope, int i, Node ni, Spec spec) {
|
||||
scope =
|
||||
any(Block b |
|
||||
any(BlockStmt b |
|
||||
i = -1 and ni = b and spec.isAt()
|
||||
or
|
||||
if exists(getLastControlOrderChild(b))
|
||||
@@ -734,7 +734,7 @@ private predicate straightLineSparse(Node scope, int i, Node ni, Spec spec) {
|
||||
or
|
||||
// If the switch body is not a block then this step is skipped, and the
|
||||
// expression jumps directly to the cases.
|
||||
i = 1 and ni = s.getStmt().(Block) and spec.isAt()
|
||||
i = 1 and ni = s.getStmt().(BlockStmt) and spec.isAt()
|
||||
or
|
||||
i = 2 and ni = s.getASwitchCase() and spec.isBefore()
|
||||
or
|
||||
@@ -1010,7 +1010,7 @@ private predicate subEdgeIncludingDestructors(Pos p1, Node n1, Node n2, Pos p2)
|
||||
* The exact placement of that call in the CFG depends on the type of
|
||||
* `node` as follows:
|
||||
*
|
||||
* - `Block`: after ordinary control flow falls off the end of the block
|
||||
* - `BlockStmt`: after ordinary control flow falls off the end of the block
|
||||
* without jumps or exceptions.
|
||||
* - `ReturnStmt`: After the statement itself or after its operand (if
|
||||
* present).
|
||||
|
||||
@@ -182,7 +182,7 @@ private int switchCaseRangeEnd(SwitchCase sc) {
|
||||
* body `switchBlock`. There may be several such expressions: for example, if
|
||||
* the condition is `(x ? y : z)` then the result is {`y`, `z`}.
|
||||
*/
|
||||
private Node getASwitchExpr(SwitchStmt switch, Block switchBlock) {
|
||||
private Node getASwitchExpr(SwitchStmt switch, BlockStmt switchBlock) {
|
||||
switch.getStmt() = switchBlock and
|
||||
successors_extended(result, switchBlock)
|
||||
}
|
||||
@@ -192,7 +192,7 @@ private Node getASwitchExpr(SwitchStmt switch, Block switchBlock) {
|
||||
* from `switchBlock` to `sc` is impossible. This considers only non-`default`
|
||||
* switch cases.
|
||||
*/
|
||||
private predicate impossibleSwitchEdge(Block switchBlock, SwitchCase sc) {
|
||||
private predicate impossibleSwitchEdge(BlockStmt switchBlock, SwitchCase sc) {
|
||||
not sc instanceof DefaultCase and
|
||||
exists(SwitchStmt switch |
|
||||
switch = sc.getSwitchStmt() and
|
||||
@@ -215,7 +215,7 @@ private predicate impossibleSwitchEdge(Block switchBlock, SwitchCase sc) {
|
||||
* If a switch provably always chooses a non-default case, then the edge to
|
||||
* the default case is impossible.
|
||||
*/
|
||||
private predicate impossibleDefaultSwitchEdge(Block switchBlock, DefaultCase dc) {
|
||||
private predicate impossibleDefaultSwitchEdge(BlockStmt switchBlock, DefaultCase dc) {
|
||||
exists(SwitchStmt switch |
|
||||
switch = dc.getSwitchStmt() and
|
||||
switch.getStmt() = switchBlock and
|
||||
|
||||
@@ -29,7 +29,7 @@ private predicate stdIdentityFunction(Function f) { f.hasQualifiedName("std", ["
|
||||
*/
|
||||
private predicate stdAddressOf(Function f) { f.hasQualifiedName("std", "addressof") }
|
||||
|
||||
private predicate lvalueToLvalueStep(Expr lvalueIn, Expr lvalueOut) {
|
||||
private predicate lvalueToLvalueStepPure(Expr lvalueIn, Expr lvalueOut) {
|
||||
lvalueIn.getConversion() = lvalueOut.(ParenthesisExpr)
|
||||
or
|
||||
// When an object is implicitly converted to a reference to one of its base
|
||||
@@ -42,6 +42,10 @@ private predicate lvalueToLvalueStep(Expr lvalueIn, Expr lvalueOut) {
|
||||
// such casts.
|
||||
lvalueIn.getConversion() = lvalueOut and
|
||||
lvalueOut.(CStyleCast).isImplicit()
|
||||
}
|
||||
|
||||
private predicate lvalueToLvalueStep(Expr lvalueIn, Expr lvalueOut) {
|
||||
lvalueToLvalueStepPure(lvalueIn, lvalueOut)
|
||||
or
|
||||
// C++ only
|
||||
lvalueIn = lvalueOut.(PrefixCrementOperation).getOperand().getFullyConverted()
|
||||
@@ -214,6 +218,69 @@ private predicate referenceToUpdate(Expr reference, Expr outer, ControlFlowNode
|
||||
)
|
||||
}
|
||||
|
||||
private predicate lvalueFromVariableAccess(VariableAccess va, Expr lvalue) {
|
||||
// Base case for non-reference types.
|
||||
lvalue = va and
|
||||
not va.getConversion() instanceof ReferenceDereferenceExpr
|
||||
or
|
||||
// Base case for reference types where we pretend that they are
|
||||
// non-reference types. The type of the target of `va` can be `ReferenceType`
|
||||
// or `FunctionReferenceType`.
|
||||
lvalue = va.getConversion().(ReferenceDereferenceExpr)
|
||||
or
|
||||
// lvalue -> lvalue
|
||||
exists(Expr prev |
|
||||
lvalueFromVariableAccess(va, prev) and
|
||||
lvalueToLvalueStep(prev, lvalue)
|
||||
)
|
||||
or
|
||||
// pointer -> lvalue
|
||||
exists(Expr prev |
|
||||
pointerFromVariableAccess(va, prev) and
|
||||
pointerToLvalueStep(prev, lvalue)
|
||||
)
|
||||
or
|
||||
// reference -> lvalue
|
||||
exists(Expr prev |
|
||||
referenceFromVariableAccess(va, prev) and
|
||||
referenceToLvalueStep(prev, lvalue)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate pointerFromVariableAccess(VariableAccess va, Expr pointer) {
|
||||
// pointer -> pointer
|
||||
exists(Expr prev |
|
||||
pointerFromVariableAccess(va, prev) and
|
||||
pointerToPointerStep(prev, pointer)
|
||||
)
|
||||
or
|
||||
// reference -> pointer
|
||||
exists(Expr prev |
|
||||
referenceFromVariableAccess(va, prev) and
|
||||
referenceToPointerStep(prev, pointer)
|
||||
)
|
||||
or
|
||||
// lvalue -> pointer
|
||||
exists(Expr prev |
|
||||
lvalueFromVariableAccess(va, prev) and
|
||||
lvalueToPointerStep(prev, pointer)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate referenceFromVariableAccess(VariableAccess va, Expr reference) {
|
||||
// reference -> reference
|
||||
exists(Expr prev |
|
||||
referenceFromVariableAccess(va, prev) and
|
||||
referenceToReferenceStep(prev, reference)
|
||||
)
|
||||
or
|
||||
// lvalue -> reference
|
||||
exists(Expr prev |
|
||||
lvalueFromVariableAccess(va, prev) and
|
||||
lvalueToReferenceStep(prev, reference)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` is a control-flow node that may modify `inner` (or what it
|
||||
* points to) through `outer`. The two expressions may be `Conversion`s. Plain
|
||||
@@ -236,7 +303,7 @@ predicate valueToUpdate(Expr inner, Expr outer, ControlFlowNode node) {
|
||||
(
|
||||
inner instanceof VariableAccess and
|
||||
// Don't track non-field assignments
|
||||
(assignmentTo(outer, _) implies inner instanceof FieldAccess)
|
||||
not (assignmentTo(outer, _) and outer.(VariableAccess).getTarget() instanceof StackVariable)
|
||||
or
|
||||
inner instanceof ThisExpr
|
||||
or
|
||||
@@ -245,3 +312,27 @@ predicate valueToUpdate(Expr inner, Expr outer, ControlFlowNode node) {
|
||||
// can't do anything useful with those at the moment.
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e` is a fully-converted expression that evaluates to an lvalue
|
||||
* derived from `va` and is used for reading from or assigning to. This is in
|
||||
* contrast with a variable access that is used for taking an address (`&x`)
|
||||
* or simply discarding its value (`x;`).
|
||||
*
|
||||
* This analysis does not propagate across assignments or calls, and unlike
|
||||
* `variableAccessedAsValue` in `semmle.code.cpp.dataflow.EscapesTree` it
|
||||
* propagates through array accesses but not field accesses. The analysis is
|
||||
* also not concerned with whether the lvalue `e` is converted to an rvalue --
|
||||
* to examine that, use the relevant member predicates on `Expr`.
|
||||
*
|
||||
* If `va` has reference type, the analysis concerns the value pointed to by
|
||||
* the reference rather than the reference itself. The expression `e` may be a
|
||||
* `Conversion`.
|
||||
*/
|
||||
predicate variablePartiallyAccessed(VariableAccess va, Expr e) {
|
||||
lvalueFromVariableAccess(va, e) and
|
||||
not lvalueToLvalueStepPure(e, _) and
|
||||
not lvalueToPointerStep(e, _) and
|
||||
not lvalueToReferenceStep(e, _) and
|
||||
not e = any(ExprInVoidContext eivc | e = eivc.getConversion*())
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ private import cpp
|
||||
private import semmle.code.cpp.dataflow.internal.FlowVar
|
||||
private import semmle.code.cpp.models.interfaces.DataFlow
|
||||
private import semmle.code.cpp.controlflow.Guards
|
||||
private import semmle.code.cpp.dataflow.internal.AddressFlow
|
||||
|
||||
cached
|
||||
private newtype TNode =
|
||||
@@ -622,6 +623,15 @@ private predicate exprToExprStep_nocfg(Expr fromExpr, Expr toExpr) {
|
||||
or
|
||||
toExpr.(AddressOfExpr).getOperand() = fromExpr
|
||||
or
|
||||
// This rule enables flow from an array to its elements. Example: `a` to
|
||||
// `a[i]` or `*a`, where `a` is an array type. It does not enable flow from a
|
||||
// pointer to its indirection as in `p[i]` where `p` is a pointer type.
|
||||
exists(Expr toConverted |
|
||||
variablePartiallyAccessed(fromExpr, toConverted) and
|
||||
toExpr = toConverted.getUnconverted() and
|
||||
not toExpr = fromExpr
|
||||
)
|
||||
or
|
||||
toExpr.(BuiltInOperationBuiltInAddressOf).getOperand() = fromExpr
|
||||
or
|
||||
// The following case is needed to track the qualifier object for flow
|
||||
@@ -641,14 +651,25 @@ private predicate exprToExprStep_nocfg(Expr fromExpr, Expr toExpr) {
|
||||
// `ClassAggregateLiteral` (`{ capture1, ..., captureN }`).
|
||||
toExpr.(LambdaExpression).getInitializer() = fromExpr
|
||||
or
|
||||
// Data flow through a function model.
|
||||
toExpr =
|
||||
any(Call call |
|
||||
exists(DataFlowFunction f, FunctionInput inModel, FunctionOutput outModel, int iIn |
|
||||
call.getTarget() = f and
|
||||
exists(DataFlowFunction f, FunctionInput inModel, FunctionOutput outModel |
|
||||
f.hasDataFlow(inModel, outModel) and
|
||||
outModel.isReturnValue() and
|
||||
inModel.isParameter(iIn) and
|
||||
fromExpr = call.getArgument(iIn)
|
||||
(
|
||||
exists(int iIn |
|
||||
inModel.isParameter(iIn) and
|
||||
fromExpr = call.getArgument(iIn)
|
||||
)
|
||||
or
|
||||
inModel.isQualifierObject() and
|
||||
fromExpr = call.getQualifier()
|
||||
or
|
||||
inModel.isQualifierAddress() and
|
||||
fromExpr = call.getQualifier()
|
||||
) and
|
||||
call.getTarget() = f and
|
||||
outModel.isReturnValue()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -39,10 +39,10 @@ predicate defaultAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` should be a barrier in all global taint flow configurations
|
||||
* Holds if `node` should be a sanitizer in all global taint flow configurations
|
||||
* but not in local taint.
|
||||
*/
|
||||
predicate defaultTaintBarrier(DataFlow::Node node) { none() }
|
||||
predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if taint can flow in one local step from `nodeFrom` to `nodeTo` excluding
|
||||
@@ -96,10 +96,17 @@ predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeT
|
||||
exists(TaintFunction f, Call call, FunctionInput inModel, FunctionOutput outModel |
|
||||
call.getTarget() = f and
|
||||
inModel.isReturnValueDeref() and
|
||||
outModel.isQualifierObject() and
|
||||
f.hasTaintFlow(inModel, outModel) and
|
||||
nodeFrom.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() = call and
|
||||
nodeTo.asDefiningArgument() = call.getQualifier()
|
||||
f.hasTaintFlow(inModel, outModel) and
|
||||
(
|
||||
outModel.isQualifierObject() and
|
||||
nodeTo.asDefiningArgument() = call.getQualifier()
|
||||
or
|
||||
exists(int argOutIndex |
|
||||
outModel.isParameterDeref(argOutIndex) and
|
||||
nodeTo.asDefiningArgument() = call.getArgument(argOutIndex)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -76,20 +76,20 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isBarrier(DataFlow::Node node) {
|
||||
isSanitizer(node) or
|
||||
defaultTaintBarrier(node)
|
||||
defaultTaintSanitizer(node)
|
||||
}
|
||||
|
||||
/** Holds if data flow into `node` is prohibited. */
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) }
|
||||
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
/** Holds if taint propagation out of `node` is prohibited. */
|
||||
predicate isSanitizerOut(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) }
|
||||
|
||||
@@ -76,20 +76,20 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isBarrier(DataFlow::Node node) {
|
||||
isSanitizer(node) or
|
||||
defaultTaintBarrier(node)
|
||||
defaultTaintSanitizer(node)
|
||||
}
|
||||
|
||||
/** Holds if data flow into `node` is prohibited. */
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) }
|
||||
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
/** Holds if taint propagation out of `node` is prohibited. */
|
||||
predicate isSanitizerOut(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) }
|
||||
|
||||
@@ -27,7 +27,7 @@ class Expr extends StmtParent, @expr {
|
||||
Function getEnclosingFunction() { result = exprEnclosingElement(this) }
|
||||
|
||||
/** Gets the nearest enclosing set of curly braces around this expression in the source, if any. */
|
||||
Block getEnclosingBlock() { result = getEnclosingStmt().getEnclosingBlock() }
|
||||
BlockStmt getEnclosingBlock() { result = getEnclosingStmt().getEnclosingBlock() }
|
||||
|
||||
override Stmt getEnclosingStmt() {
|
||||
result = this.getParent().(Expr).getEnclosingStmt()
|
||||
@@ -402,7 +402,7 @@ class Expr extends StmtParent, @expr {
|
||||
*/
|
||||
predicate hasImplicitConversion() {
|
||||
exists(Expr e |
|
||||
exprconv(underlyingElement(this), unresolveElement(e)) and e.(Cast).isImplicit()
|
||||
exprconv(underlyingElement(this), unresolveElement(e)) and e.(Conversion).isImplicit()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -414,7 +414,7 @@ class Expr extends StmtParent, @expr {
|
||||
*/
|
||||
predicate hasExplicitConversion() {
|
||||
exists(Expr e |
|
||||
exprconv(underlyingElement(this), unresolveElement(e)) and not e.(Cast).isImplicit()
|
||||
exprconv(underlyingElement(this), unresolveElement(e)) and not e.(Conversion).isImplicit()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -453,12 +453,14 @@ class Expr extends StmtParent, @expr {
|
||||
* cast from B to C. Only (1) and (2) would be included.
|
||||
*/
|
||||
Expr getExplicitlyConverted() {
|
||||
// result is this or one of its conversions
|
||||
result = this.getConversion*() and
|
||||
// result is not an implicit conversion - it's either the expr or an explicit cast
|
||||
(result = this or not result.(Cast).isImplicit()) and
|
||||
// there is no further explicit conversion after result
|
||||
not exists(Cast other | other = result.getConversion+() and not other.isImplicit())
|
||||
// For performance, we avoid a full transitive closure over `getConversion`.
|
||||
// Since there can be several implicit conversions before and after an
|
||||
// explicit conversion, use `getImplicitlyConverted` to step over them
|
||||
// cheaply. Then, if there is an explicit conversion following the implict
|
||||
// conversion sequence, recurse to handle multiple explicit conversions.
|
||||
if this.getImplicitlyConverted().hasExplicitConversion()
|
||||
then result = this.getImplicitlyConverted().getConversion().getExplicitlyConverted()
|
||||
else result = this
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1109,7 +1111,7 @@ class StmtExpr extends Expr, @expr_stmt {
|
||||
/** Get the result expression of a statement. (Helper function for StmtExpr.) */
|
||||
private Expr getStmtResultExpr(Stmt stmt) {
|
||||
result = stmt.(ExprStmt).getExpr() or
|
||||
result = getStmtResultExpr(stmt.(Block).getLastStmt())
|
||||
result = getStmtResultExpr(stmt.(BlockStmt).getLastStmt())
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -144,8 +144,23 @@ OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) {
|
||||
*/
|
||||
predicate jumpStep(Node n1, Node n2) { none() }
|
||||
|
||||
/**
|
||||
* Gets a field corresponding to the bit range `[startBit..endBit)` of class `c`, if any.
|
||||
*/
|
||||
private Field getAField(Class c, int startBit, int endBit) {
|
||||
result.getDeclaringType() = c and
|
||||
startBit = 8 * result.getByteOffset() and
|
||||
endBit = 8 * result.getType().getSize() + startBit
|
||||
or
|
||||
exists(Field f, Class cInner |
|
||||
f = c.getAField() and
|
||||
cInner = f.getUnderlyingType() and
|
||||
result = getAField(cInner, startBit - 8 * f.getByteOffset(), endBit - 8 * f.getByteOffset())
|
||||
)
|
||||
}
|
||||
|
||||
private newtype TContent =
|
||||
TFieldContent(Field f) or
|
||||
TFieldContent(Class c, int startBit, int endBit) { exists(getAField(c, startBit, endBit)) } or
|
||||
TCollectionContent() or
|
||||
TArrayContent()
|
||||
|
||||
@@ -163,17 +178,18 @@ class Content extends TContent {
|
||||
}
|
||||
|
||||
private class FieldContent extends Content, TFieldContent {
|
||||
Field f;
|
||||
Class c;
|
||||
int startBit;
|
||||
int endBit;
|
||||
|
||||
FieldContent() { this = TFieldContent(f) }
|
||||
FieldContent() { this = TFieldContent(c, startBit, endBit) }
|
||||
|
||||
Field getField() { result = f }
|
||||
// Ensure that there's just 1 result for `toString`.
|
||||
override string toString() { result = min(Field f | f = getAField() | f.toString()) }
|
||||
|
||||
override string toString() { result = f.toString() }
|
||||
predicate hasOffset(Class cl, int start, int end) { cl = c and start = startBit and end = endBit }
|
||||
|
||||
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
|
||||
f.getLocation().hasLocationInfo(path, sl, sc, el, ec)
|
||||
}
|
||||
Field getAField() { result = getAField(c, startBit, endBit) }
|
||||
}
|
||||
|
||||
private class CollectionContent extends Content, TCollectionContent {
|
||||
@@ -185,20 +201,38 @@ private class ArrayContent extends Content, TArrayContent {
|
||||
}
|
||||
|
||||
private predicate storeStepNoChi(Node node1, Content f, PostUpdateNode node2) {
|
||||
exists(FieldAddressInstruction fa, StoreInstruction store |
|
||||
exists(StoreInstruction store, Class c |
|
||||
store = node2.asInstruction() and
|
||||
store.getDestinationAddress() = fa and
|
||||
store.getSourceValue() = node1.asInstruction() and
|
||||
f.(FieldContent).getField() = fa.getField()
|
||||
getWrittenField(store, f.(FieldContent).getAField(), c) and
|
||||
f.(FieldContent).hasOffset(c, _, _)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate getWrittenField(StoreInstruction store, Field f, Class c) {
|
||||
exists(FieldAddressInstruction fa |
|
||||
fa = store.getDestinationAddress() and
|
||||
f = fa.getField() and
|
||||
c = f.getDeclaringType()
|
||||
)
|
||||
}
|
||||
|
||||
private predicate storeStepChi(Node node1, Content f, PostUpdateNode node2) {
|
||||
exists(FieldAddressInstruction fa, StoreInstruction store |
|
||||
exists(StoreInstruction store, ChiInstruction chi |
|
||||
node1.asInstruction() = store and
|
||||
store.getDestinationAddress() = fa and
|
||||
node2.asInstruction().(ChiInstruction).getPartial() = store and
|
||||
f.(FieldContent).getField() = fa.getField()
|
||||
node2.asInstruction() = chi and
|
||||
chi.getPartial() = store and
|
||||
exists(Class c |
|
||||
c = chi.getResultType() and
|
||||
exists(int startBit, int endBit |
|
||||
chi.getUpdatedInterval(startBit, endBit) and
|
||||
f.(FieldContent).hasOffset(c, startBit, endBit)
|
||||
)
|
||||
or
|
||||
getWrittenField(store, f.(FieldContent).getAField(), c) and
|
||||
f.(FieldContent).hasOffset(c, _, _)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -212,17 +246,37 @@ predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
|
||||
storeStepChi(node1, f, node2)
|
||||
}
|
||||
|
||||
bindingset[result, i]
|
||||
private int unbindInt(int i) { i <= result and i >= result }
|
||||
|
||||
pragma[noinline]
|
||||
private predicate getLoadedField(LoadInstruction load, Field f, Class c) {
|
||||
exists(FieldAddressInstruction fa |
|
||||
fa = load.getSourceAddress() and
|
||||
f = fa.getField() and
|
||||
c = f.getDeclaringType()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` via a read of `f`.
|
||||
* Thus, `node1` references an object with a field `f` whose value ends up in
|
||||
* `node2`.
|
||||
*/
|
||||
predicate readStep(Node node1, Content f, Node node2) {
|
||||
exists(FieldAddressInstruction fa, LoadInstruction load |
|
||||
load.getSourceAddress() = fa and
|
||||
exists(LoadInstruction load |
|
||||
node2.asInstruction() = load and
|
||||
node1.asInstruction() = load.getSourceValueOperand().getAnyDef() and
|
||||
fa.getField() = f.(FieldContent).getField() and
|
||||
load = node2.asInstruction()
|
||||
exists(Class c |
|
||||
c = load.getSourceValueOperand().getAnyDef().getResultType() and
|
||||
exists(int startBit, int endBit |
|
||||
load.getSourceValueOperand().getUsedInterval(unbindInt(startBit), unbindInt(endBit)) and
|
||||
f.(FieldContent).hasOffset(c, startBit, endBit)
|
||||
)
|
||||
or
|
||||
getLoadedField(load, f.(FieldContent).getAField(), c) and
|
||||
f.(FieldContent).hasOffset(c, _, _)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -335,12 +335,14 @@ abstract private class PartialDefinitionNode extends PostUpdateNode {
|
||||
|
||||
private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
|
||||
override ChiInstruction instr;
|
||||
FieldAddressInstruction field;
|
||||
StoreInstruction store;
|
||||
|
||||
ExplicitFieldStoreQualifierNode() {
|
||||
not instr.isResultConflated() and
|
||||
exists(StoreInstruction store |
|
||||
instr.getPartial() = store and field = store.getDestinationAddress()
|
||||
instr.getPartial() = store and
|
||||
(
|
||||
instr.getUpdatedInterval(_, _) or
|
||||
store.getDestinationAddress() instanceof FieldAddressInstruction
|
||||
)
|
||||
}
|
||||
|
||||
@@ -351,7 +353,12 @@ private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
|
||||
override Node getPreUpdateNode() { result.asOperand() = instr.getTotalOperand() }
|
||||
|
||||
override Expr getDefinedExpr() {
|
||||
result = field.getObjectAddress().getUnconvertedResultExpression()
|
||||
result =
|
||||
store
|
||||
.getDestinationAddress()
|
||||
.(FieldAddressInstruction)
|
||||
.getObjectAddress()
|
||||
.getUnconvertedResultExpression()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,17 +370,22 @@ private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
|
||||
*/
|
||||
private class ExplicitSingleFieldStoreQualifierNode extends PartialDefinitionNode {
|
||||
override StoreInstruction instr;
|
||||
FieldAddressInstruction field;
|
||||
|
||||
ExplicitSingleFieldStoreQualifierNode() {
|
||||
field = instr.getDestinationAddress() and
|
||||
not exists(ChiInstruction chi | chi.getPartial() = instr)
|
||||
not exists(ChiInstruction chi | chi.getPartial() = instr) and
|
||||
// Without this condition any store would create a `PostUpdateNode`.
|
||||
instr.getDestinationAddress() instanceof FieldAddressInstruction
|
||||
}
|
||||
|
||||
override Node getPreUpdateNode() { none() }
|
||||
|
||||
override Expr getDefinedExpr() {
|
||||
result = field.getObjectAddress().getUnconvertedResultExpression()
|
||||
result =
|
||||
instr
|
||||
.getDestinationAddress()
|
||||
.(FieldAddressInstruction)
|
||||
.getObjectAddress()
|
||||
.getUnconvertedResultExpression()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -545,7 +557,7 @@ pragma[noinline]
|
||||
private predicate getFieldSizeOfClass(Class c, Type type, int size) {
|
||||
exists(Field f |
|
||||
f.getDeclaringType() = c and
|
||||
f.getType() = type and
|
||||
f.getUnderlyingType() = type and
|
||||
type.getSize() = size
|
||||
)
|
||||
}
|
||||
@@ -589,7 +601,7 @@ private predicate simpleOperandLocalFlowStep(Instruction iFrom, Operand opTo) {
|
||||
exists(LoadInstruction load |
|
||||
load.getSourceValueOperand() = opTo and
|
||||
opTo.getAnyDef() = iFrom and
|
||||
isSingleFieldClass(iFrom.getResultType(), opTo.getType())
|
||||
isSingleFieldClass(iFrom.getResultType(), opTo.getType().getUnderlyingType())
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -100,10 +100,10 @@ predicate defaultAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` should be a barrier in all global taint flow configurations
|
||||
* Holds if `node` should be a sanitizer in all global taint flow configurations
|
||||
* but not in local taint.
|
||||
*/
|
||||
predicate defaultTaintBarrier(DataFlow::Node node) { none() }
|
||||
predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if taint can flow from `instrIn` to `instrOut` through a call to a
|
||||
|
||||
@@ -76,20 +76,20 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isBarrier(DataFlow::Node node) {
|
||||
isSanitizer(node) or
|
||||
defaultTaintBarrier(node)
|
||||
defaultTaintSanitizer(node)
|
||||
}
|
||||
|
||||
/** Holds if data flow into `node` is prohibited. */
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) }
|
||||
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
/** Holds if taint propagation out of `node` is prohibited. */
|
||||
predicate isSanitizerOut(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) }
|
||||
|
||||
@@ -76,20 +76,20 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isBarrier(DataFlow::Node node) {
|
||||
isSanitizer(node) or
|
||||
defaultTaintBarrier(node)
|
||||
defaultTaintSanitizer(node)
|
||||
}
|
||||
|
||||
/** Holds if data flow into `node` is prohibited. */
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) }
|
||||
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
/** Holds if taint propagation out of `node` is prohibited. */
|
||||
predicate isSanitizerOut(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) }
|
||||
|
||||
@@ -1962,6 +1962,13 @@ class ChiInstruction extends Instruction {
|
||||
* Gets the operand that represents the new value written by the memory write.
|
||||
*/
|
||||
final Instruction getPartial() { result = getPartialOperand().getDef() }
|
||||
|
||||
/**
|
||||
* Gets the bit range `[startBit, endBit)` updated by the partial operand of this `ChiInstruction`, relative to the start address of the total operand.
|
||||
*/
|
||||
final predicate getUpdatedInterval(int startBit, int endBit) {
|
||||
Construction::getIntervalUpdatedByChi(this, startBit, endBit)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -328,6 +328,14 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOper
|
||||
not Construction::isInCycle(useInstr) and
|
||||
strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the operand totally overlaps with its definition and consumes the
|
||||
* bit range `[startBitOffset, endBitOffset)` relative to the start address of the definition.
|
||||
*/
|
||||
predicate getUsedInterval(int startBitOffset, int endBitOffset) {
|
||||
Construction::getUsedInterval(this, startBitOffset, endBitOffset)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -617,3 +617,9 @@ MemoryLocation getOperandMemoryLocation(MemoryOperand operand) {
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the start bit offset of a `MemoryLocation`, if any. */
|
||||
int getStartBitOffset(VariableMemoryLocation location) { result = location.getStartBitOffset() }
|
||||
|
||||
/** Gets the end bit offset of a `MemoryLocation`, if any. */
|
||||
int getEndBitOffset(VariableMemoryLocation location) { result = location.getEndBitOffset() }
|
||||
|
||||
@@ -149,6 +149,34 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the partial operand of this `ChiInstruction` updates the bit range
|
||||
* `[startBitOffset, endBitOffset)` of the total operand.
|
||||
*/
|
||||
cached
|
||||
predicate getIntervalUpdatedByChi(ChiInstruction chi, int startBitOffset, int endBitOffset) {
|
||||
exists(Alias::MemoryLocation location, OldInstruction oldInstruction |
|
||||
oldInstruction = getOldInstruction(chi.getPartial()) and
|
||||
location = Alias::getResultMemoryLocation(oldInstruction) and
|
||||
startBitOffset = Alias::getStartBitOffset(location) and
|
||||
endBitOffset = Alias::getEndBitOffset(location)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `operand` totally overlaps with its definition and consumes the bit range
|
||||
* `[startBitOffset, endBitOffset)`.
|
||||
*/
|
||||
cached
|
||||
predicate getUsedInterval(NonPhiMemoryOperand operand, int startBitOffset, int endBitOffset) {
|
||||
exists(Alias::MemoryLocation location, OldIR::NonPhiMemoryOperand oldOperand |
|
||||
oldOperand = operand.getUse().(OldInstruction).getAnOperand() and
|
||||
location = Alias::getOperandMemoryLocation(oldOperand) and
|
||||
startBitOffset = Alias::getStartBitOffset(location) and
|
||||
endBitOffset = Alias::getEndBitOffset(location)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `instr` is part of a cycle in the operand graph that doesn't go
|
||||
* through a phi instruction and therefore should be impossible.
|
||||
|
||||
@@ -1962,6 +1962,13 @@ class ChiInstruction extends Instruction {
|
||||
* Gets the operand that represents the new value written by the memory write.
|
||||
*/
|
||||
final Instruction getPartial() { result = getPartialOperand().getDef() }
|
||||
|
||||
/**
|
||||
* Gets the bit range `[startBit, endBit)` updated by the partial operand of this `ChiInstruction`, relative to the start address of the total operand.
|
||||
*/
|
||||
final predicate getUpdatedInterval(int startBit, int endBit) {
|
||||
Construction::getIntervalUpdatedByChi(this, startBit, endBit)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -328,6 +328,14 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOper
|
||||
not Construction::isInCycle(useInstr) and
|
||||
strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the operand totally overlaps with its definition and consumes the
|
||||
* bit range `[startBitOffset, endBitOffset)` relative to the start address of the definition.
|
||||
*/
|
||||
predicate getUsedInterval(int startBitOffset, int endBitOffset) {
|
||||
Construction::getUsedInterval(this, startBitOffset, endBitOffset)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -182,6 +182,18 @@ Instruction getMemoryOperandDefinition(
|
||||
none()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the partial operand of this `ChiInstruction` updates the bit range
|
||||
* `[startBitOffset, endBitOffset)` of the total operand.
|
||||
*/
|
||||
predicate getIntervalUpdatedByChi(ChiInstruction chi, int startBit, int endBit) { none() }
|
||||
|
||||
/**
|
||||
* Holds if the operand totally overlaps with its definition and consumes the
|
||||
* bit range `[startBitOffset, endBitOffset)`.
|
||||
*/
|
||||
predicate getUsedInterval(Operand operand, int startBit, int endBit) { none() }
|
||||
|
||||
/** Gets a non-phi instruction that defines an operand of `instr`. */
|
||||
private Instruction getNonPhiOperandDef(Instruction instr) {
|
||||
result = getRegisterOperandDefinition(instr, _)
|
||||
|
||||
@@ -2905,7 +2905,7 @@ predicate exprNeedsCopyIfNotLoaded(Expr expr) {
|
||||
private predicate exprImmediatelyDiscarded(Expr expr) {
|
||||
exists(ExprStmt s |
|
||||
s = expr.getParent() and
|
||||
not exists(StmtExpr se | s = se.getStmt().(Block).getLastStmt())
|
||||
not exists(StmtExpr se | s = se.getStmt().(BlockStmt).getLastStmt())
|
||||
)
|
||||
or
|
||||
exists(CommaExpr c | c.getLeftOperand() = expr)
|
||||
|
||||
@@ -290,7 +290,7 @@ class TranslatedTryStmt extends TranslatedStmt {
|
||||
}
|
||||
|
||||
class TranslatedBlock extends TranslatedStmt {
|
||||
override Block stmt;
|
||||
override BlockStmt stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) { result = getStmt(id) }
|
||||
|
||||
|
||||
@@ -1962,6 +1962,13 @@ class ChiInstruction extends Instruction {
|
||||
* Gets the operand that represents the new value written by the memory write.
|
||||
*/
|
||||
final Instruction getPartial() { result = getPartialOperand().getDef() }
|
||||
|
||||
/**
|
||||
* Gets the bit range `[startBit, endBit)` updated by the partial operand of this `ChiInstruction`, relative to the start address of the total operand.
|
||||
*/
|
||||
final predicate getUpdatedInterval(int startBit, int endBit) {
|
||||
Construction::getIntervalUpdatedByChi(this, startBit, endBit)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -328,6 +328,14 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, NonPhiMemoryOper
|
||||
not Construction::isInCycle(useInstr) and
|
||||
strictcount(Construction::getMemoryOperandDefinition(useInstr, tag, _)) = 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the operand totally overlaps with its definition and consumes the
|
||||
* bit range `[startBitOffset, endBitOffset)` relative to the start address of the definition.
|
||||
*/
|
||||
predicate getUsedInterval(int startBitOffset, int endBitOffset) {
|
||||
Construction::getUsedInterval(this, startBitOffset, endBitOffset)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -149,6 +149,34 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the partial operand of this `ChiInstruction` updates the bit range
|
||||
* `[startBitOffset, endBitOffset)` of the total operand.
|
||||
*/
|
||||
cached
|
||||
predicate getIntervalUpdatedByChi(ChiInstruction chi, int startBitOffset, int endBitOffset) {
|
||||
exists(Alias::MemoryLocation location, OldInstruction oldInstruction |
|
||||
oldInstruction = getOldInstruction(chi.getPartial()) and
|
||||
location = Alias::getResultMemoryLocation(oldInstruction) and
|
||||
startBitOffset = Alias::getStartBitOffset(location) and
|
||||
endBitOffset = Alias::getEndBitOffset(location)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `operand` totally overlaps with its definition and consumes the bit range
|
||||
* `[startBitOffset, endBitOffset)`.
|
||||
*/
|
||||
cached
|
||||
predicate getUsedInterval(NonPhiMemoryOperand operand, int startBitOffset, int endBitOffset) {
|
||||
exists(Alias::MemoryLocation location, OldIR::NonPhiMemoryOperand oldOperand |
|
||||
oldOperand = operand.getUse().(OldInstruction).getAnOperand() and
|
||||
location = Alias::getOperandMemoryLocation(oldOperand) and
|
||||
startBitOffset = Alias::getStartBitOffset(location) and
|
||||
endBitOffset = Alias::getEndBitOffset(location)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `instr` is part of a cycle in the operand graph that doesn't go
|
||||
* through a phi instruction and therefore should be impossible.
|
||||
|
||||
@@ -79,3 +79,9 @@ MemoryLocation getResultMemoryLocation(Instruction instr) {
|
||||
MemoryLocation getOperandMemoryLocation(MemoryOperand operand) {
|
||||
result = getMemoryLocation(getAddressOperandAllocation(operand.getAddressOperand()))
|
||||
}
|
||||
|
||||
/** Gets the start bit offset of a `MemoryLocation`, if any. */
|
||||
int getStartBitOffset(MemoryLocation location) { none() }
|
||||
|
||||
/** Gets the end bit offset of a `MemoryLocation`, if any. */
|
||||
int getEndBitOffset(MemoryLocation location) { none() }
|
||||
|
||||
@@ -334,7 +334,7 @@ private predicate branchingExpr(Expr expr) {
|
||||
* Gets the number of branching statements and expressions in a block. This is
|
||||
* for computing cyclomatic complexity.
|
||||
*/
|
||||
int cyclomaticComplexityBranches(Block b) {
|
||||
int cyclomaticComplexityBranches(BlockStmt b) {
|
||||
result =
|
||||
count(Stmt stmt |
|
||||
branchingStmt(stmt) and
|
||||
@@ -373,7 +373,7 @@ private predicate skipParent(Stmt s) {
|
||||
exists(Stmt parent | parent = s.getParentStmt() |
|
||||
s instanceof IfStmt and parent.(IfStmt).getElse() = s
|
||||
or
|
||||
parent instanceof Block
|
||||
parent instanceof BlockStmt
|
||||
or
|
||||
exists(File f, int startLine, int startCol |
|
||||
startsAt(s, f, startLine, startCol) and
|
||||
|
||||
@@ -18,3 +18,4 @@ private import implementations.StdContainer
|
||||
private import implementations.StdString
|
||||
private import implementations.Swap
|
||||
private import implementations.GetDelim
|
||||
private import implementations.SmartPointer
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
|
||||
/**
|
||||
* The `std::shared_ptr` and `std::unique_ptr` template classes.
|
||||
*/
|
||||
class UniqueOrSharedPtr extends Class {
|
||||
UniqueOrSharedPtr() { this.hasQualifiedName("std", ["shared_ptr", "unique_ptr"]) }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `std::make_shared` and `std::make_unique` template functions.
|
||||
*/
|
||||
class MakeUniqueOrShared extends TaintFunction {
|
||||
MakeUniqueOrShared() { this.hasQualifiedName("std", ["make_shared", "make_unique"]) }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// Exclude the specializations of `std::make_shared` and `std::make_unique` that allocate arrays
|
||||
// since these just take a size argument, which we don't want to propagate taint through.
|
||||
not this.isArray() and
|
||||
input.isParameter(_) and
|
||||
output.isReturnValue()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the function returns a `shared_ptr<T>` (or `unique_ptr<T>`) where `T` is an
|
||||
* array type (i.e., `U[]` for some type `U`).
|
||||
*/
|
||||
predicate isArray() {
|
||||
this.getTemplateArgument(0).(Type).getUnderlyingType() instanceof ArrayType
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A prefix `operator*` member function for a `shared_ptr` or `unique_ptr` type.
|
||||
*/
|
||||
class UniqueOrSharedDereferenceMemberOperator extends MemberFunction, TaintFunction {
|
||||
UniqueOrSharedDereferenceMemberOperator() {
|
||||
this.hasName("operator*") and
|
||||
this.getDeclaringType() instanceof UniqueOrSharedPtr
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
input.isQualifierObject() and
|
||||
output.isReturnValueDeref()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `std::shared_ptr` or `std::unique_ptr` function `get`.
|
||||
*/
|
||||
class UniqueOrSharedGet extends TaintFunction {
|
||||
UniqueOrSharedGet() {
|
||||
this.hasName("get") and
|
||||
this.getDeclaringType() instanceof UniqueOrSharedPtr
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
input.isQualifierObject() and
|
||||
output.isReturnValue()
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Provides implementation classes modeling `std::string` and other
|
||||
* instantiations of `std::basic_string`. See `semmle.code.cpp.models.Models`
|
||||
* for usage information.
|
||||
* Provides implementation classes modeling `std::string` (and other
|
||||
* instantiations of `std::basic_string`) and `std::ostream`. See
|
||||
* `semmle.code.cpp.models.Models` for usage information.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
@@ -270,3 +270,115 @@ class StdStringAt extends TaintFunction {
|
||||
output.isQualifierObject()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `std::basic_ostream` template class.
|
||||
*/
|
||||
class StdBasicOStream extends TemplateClass {
|
||||
StdBasicOStream() { this.hasQualifiedName("std", "basic_ostream") }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `std::ostream` functions `operator<<` (defined as a member function),
|
||||
* `put` and `write`.
|
||||
*/
|
||||
class StdOStreamOut extends DataFlowFunction, TaintFunction {
|
||||
StdOStreamOut() { this.hasQualifiedName("std", "basic_ostream", ["operator<<", "put", "write"]) }
|
||||
|
||||
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from qualifier to return value
|
||||
input.isQualifierAddress() and
|
||||
output.isReturnValue()
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from first parameter (value or pointer) to qualifier
|
||||
input.isParameter(0) and
|
||||
output.isQualifierObject()
|
||||
or
|
||||
input.isParameterDeref(0) and
|
||||
output.isQualifierObject()
|
||||
or
|
||||
// flow from first parameter (value or pointer) to return value
|
||||
input.isParameter(0) and
|
||||
output.isReturnValueDeref()
|
||||
or
|
||||
input.isParameterDeref(0) and
|
||||
output.isReturnValueDeref()
|
||||
or
|
||||
// reverse flow from returned reference to the qualifier
|
||||
input.isReturnValueDeref() and
|
||||
output.isQualifierObject()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `std::ostream` function `operator<<` (defined as a non-member function).
|
||||
*/
|
||||
class StdOStreamOutNonMember extends DataFlowFunction, TaintFunction {
|
||||
StdOStreamOutNonMember() {
|
||||
this.hasQualifiedName("std", "operator<<") and
|
||||
this.getUnspecifiedType().(ReferenceType).getBaseType() =
|
||||
any(StdBasicOStream s).getAnInstantiation()
|
||||
}
|
||||
|
||||
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from first parameter to return value
|
||||
input.isParameter(0) and
|
||||
output.isReturnValue()
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from second parameter to first parameter
|
||||
input.isParameter(1) and
|
||||
output.isParameterDeref(0)
|
||||
or
|
||||
// flow from second parameter to return value
|
||||
input.isParameter(1) and
|
||||
output.isReturnValueDeref()
|
||||
or
|
||||
// reverse flow from returned reference to the first parameter
|
||||
input.isReturnValueDeref() and
|
||||
output.isParameterDeref(0)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional model for `std::stringstream` constructors that take a string
|
||||
* input parameter.
|
||||
*/
|
||||
class StdStringStreamConstructor extends Constructor, TaintFunction {
|
||||
StdStringStreamConstructor() {
|
||||
this.getDeclaringType().hasQualifiedName("std", "basic_stringstream")
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index of a parameter to this function that is a string.
|
||||
*/
|
||||
int getAStringParameterIndex() {
|
||||
getParameter(result).getType() instanceof ReferenceType // `const std::basic_string &`
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// taint flow from any parameter of string type to the returned object
|
||||
input.isParameterDeref(getAStringParameterIndex()) and
|
||||
output.isReturnValue() // TODO: this should be `isQualifierObject` by our current definitions, but that flow is not yet supported.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `std::stringstream` function `str`.
|
||||
*/
|
||||
class StdStringStreamStr extends TaintFunction {
|
||||
StdStringStreamStr() { this.hasQualifiedName("std", "basic_stringstream", "str") }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from qualifier to return value (if any)
|
||||
input.isQualifierObject() and
|
||||
output.isReturnValue()
|
||||
or
|
||||
// flow from first parameter (if any) to qualifier
|
||||
input.isParameterDeref(0) and
|
||||
output.isQualifierObject()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,6 +171,65 @@ predicate eqOpWithSwapAndNegate(EqualityOperation cmp, Expr a, Expr b, boolean i
|
||||
eqOpWithSwap(cmp, a, b, branch.booleanNot()) and isEQ = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `cmp` is an unconverted conversion of `a` to a Boolean that
|
||||
* evalutes to `isEQ` iff `a` is 0.
|
||||
*
|
||||
* Note that `a` can be `cmp` itself or a conversion thereof.
|
||||
*/
|
||||
private predicate eqZero(Expr cmp, Expr a, boolean isEQ) {
|
||||
// The `!a` expression tests `a` equal to zero when `a` is a number converted
|
||||
// to a Boolean.
|
||||
isEQ = true and
|
||||
exists(Expr notOperand | notOperand = cmp.(NotExpr).getOperand().getFullyConverted() |
|
||||
// In C++ code there will be a BoolConversion in `!myInt`
|
||||
a = notOperand.(BoolConversion).getExpr()
|
||||
or
|
||||
// In C code there is no conversion since there was no bool type before C99
|
||||
a = notOperand and
|
||||
not a instanceof BoolConversion // avoid overlap with the case above
|
||||
)
|
||||
or
|
||||
// The `(bool)a` expression tests `a` NOT equal to zero when `a` is a number
|
||||
// converted to a Boolean. To avoid overlap with the case above, this case
|
||||
// excludes conversions that are right below a `!`.
|
||||
isEQ = false and
|
||||
linearAccess(cmp, _, _, _) and
|
||||
// This test for `isCondition` implies that `cmp` is unconverted and that the
|
||||
// parent of `cfg` is not a `NotExpr` -- the CFG doesn't do branching from
|
||||
// inside `NotExpr`.
|
||||
cmp.isCondition() and
|
||||
// The GNU two-operand conditional expression is not supported for the
|
||||
// purpose of guards, but the value of the conditional expression itself is
|
||||
// modeled in the range analysis.
|
||||
not exists(ConditionalExpr cond | cmp = cond.getCondition() and cond.isTwoOperand()) and
|
||||
(
|
||||
// In C++ code there will be a BoolConversion in `if (myInt)`
|
||||
a = cmp.getFullyConverted().(BoolConversion).getExpr()
|
||||
or
|
||||
// In C code there is no conversion since there was no bool type before C99
|
||||
a = cmp.getFullyConverted() and
|
||||
not a instanceof BoolConversion // avoid overlap with the case above
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `branch` of `cmp` is taken when `a` compares `isEQ` to zero.
|
||||
*
|
||||
* Note that `a` can be `cmp` itself or a conversion thereof.
|
||||
*/
|
||||
predicate eqZeroWithNegate(Expr cmp, Expr a, boolean isEQ, boolean branch) {
|
||||
// The comparison for _equality_ to zero is on the `true` branch when `cmp`
|
||||
// compares equal to zero and on the `false` branch when `cmp` compares not
|
||||
// equal to zero.
|
||||
eqZero(cmp, a, branch) and isEQ = true
|
||||
or
|
||||
// The comparison for _inequality_ to zero is on the `false` branch when
|
||||
// `cmp` compares equal to zero and on the `true` branch when `cmp` compares
|
||||
// not equal to zero.
|
||||
eqZero(cmp, a, branch.booleanNot()) and isEQ = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `expr` is equivalent to `p*v + q`, where `p` is a non-zero
|
||||
* number. This takes into account the associativity, commutativity and
|
||||
|
||||
@@ -40,21 +40,20 @@ library class RangeSSA extends SSAHelper {
|
||||
}
|
||||
}
|
||||
|
||||
private predicate guard_defn(
|
||||
VariableAccess v, ComparisonOperation guard, BasicBlock b, boolean branch
|
||||
) {
|
||||
private predicate guard_defn(VariableAccess v, Expr guard, BasicBlock b, boolean branch) {
|
||||
guardCondition(guard, v, branch) and
|
||||
guardSuccessor(guard, branch, b)
|
||||
}
|
||||
|
||||
private predicate guardCondition(ComparisonOperation guard, VariableAccess v, boolean branch) {
|
||||
private predicate guardCondition(Expr guard, VariableAccess v, boolean branch) {
|
||||
exists(Expr lhs | linearAccess(lhs, v, _, _) |
|
||||
relOpWithSwapAndNegate(guard, lhs, _, _, _, branch) or
|
||||
eqOpWithSwapAndNegate(guard, lhs, _, _, branch)
|
||||
eqOpWithSwapAndNegate(guard, lhs, _, _, branch) or
|
||||
eqZeroWithNegate(guard, lhs, _, branch)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate guardSuccessor(ComparisonOperation guard, boolean branch, BasicBlock succ) {
|
||||
private predicate guardSuccessor(Expr guard, boolean branch, BasicBlock succ) {
|
||||
branch = true and succ = guard.getATrueSuccessor()
|
||||
or
|
||||
branch = false and succ = guard.getAFalseSuccessor()
|
||||
@@ -98,7 +97,7 @@ class RangeSsaDefinition extends ControlFlowNodeBase {
|
||||
* If this definition is a phi node corresponding to a guard,
|
||||
* then return the variable and the guard.
|
||||
*/
|
||||
predicate isGuardPhi(VariableAccess v, ComparisonOperation guard, boolean branch) {
|
||||
predicate isGuardPhi(VariableAccess v, Expr guard, boolean branch) {
|
||||
guard_defn(v, guard, this, branch)
|
||||
}
|
||||
|
||||
|
||||
@@ -427,11 +427,11 @@ private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVaria
|
||||
private predicate phiDependsOnDef(
|
||||
RangeSsaDefinition phi, StackVariable v, RangeSsaDefinition srcDef, StackVariable srcVar
|
||||
) {
|
||||
exists(VariableAccess access, ComparisonOperation guard |
|
||||
exists(VariableAccess access, Expr guard |
|
||||
access = v.getAnAccess() and
|
||||
phi.isGuardPhi(access, guard, _)
|
||||
|
|
||||
exprDependsOnDef(guard.getAnOperand(), srcDef, srcVar) or
|
||||
exprDependsOnDef(guard.(ComparisonOperation).getAnOperand(), srcDef, srcVar) or
|
||||
exprDependsOnDef(access, srcDef, srcVar)
|
||||
)
|
||||
or
|
||||
@@ -570,7 +570,7 @@ private float getTruncatedLowerBounds(Expr expr) {
|
||||
else (
|
||||
// Some of the bounds computed by getLowerBoundsImpl might
|
||||
// overflow, so we replace invalid bounds with exprMinVal.
|
||||
exists(float newLB | newLB = getLowerBoundsImpl(expr) |
|
||||
exists(float newLB | newLB = normalizeFloatUp(getLowerBoundsImpl(expr)) |
|
||||
if exprMinVal(expr) <= newLB and newLB <= exprMaxVal(expr)
|
||||
then result = newLB
|
||||
else result = exprMinVal(expr)
|
||||
@@ -617,7 +617,7 @@ private float getTruncatedUpperBounds(Expr expr) {
|
||||
// Some of the bounds computed by `getUpperBoundsImpl`
|
||||
// might overflow, so we replace invalid bounds with
|
||||
// `exprMaxVal`.
|
||||
exists(float newUB | newUB = getUpperBoundsImpl(expr) |
|
||||
exists(float newUB | newUB = normalizeFloatUp(getUpperBoundsImpl(expr)) |
|
||||
if exprMinVal(expr) <= newUB and newUB <= exprMaxVal(expr)
|
||||
then result = newUB
|
||||
else result = exprMaxVal(expr)
|
||||
@@ -1132,9 +1132,7 @@ private float boolConversionUpperBound(Expr expr) {
|
||||
* use the guard to deduce that the lower bound is 2 inside the block.
|
||||
*/
|
||||
private float getPhiLowerBounds(StackVariable v, RangeSsaDefinition phi) {
|
||||
exists(
|
||||
VariableAccess access, ComparisonOperation guard, boolean branch, float defLB, float guardLB
|
||||
|
|
||||
exists(VariableAccess access, Expr guard, boolean branch, float defLB, float guardLB |
|
||||
access = v.getAnAccess() and
|
||||
phi.isGuardPhi(access, guard, branch) and
|
||||
lowerBoundFromGuard(guard, access, guardLB, branch) and
|
||||
@@ -1146,13 +1144,13 @@ private float getPhiLowerBounds(StackVariable v, RangeSsaDefinition phi) {
|
||||
or
|
||||
exists(VariableAccess access, float neConstant, float lower |
|
||||
isNEPhi(v, phi, access, neConstant) and
|
||||
lower = getFullyConvertedLowerBounds(access) and
|
||||
lower = getTruncatedLowerBounds(access) and
|
||||
if lower = neConstant then result = lower + 1 else result = lower
|
||||
)
|
||||
or
|
||||
exists(VariableAccess access |
|
||||
isUnsupportedGuardPhi(v, phi, access) and
|
||||
result = getFullyConvertedLowerBounds(access)
|
||||
result = getTruncatedLowerBounds(access)
|
||||
)
|
||||
or
|
||||
result = getDefLowerBounds(phi.getAPhiInput(v), v)
|
||||
@@ -1160,9 +1158,7 @@ private float getPhiLowerBounds(StackVariable v, RangeSsaDefinition phi) {
|
||||
|
||||
/** See comment for `getPhiLowerBounds`, above. */
|
||||
private float getPhiUpperBounds(StackVariable v, RangeSsaDefinition phi) {
|
||||
exists(
|
||||
VariableAccess access, ComparisonOperation guard, boolean branch, float defUB, float guardUB
|
||||
|
|
||||
exists(VariableAccess access, Expr guard, boolean branch, float defUB, float guardUB |
|
||||
access = v.getAnAccess() and
|
||||
phi.isGuardPhi(access, guard, branch) and
|
||||
upperBoundFromGuard(guard, access, guardUB, branch) and
|
||||
@@ -1174,13 +1170,13 @@ private float getPhiUpperBounds(StackVariable v, RangeSsaDefinition phi) {
|
||||
or
|
||||
exists(VariableAccess access, float neConstant, float upper |
|
||||
isNEPhi(v, phi, access, neConstant) and
|
||||
upper = getFullyConvertedUpperBounds(access) and
|
||||
upper = getTruncatedUpperBounds(access) and
|
||||
if upper = neConstant then result = upper - 1 else result = upper
|
||||
)
|
||||
or
|
||||
exists(VariableAccess access |
|
||||
isUnsupportedGuardPhi(v, phi, access) and
|
||||
result = getFullyConvertedUpperBounds(access)
|
||||
result = getTruncatedUpperBounds(access)
|
||||
)
|
||||
or
|
||||
result = getDefUpperBounds(phi.getAPhiInput(v), v)
|
||||
@@ -1252,70 +1248,6 @@ private float getDefUpperBoundsImpl(RangeSsaDefinition def, StackVariable v) {
|
||||
unanalyzableDefBounds(def, v, _, result)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the lower bounds for a `RangeSsaDefinition`. Most of the work is
|
||||
* done by `getDefLowerBoundsImpl`, but this is where widening is applied
|
||||
* to prevent the analysis from exploding due to a recursive definition.
|
||||
*/
|
||||
private float getDefLowerBounds(RangeSsaDefinition def, StackVariable v) {
|
||||
exists(float newLB, float truncatedLB |
|
||||
newLB = getDefLowerBoundsImpl(def, v) and
|
||||
if varMinVal(v) <= newLB and newLB <= varMaxVal(v)
|
||||
then truncatedLB = newLB
|
||||
else truncatedLB = varMinVal(v)
|
||||
|
|
||||
// Widening: check whether the new lower bound is from a source which
|
||||
// depends recursively on the current definition.
|
||||
if isRecursiveDef(def, v)
|
||||
then
|
||||
// The new lower bound is from a recursive source, so we round
|
||||
// down to one of a limited set of values to prevent the
|
||||
// recursion from exploding.
|
||||
result =
|
||||
max(float widenLB |
|
||||
widenLB = wideningLowerBounds(getVariableRangeType(v)) and
|
||||
not widenLB > truncatedLB
|
||||
|
|
||||
widenLB
|
||||
)
|
||||
else result = truncatedLB
|
||||
)
|
||||
or
|
||||
// The definition might overflow positively and wrap. If so, the lower
|
||||
// bound is `typeLowerBound`.
|
||||
defMightOverflowPositively(def, v) and result = varMinVal(v)
|
||||
}
|
||||
|
||||
/** See comment for `getDefLowerBounds`, above. */
|
||||
private float getDefUpperBounds(RangeSsaDefinition def, StackVariable v) {
|
||||
exists(float newUB, float truncatedUB |
|
||||
newUB = getDefUpperBoundsImpl(def, v) and
|
||||
if varMinVal(v) <= newUB and newUB <= varMaxVal(v)
|
||||
then truncatedUB = newUB
|
||||
else truncatedUB = varMaxVal(v)
|
||||
|
|
||||
// Widening: check whether the new upper bound is from a source which
|
||||
// depends recursively on the current definition.
|
||||
if isRecursiveDef(def, v)
|
||||
then
|
||||
// The new upper bound is from a recursive source, so we round
|
||||
// up to one of a fixed set of values to prevent the recursion
|
||||
// from exploding.
|
||||
result =
|
||||
min(float widenUB |
|
||||
widenUB = wideningUpperBounds(getVariableRangeType(v)) and
|
||||
not widenUB < truncatedUB
|
||||
|
|
||||
widenUB
|
||||
)
|
||||
else result = truncatedUB
|
||||
)
|
||||
or
|
||||
// The definition might overflow negatively and wrap. If so, the upper
|
||||
// bound is `typeUpperBound`.
|
||||
defMightOverflowNegatively(def, v) and result = varMaxVal(v)
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for `getDefLowerBounds` and `getDefUpperBounds`. Find the set of
|
||||
* unanalyzable definitions (such as function parameters) and make their
|
||||
@@ -1334,7 +1266,7 @@ private predicate unanalyzableDefBounds(RangeSsaDefinition def, StackVariable v,
|
||||
* inferences about `v`.
|
||||
*/
|
||||
bindingset[guard, v, branch]
|
||||
predicate nonNanGuardedVariable(ComparisonOperation guard, VariableAccess v, boolean branch) {
|
||||
predicate nonNanGuardedVariable(Expr guard, VariableAccess v, boolean branch) {
|
||||
getVariableRangeType(v.getTarget()) instanceof IntegralType
|
||||
or
|
||||
getVariableRangeType(v.getTarget()) instanceof FloatingPointType and
|
||||
@@ -1353,9 +1285,7 @@ predicate nonNanGuardedVariable(ComparisonOperation guard, VariableAccess v, boo
|
||||
* predicate uses the bounds information for `r` to compute a lower bound
|
||||
* for `v`.
|
||||
*/
|
||||
private predicate lowerBoundFromGuard(
|
||||
ComparisonOperation guard, VariableAccess v, float lb, boolean branch
|
||||
) {
|
||||
private predicate lowerBoundFromGuard(Expr guard, VariableAccess v, float lb, boolean branch) {
|
||||
exists(float childLB, RelationStrictness strictness |
|
||||
boundFromGuard(guard, v, childLB, true, strictness, branch)
|
||||
|
|
||||
@@ -1375,9 +1305,7 @@ private predicate lowerBoundFromGuard(
|
||||
* predicate uses the bounds information for `r` to compute a upper bound
|
||||
* for `v`.
|
||||
*/
|
||||
private predicate upperBoundFromGuard(
|
||||
ComparisonOperation guard, VariableAccess v, float ub, boolean branch
|
||||
) {
|
||||
private predicate upperBoundFromGuard(Expr guard, VariableAccess v, float ub, boolean branch) {
|
||||
exists(float childUB, RelationStrictness strictness |
|
||||
boundFromGuard(guard, v, childUB, false, strictness, branch)
|
||||
|
|
||||
@@ -1397,7 +1325,7 @@ private predicate upperBoundFromGuard(
|
||||
* `linearBoundFromGuard`.
|
||||
*/
|
||||
private predicate boundFromGuard(
|
||||
ComparisonOperation guard, VariableAccess v, float boundValue, boolean isLowerBound,
|
||||
Expr guard, VariableAccess v, float boundValue, boolean isLowerBound,
|
||||
RelationStrictness strictness, boolean branch
|
||||
) {
|
||||
exists(float p, float q, float r, boolean isLB |
|
||||
@@ -1410,6 +1338,15 @@ private predicate boundFromGuard(
|
||||
or
|
||||
p < 0 and isLowerBound = isLB.booleanNot()
|
||||
)
|
||||
or
|
||||
// When `!e` is true, we know that `0 <= e <= 0`
|
||||
exists(float p, float q, Expr e |
|
||||
linearAccess(e, v, p, q) and
|
||||
eqZeroWithNegate(guard, e, true, branch) and
|
||||
boundValue = (0.0 - q) / p and
|
||||
isLowerBound = [false, true] and
|
||||
strictness = Nonstrict()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1487,6 +1424,15 @@ private predicate isNEPhi(
|
||||
linearAccess(linearExpr, access, p, q) and
|
||||
neConstant = (r - q) / p
|
||||
)
|
||||
or
|
||||
exists(Expr op, boolean branch, Expr linearExpr, float p, float q |
|
||||
access.getTarget() = v and
|
||||
phi.isGuardPhi(access, op, branch) and
|
||||
eqZeroWithNegate(op, linearExpr, false, branch) and
|
||||
v.getUnspecifiedType() instanceof IntegralOrEnumType and // Float `!` is too imprecise
|
||||
linearAccess(linearExpr, access, p, q) and
|
||||
neConstant = (0.0 - q) / p
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1496,10 +1442,13 @@ private predicate isNEPhi(
|
||||
* compile-time constant.
|
||||
*/
|
||||
private predicate isUnsupportedGuardPhi(Variable v, RangeSsaDefinition phi, VariableAccess access) {
|
||||
exists(ComparisonOperation cmp, boolean branch |
|
||||
exists(Expr cmp, boolean branch |
|
||||
eqOpWithSwapAndNegate(cmp, _, _, false, branch)
|
||||
or
|
||||
eqZeroWithNegate(cmp, _, false, branch)
|
||||
|
|
||||
access.getTarget() = v and
|
||||
phi.isGuardPhi(access, cmp, branch) and
|
||||
eqOpWithSwapAndNegate(cmp, _, _, false, branch) and
|
||||
not isNEPhi(v, phi, access, _)
|
||||
)
|
||||
}
|
||||
@@ -1675,6 +1624,70 @@ module SimpleRangeAnalysisInternal {
|
||||
float getFullyConvertedUpperBounds(Expr expr) {
|
||||
result = getTruncatedUpperBounds(expr.getFullyConverted())
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the lower bounds for a `RangeSsaDefinition`. Most of the work is
|
||||
* done by `getDefLowerBoundsImpl`, but this is where widening is applied
|
||||
* to prevent the analysis from exploding due to a recursive definition.
|
||||
*/
|
||||
float getDefLowerBounds(RangeSsaDefinition def, StackVariable v) {
|
||||
exists(float newLB, float truncatedLB |
|
||||
newLB = getDefLowerBoundsImpl(def, v) and
|
||||
if varMinVal(v) <= newLB and newLB <= varMaxVal(v)
|
||||
then truncatedLB = newLB
|
||||
else truncatedLB = varMinVal(v)
|
||||
|
|
||||
// Widening: check whether the new lower bound is from a source which
|
||||
// depends recursively on the current definition.
|
||||
if isRecursiveDef(def, v)
|
||||
then
|
||||
// The new lower bound is from a recursive source, so we round
|
||||
// down to one of a limited set of values to prevent the
|
||||
// recursion from exploding.
|
||||
result =
|
||||
max(float widenLB |
|
||||
widenLB = wideningLowerBounds(getVariableRangeType(v)) and
|
||||
not widenLB > truncatedLB
|
||||
|
|
||||
widenLB
|
||||
)
|
||||
else result = truncatedLB
|
||||
)
|
||||
or
|
||||
// The definition might overflow positively and wrap. If so, the lower
|
||||
// bound is `typeLowerBound`.
|
||||
defMightOverflowPositively(def, v) and result = varMinVal(v)
|
||||
}
|
||||
|
||||
/** See comment for `getDefLowerBounds`, above. */
|
||||
float getDefUpperBounds(RangeSsaDefinition def, StackVariable v) {
|
||||
exists(float newUB, float truncatedUB |
|
||||
newUB = getDefUpperBoundsImpl(def, v) and
|
||||
if varMinVal(v) <= newUB and newUB <= varMaxVal(v)
|
||||
then truncatedUB = newUB
|
||||
else truncatedUB = varMaxVal(v)
|
||||
|
|
||||
// Widening: check whether the new upper bound is from a source which
|
||||
// depends recursively on the current definition.
|
||||
if isRecursiveDef(def, v)
|
||||
then
|
||||
// The new upper bound is from a recursive source, so we round
|
||||
// up to one of a fixed set of values to prevent the recursion
|
||||
// from exploding.
|
||||
result =
|
||||
min(float widenUB |
|
||||
widenUB = wideningUpperBounds(getVariableRangeType(v)) and
|
||||
not widenUB < truncatedUB
|
||||
|
|
||||
widenUB
|
||||
)
|
||||
else result = truncatedUB
|
||||
)
|
||||
or
|
||||
// The definition might overflow negatively and wrap. If so, the upper
|
||||
// bound is `typeUpperBound`.
|
||||
defMightOverflowNegatively(def, v) and result = varMaxVal(v)
|
||||
}
|
||||
}
|
||||
|
||||
private import SimpleRangeAnalysisInternal
|
||||
|
||||
@@ -17,8 +17,8 @@ import semmle.code.cpp.stmts.Stmt
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class Block extends Stmt, @stmt_block {
|
||||
override string getAPrimaryQlClass() { result = "Block" }
|
||||
class BlockStmt extends Stmt, @stmt_block {
|
||||
override string getAPrimaryQlClass() { result = "BlockStmt" }
|
||||
|
||||
/**
|
||||
* Gets a child declaration of this block.
|
||||
@@ -76,8 +76,8 @@ class Block extends Stmt, @stmt_block {
|
||||
* the result is the expression statement `a = b`.
|
||||
*/
|
||||
Stmt getLastStmtIn() {
|
||||
if getLastStmt() instanceof Block
|
||||
then result = getLastStmt().(Block).getLastStmtIn()
|
||||
if getLastStmt() instanceof BlockStmt
|
||||
then result = getLastStmt().(BlockStmt).getLastStmtIn()
|
||||
else result = getLastStmt()
|
||||
}
|
||||
|
||||
@@ -126,3 +126,9 @@ class Block extends Stmt, @stmt_block {
|
||||
|
||||
override predicate mayBeGloballyImpure() { this.getAStmt().mayBeGloballyImpure() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: This is now called `BlockStmt` to avoid confusion with
|
||||
* `BasicBlock`.
|
||||
*/
|
||||
deprecated class Block = BlockStmt;
|
||||
|
||||
@@ -25,10 +25,10 @@ class Stmt extends StmtParent, @stmt {
|
||||
/**
|
||||
* Gets the nearest enclosing block of this statement in the source, if any.
|
||||
*/
|
||||
Block getEnclosingBlock() {
|
||||
BlockStmt getEnclosingBlock() {
|
||||
if
|
||||
getParentStmt() instanceof Block and
|
||||
not getParentStmt().(Block).getLocation() instanceof UnknownLocation
|
||||
getParentStmt() instanceof BlockStmt and
|
||||
not getParentStmt().(BlockStmt).getLocation() instanceof UnknownLocation
|
||||
then result = getParentStmt()
|
||||
else result = getParentStmt().getEnclosingBlock()
|
||||
}
|
||||
@@ -53,7 +53,7 @@ class Stmt extends StmtParent, @stmt {
|
||||
* to trace the flow of control instead.
|
||||
*/
|
||||
Stmt getFollowingStmt() {
|
||||
exists(Block b, int i |
|
||||
exists(BlockStmt b, int i |
|
||||
this = b.getStmt(i) and
|
||||
result = b.getStmt(i + 1)
|
||||
)
|
||||
@@ -240,7 +240,7 @@ class IfStmt extends ConditionalStmt, @stmt_if {
|
||||
* ```
|
||||
* if (b) { x = 1; }
|
||||
* ```
|
||||
* the result is the `Block` `{ x = 1; }`.
|
||||
* the result is the `BlockStmt` `{ x = 1; }`.
|
||||
*/
|
||||
Stmt getThen() { if_then(underlyingElement(this), unresolveElement(result)) }
|
||||
|
||||
@@ -251,7 +251,7 @@ class IfStmt extends ConditionalStmt, @stmt_if {
|
||||
* ```
|
||||
* if (b) { x = 1; } else { x = 2; }
|
||||
* ```
|
||||
* the result is the `Block` `{ x = 2; }`, and for
|
||||
* the result is the `BlockStmt` `{ x = 2; }`, and for
|
||||
* ```
|
||||
* if (b) { x = 1; }
|
||||
* ```
|
||||
@@ -326,7 +326,7 @@ class ConstexprIfStmt extends ConditionalStmt, @stmt_constexpr_if {
|
||||
* ```
|
||||
* if constexpr (b) { x = 1; }
|
||||
* ```
|
||||
* the result is the `Block` `{ x = 1; }`.
|
||||
* the result is the `BlockStmt` `{ x = 1; }`.
|
||||
*/
|
||||
Stmt getThen() { constexpr_if_then(underlyingElement(this), unresolveElement(result)) }
|
||||
|
||||
@@ -337,7 +337,7 @@ class ConstexprIfStmt extends ConditionalStmt, @stmt_constexpr_if {
|
||||
* ```
|
||||
* if constexpr (b) { x = 1; } else { x = 2; }
|
||||
* ```
|
||||
* the result is the `Block` `{ x = 2; }`, and for
|
||||
* the result is the `BlockStmt` `{ x = 2; }`, and for
|
||||
* ```
|
||||
* if constexpr (b) { x = 1; }
|
||||
* ```
|
||||
@@ -842,7 +842,7 @@ class RangeBasedForStmt extends Loop, @stmt_range_based_for {
|
||||
* ```
|
||||
* for (int x : xs) { y += x; }
|
||||
* ```
|
||||
* the result is the `Block` `{ y += x; }`.
|
||||
* the result is the `BlockStmt` `{ y += x; }`.
|
||||
*/
|
||||
override Stmt getStmt() { result = this.getChild(5) }
|
||||
|
||||
@@ -1229,7 +1229,7 @@ class SwitchCase extends Stmt, @stmt_switch_case {
|
||||
* DEPRECATED: use `SwitchCase.getAStmt` or `ControlFlowNode.getASuccessor`
|
||||
* rather than this predicate.
|
||||
*
|
||||
* Gets the `Block` statement immediately following this 'switch case'
|
||||
* Gets the `BlockStmt` statement immediately following this 'switch case'
|
||||
* statement, if any.
|
||||
*
|
||||
* For example, for
|
||||
@@ -1250,7 +1250,7 @@ class SwitchCase extends Stmt, @stmt_switch_case {
|
||||
* the `case 7:` has result `{ x = 2; break; }`, `default:` has result
|
||||
* `{ x = 3; }`, and the others have no result.
|
||||
*/
|
||||
deprecated Block getLabelledStmt() {
|
||||
deprecated BlockStmt getLabelledStmt() {
|
||||
exists(int i, Stmt parent |
|
||||
this = parent.getChild(i) and
|
||||
result = parent.getChild(i + 1)
|
||||
@@ -1331,7 +1331,7 @@ class SwitchCase extends Stmt, @stmt_switch_case {
|
||||
* `default:` has results `{ x = 3; }, `x = 4;` and `break;`.
|
||||
*/
|
||||
Stmt getAStmt() {
|
||||
exists(Block b, int i, int j |
|
||||
exists(BlockStmt b, int i, int j |
|
||||
b.getStmt(i) = this and
|
||||
b.getStmt(j) = result and
|
||||
i < j and
|
||||
@@ -1370,8 +1370,8 @@ class SwitchCase extends Stmt, @stmt_switch_case {
|
||||
exists(Stmt lastStmt |
|
||||
lastStmt = this.getAStmt() and
|
||||
not lastStmt.getFollowingStmt() = this.getAStmt() and
|
||||
if lastStmt instanceof Block
|
||||
then result = lastStmt.(Block).getLastStmtIn()
|
||||
if lastStmt instanceof BlockStmt
|
||||
then result = lastStmt.(BlockStmt).getLastStmtIn()
|
||||
else result = lastStmt
|
||||
)
|
||||
}
|
||||
@@ -1528,7 +1528,7 @@ class SwitchStmt extends ConditionalStmt, @stmt_switch {
|
||||
/**
|
||||
* Gets the body statement of this 'switch' statement.
|
||||
*
|
||||
* In almost all cases the result will be a `Block`, but there are
|
||||
* In almost all cases the result will be a `BlockStmt`, but there are
|
||||
* other syntactically valid constructions.
|
||||
*
|
||||
* For example, for
|
||||
@@ -1859,7 +1859,7 @@ class FunctionTryStmt extends TryStmt {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class CatchBlock extends Block {
|
||||
class CatchBlock extends BlockStmt {
|
||||
override string getAPrimaryQlClass() { result = "CatchBlock" }
|
||||
|
||||
CatchBlock() { ishandler(underlyingElement(this)) }
|
||||
@@ -1925,7 +1925,7 @@ class MicrosoftTryExceptStmt extends MicrosoftTryStmt {
|
||||
/** Gets the expression guarding the `__except` statement. */
|
||||
Expr getCondition() { result = getChild(1) }
|
||||
|
||||
/** Gets the `__except` statement (usually a `Block`). */
|
||||
/** Gets the `__except` statement (usually a `BlockStmt`). */
|
||||
Stmt getExcept() { result = getChild(2) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "MicrosoftTryExceptStmt" }
|
||||
@@ -1949,7 +1949,7 @@ class MicrosoftTryFinallyStmt extends MicrosoftTryStmt {
|
||||
|
||||
override string toString() { result = "__try { ... } __finally { ... }" }
|
||||
|
||||
/** Gets the `__finally` statement (usually a `Block`). */
|
||||
/** Gets the `__finally` statement (usually a `BlockStmt`). */
|
||||
Stmt getFinally() { result = getChild(1) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "MicrosoftTryFinallyStmt" }
|
||||
@@ -2108,7 +2108,7 @@ class VlaDeclStmt extends Stmt, @stmt_vla_decl {
|
||||
* declaration statement.
|
||||
*/
|
||||
int getNumberOfVlaDimensionStmts() {
|
||||
exists(Block b, int j |
|
||||
exists(BlockStmt b, int j |
|
||||
this = b.getStmt(j) and
|
||||
result =
|
||||
j - 1 -
|
||||
@@ -2125,7 +2125,7 @@ class VlaDeclStmt extends Stmt, @stmt_vla_decl {
|
||||
*/
|
||||
VlaDimensionStmt getVlaDimensionStmt(int i) {
|
||||
i in [0 .. this.getNumberOfVlaDimensionStmts() - 1] and
|
||||
exists(Block b, int j |
|
||||
exists(BlockStmt b, int j |
|
||||
this = b.getStmt(j) and
|
||||
result = b.getStmt(j - this.getNumberOfVlaDimensionStmts() + i)
|
||||
)
|
||||
|
||||
@@ -414,6 +414,28 @@ function_entry_point(int id: @function ref, unique int entry_point: @stmt ref);
|
||||
|
||||
function_return_type(int id: @function ref, int return_type: @type ref);
|
||||
|
||||
/** If `function` is a coroutine, then this gives the
|
||||
std::experimental::resumable_traits instance associated with it,
|
||||
and the variables representing the `handle` and `promise` for it. */
|
||||
coroutine(
|
||||
unique int function: @function ref,
|
||||
int traits: @type ref,
|
||||
int handle: @variable ref,
|
||||
int promise: @variable ref
|
||||
);
|
||||
|
||||
/** The `new` function used for allocating the coroutine state, if any. */
|
||||
coroutine_new(
|
||||
unique int function: @function ref,
|
||||
int new: @function ref
|
||||
);
|
||||
|
||||
/** The `delete` function used for deallocating the coroutine state, if any. */
|
||||
coroutine_delete(
|
||||
unique int function: @function ref,
|
||||
int delete: @function ref
|
||||
);
|
||||
|
||||
purefunctions(unique int id: @function ref);
|
||||
|
||||
function_deleted(unique int id: @function ref);
|
||||
|
||||
@@ -1536,7 +1536,7 @@
|
||||
</e>
|
||||
<e>
|
||||
<k>seconds</k>
|
||||
<v>11965</v>
|
||||
<v>12700</v>
|
||||
</e>
|
||||
</columnsizes>
|
||||
<dependencies>
|
||||
@@ -1580,14 +1580,19 @@
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>2</a>
|
||||
<b>3</b>
|
||||
<v>21</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>3</a>
|
||||
<b>4</b>
|
||||
<v>2719</v>
|
||||
<v>2599</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>4</a>
|
||||
<b>5</b>
|
||||
<v>6810</v>
|
||||
<v>6909</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
@@ -1633,8 +1638,8 @@
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1091</a>
|
||||
<b>1092</b>
|
||||
<a>1158</a>
|
||||
<b>1159</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
</bs>
|
||||
@@ -1691,13 +1696,13 @@
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>572</a>
|
||||
<b>573</b>
|
||||
<a>590</a>
|
||||
<b>591</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>666</a>
|
||||
<b>667</b>
|
||||
<a>694</a>
|
||||
<b>695</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
</bs>
|
||||
@@ -1714,22 +1719,22 @@
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>7863</v>
|
||||
<v>8653</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>2</a>
|
||||
<b>3</b>
|
||||
<v>2237</v>
|
||||
<v>2588</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>3</a>
|
||||
<b>4</b>
|
||||
<v>1107</v>
|
||||
<b>5</b>
|
||||
<v>1074</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>4</a>
|
||||
<b>641</b>
|
||||
<v>756</v>
|
||||
<a>5</a>
|
||||
<b>629</b>
|
||||
<v>383</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
@@ -1745,7 +1750,7 @@
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>11965</v>
|
||||
<v>12700</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
@@ -1761,17 +1766,17 @@
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>10144</v>
|
||||
<v>11131</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>2</a>
|
||||
<b>3</b>
|
||||
<v>1809</v>
|
||||
<v>1535</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>3</a>
|
||||
<b>4</b>
|
||||
<v>10</v>
|
||||
<v>32</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
@@ -2150,11 +2155,11 @@
|
||||
</e>
|
||||
<e>
|
||||
<k>cpu_seconds</k>
|
||||
<v>8159</v>
|
||||
<v>8093</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>elapsed_seconds</k>
|
||||
<v>197</v>
|
||||
<v>219</v>
|
||||
</e>
|
||||
</columnsizes>
|
||||
<dependencies>
|
||||
@@ -2200,17 +2205,17 @@
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>7106</v>
|
||||
<v>6931</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>2</a>
|
||||
<b>3</b>
|
||||
<v>833</v>
|
||||
<v>954</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>3</a>
|
||||
<b>7</b>
|
||||
<v>219</v>
|
||||
<v>208</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
@@ -2226,12 +2231,12 @@
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>7677</v>
|
||||
<v>7764</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>2</a>
|
||||
<b>3</b>
|
||||
<v>482</v>
|
||||
<v>329</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
@@ -2247,7 +2252,7 @@
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>43</v>
|
||||
<v>54</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>2</a>
|
||||
@@ -2255,13 +2260,18 @@
|
||||
<v>21</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>4</a>
|
||||
<b>5</b>
|
||||
<a>3</a>
|
||||
<b>4</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>6</a>
|
||||
<b>7</b>
|
||||
<a>5</a>
|
||||
<b>6</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>7</a>
|
||||
<b>8</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
@@ -2270,48 +2280,48 @@
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>12</a>
|
||||
<b>13</b>
|
||||
<a>11</a>
|
||||
<b>12</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>13</a>
|
||||
<b>14</b>
|
||||
<a>17</a>
|
||||
<b>18</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>31</a>
|
||||
<b>32</b>
|
||||
<a>41</a>
|
||||
<b>42</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>32</a>
|
||||
<b>33</b>
|
||||
<a>46</a>
|
||||
<b>47</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>99</a>
|
||||
<b>100</b>
|
||||
<a>47</a>
|
||||
<b>48</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>106</a>
|
||||
<b>107</b>
|
||||
<a>86</a>
|
||||
<b>87</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>149</a>
|
||||
<b>150</b>
|
||||
<a>157</a>
|
||||
<b>158</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>191</a>
|
||||
<b>192</b>
|
||||
<a>183</a>
|
||||
<b>184</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>211</a>
|
||||
<b>212</b>
|
||||
<a>250</a>
|
||||
<b>251</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
</bs>
|
||||
@@ -2328,7 +2338,7 @@
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>43</v>
|
||||
<v>54</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>2</a>
|
||||
@@ -2336,13 +2346,18 @@
|
||||
<v>21</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>4</a>
|
||||
<b>5</b>
|
||||
<a>3</a>
|
||||
<b>4</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>6</a>
|
||||
<b>7</b>
|
||||
<a>5</a>
|
||||
<b>6</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>7</a>
|
||||
<b>8</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
@@ -2351,48 +2366,48 @@
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>12</a>
|
||||
<b>13</b>
|
||||
<a>11</a>
|
||||
<b>12</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>13</a>
|
||||
<b>14</b>
|
||||
<a>17</a>
|
||||
<b>18</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>31</a>
|
||||
<b>32</b>
|
||||
<a>40</a>
|
||||
<b>41</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>32</a>
|
||||
<b>33</b>
|
||||
<a>44</a>
|
||||
<b>45</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>87</a>
|
||||
<b>88</b>
|
||||
<a>46</a>
|
||||
<b>47</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>90</a>
|
||||
<b>91</b>
|
||||
<a>73</a>
|
||||
<b>74</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>138</a>
|
||||
<b>139</b>
|
||||
<a>150</a>
|
||||
<b>151</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>178</a>
|
||||
<b>179</b>
|
||||
<a>164</a>
|
||||
<b>165</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>180</a>
|
||||
<b>181</b>
|
||||
<a>190</a>
|
||||
<b>191</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
</bs>
|
||||
@@ -15740,6 +15755,318 @@
|
||||
</dependencies>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>coroutine</name>
|
||||
<cardinality>2</cardinality>
|
||||
<columnsizes>
|
||||
<e>
|
||||
<k>function</k>
|
||||
<v>2</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>traits</k>
|
||||
<v>2</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>handle</k>
|
||||
<v>2</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>promise</k>
|
||||
<v>2</v>
|
||||
</e>
|
||||
</columnsizes>
|
||||
<dependencies>
|
||||
<dep>
|
||||
<src>function</src>
|
||||
<trg>traits</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>2</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>function</src>
|
||||
<trg>handle</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>2</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>function</src>
|
||||
<trg>promise</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>2</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>traits</src>
|
||||
<trg>function</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>2</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>traits</src>
|
||||
<trg>handle</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>2</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>traits</src>
|
||||
<trg>promise</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>2</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>handle</src>
|
||||
<trg>function</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>2</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>handle</src>
|
||||
<trg>traits</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>2</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>handle</src>
|
||||
<trg>promise</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>2</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>promise</src>
|
||||
<trg>function</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>2</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>promise</src>
|
||||
<trg>traits</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>2</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>promise</src>
|
||||
<trg>handle</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>2</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
</dependencies>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>coroutine_new</name>
|
||||
<cardinality>2</cardinality>
|
||||
<columnsizes>
|
||||
<e>
|
||||
<k>function</k>
|
||||
<v>2</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>new</k>
|
||||
<v>1</v>
|
||||
</e>
|
||||
</columnsizes>
|
||||
<dependencies>
|
||||
<dep>
|
||||
<src>function</src>
|
||||
<trg>new</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>2</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>new</src>
|
||||
<trg>function</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>2</a>
|
||||
<b>3</b>
|
||||
<v>1</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
</dependencies>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>coroutine_delete</name>
|
||||
<cardinality>2</cardinality>
|
||||
<columnsizes>
|
||||
<e>
|
||||
<k>function</k>
|
||||
<v>2</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>delete</k>
|
||||
<v>1</v>
|
||||
</e>
|
||||
</columnsizes>
|
||||
<dependencies>
|
||||
<dep>
|
||||
<src>function</src>
|
||||
<trg>delete</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>2</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>delete</src>
|
||||
<trg>function</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>2</a>
|
||||
<b>3</b>
|
||||
<v>1</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
</dependencies>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>purefunctions</name>
|
||||
<cardinality>20748</cardinality>
|
||||
<columnsizes>
|
||||
@@ -32948,11 +33275,11 @@
|
||||
</e>
|
||||
<e>
|
||||
<k>kind</k>
|
||||
<v>598</v>
|
||||
<v>1096</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>location</k>
|
||||
<v>5472231</v>
|
||||
<v>3623249</v>
|
||||
</e>
|
||||
</columnsizes>
|
||||
<dependencies>
|
||||
@@ -32996,69 +33323,69 @@
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>8</b>
|
||||
<v>52</v>
|
||||
<a>2</a>
|
||||
<b>14</b>
|
||||
<v>87</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>8</a>
|
||||
<b>18</b>
|
||||
<v>52</v>
|
||||
<a>15</a>
|
||||
<b>50</b>
|
||||
<v>87</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>21</a>
|
||||
<b>62</b>
|
||||
<v>45</v>
|
||||
<a>50</a>
|
||||
<b>90</b>
|
||||
<v>87</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>100</a>
|
||||
<b>150</b>
|
||||
<v>45</v>
|
||||
<a>90</a>
|
||||
<b>223</b>
|
||||
<v>87</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>213</a>
|
||||
<b>506</b>
|
||||
<v>45</v>
|
||||
<a>306</a>
|
||||
<b>471</b>
|
||||
<v>87</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>531</a>
|
||||
<b>815</b>
|
||||
<v>45</v>
|
||||
<a>484</a>
|
||||
<b>715</b>
|
||||
<v>87</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>835</a>
|
||||
<b>2006</b>
|
||||
<v>45</v>
|
||||
<a>866</a>
|
||||
<b>2036</b>
|
||||
<v>87</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>2338</a>
|
||||
<b>3023</b>
|
||||
<v>45</v>
|
||||
<a>2167</a>
|
||||
<b>2960</b>
|
||||
<v>87</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>3116</a>
|
||||
<b>5545</b>
|
||||
<v>45</v>
|
||||
<a>3202</a>
|
||||
<b>4443</b>
|
||||
<v>87</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>5585</a>
|
||||
<b>10844</b>
|
||||
<v>45</v>
|
||||
<a>4717</a>
|
||||
<b>6425</b>
|
||||
<v>87</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>13459</a>
|
||||
<b>19466</b>
|
||||
<v>45</v>
|
||||
<a>6722</a>
|
||||
<b>13439</b>
|
||||
<v>87</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>20677</a>
|
||||
<b>67545</b>
|
||||
<v>45</v>
|
||||
<a>17876</a>
|
||||
<b>114329</b>
|
||||
<v>87</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>150195</a>
|
||||
<b>817400</b>
|
||||
<v>39</v>
|
||||
<a>192871</a>
|
||||
<b>428312</b>
|
||||
<v>43</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
@@ -33074,72 +33401,67 @@
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>4</b>
|
||||
<v>45</v>
|
||||
<v>98</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>4</a>
|
||||
<b>9</b>
|
||||
<v>45</v>
|
||||
<b>14</b>
|
||||
<v>98</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>12</a>
|
||||
<b>21</b>
|
||||
<v>45</v>
|
||||
<a>14</a>
|
||||
<b>24</b>
|
||||
<v>87</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>21</a>
|
||||
<b>85</b>
|
||||
<v>45</v>
|
||||
<a>24</a>
|
||||
<b>38</b>
|
||||
<v>87</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>86</a>
|
||||
<b>186</b>
|
||||
<v>45</v>
|
||||
<a>38</a>
|
||||
<b>134</b>
|
||||
<v>87</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>191</a>
|
||||
<b>309</b>
|
||||
<v>45</v>
|
||||
<a>144</a>
|
||||
<b>259</b>
|
||||
<v>87</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>419</a>
|
||||
<b>726</b>
|
||||
<v>45</v>
|
||||
<a>270</a>
|
||||
<b>481</b>
|
||||
<v>87</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>740</a>
|
||||
<b>1250</b>
|
||||
<v>45</v>
|
||||
<a>481</a>
|
||||
<b>1076</b>
|
||||
<v>87</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>1517</a>
|
||||
<b>2150</b>
|
||||
<v>45</v>
|
||||
<a>1099</a>
|
||||
<b>1408</b>
|
||||
<v>87</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>2341</a>
|
||||
<b>3754</b>
|
||||
<v>45</v>
|
||||
<a>1427</a>
|
||||
<b>2051</b>
|
||||
<v>87</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>3790</a>
|
||||
<b>7357</b>
|
||||
<v>45</v>
|
||||
<a>2060</a>
|
||||
<b>4561</b>
|
||||
<v>87</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>7374</a>
|
||||
<b>16657</b>
|
||||
<v>45</v>
|
||||
<a>5889</a>
|
||||
<b>60114</b>
|
||||
<v>87</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>18659</a>
|
||||
<b>177300</b>
|
||||
<v>45</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>374826</a>
|
||||
<b>374827</b>
|
||||
<v>6</v>
|
||||
<a>72772</a>
|
||||
<b>118610</b>
|
||||
<v>21</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
@@ -33155,22 +33477,37 @@
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>3700703</v>
|
||||
<v>1680483</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>2</a>
|
||||
<b>3</b>
|
||||
<v>1002541</v>
|
||||
<v>738624</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>3</a>
|
||||
<b>4</b>
|
||||
<v>319926</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>4</a>
|
||||
<b>5</b>
|
||||
<v>434500</v>
|
||||
<v>276890</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>5</a>
|
||||
<b>306832</b>
|
||||
<v>334486</v>
|
||||
<b>9</b>
|
||||
<v>301720</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>9</a>
|
||||
<b>53</b>
|
||||
<v>272120</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>53</a>
|
||||
<b>144478</b>
|
||||
<v>33483</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
@@ -33186,17 +33523,17 @@
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>4305765</v>
|
||||
<v>2586676</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>2</a>
|
||||
<b>3</b>
|
||||
<v>882917</v>
|
||||
<v>807411</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>3</a>
|
||||
<b>20</b>
|
||||
<v>283548</v>
|
||||
<b>30</b>
|
||||
<v>229161</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
|
||||
@@ -19,7 +19,7 @@ AddressOf.c:
|
||||
# 1| params:
|
||||
# 1| 0: [Parameter] i
|
||||
# 1| Type = [IntType] int
|
||||
# 1| body: [Block] { ... }
|
||||
# 1| body: [BlockStmt] { ... }
|
||||
# 2| 0: [DeclStmt] declaration
|
||||
# 2| 0: [VariableDeclarationEntry] definition of j
|
||||
# 2| Type = [IntPointerType] int *
|
||||
@@ -34,7 +34,7 @@ AddressOf.c:
|
||||
ArrayToPointer.c:
|
||||
# 5| [TopLevelFunction] void ArrayToPointer()
|
||||
# 5| params:
|
||||
# 6| body: [Block] { ... }
|
||||
# 6| body: [BlockStmt] { ... }
|
||||
# 7| 0: [DeclStmt] declaration
|
||||
# 7| 0: [VariableDeclarationEntry] definition of c
|
||||
# 7| Type = [ArrayType] char[]
|
||||
@@ -70,7 +70,7 @@ Cast.c:
|
||||
# 1| Type = [CharPointerType] char *
|
||||
# 1| 1: [Parameter] v
|
||||
# 1| Type = [VoidPointerType] void *
|
||||
# 1| body: [Block] { ... }
|
||||
# 1| body: [BlockStmt] { ... }
|
||||
# 2| 0: [ExprStmt] ExprStmt
|
||||
# 2| 0: [AssignExpr] ... = ...
|
||||
# 2| Type = [CharPointerType] char *
|
||||
@@ -89,7 +89,7 @@ Cast.c:
|
||||
ConditionDecl.cpp:
|
||||
# 1| [TopLevelFunction] void ConditionDecl()
|
||||
# 1| params:
|
||||
# 1| body: [Block] { ... }
|
||||
# 1| body: [BlockStmt] { ... }
|
||||
# 2| 0: [DeclStmt] declaration
|
||||
# 2| 0: [VariableDeclarationEntry] definition of j
|
||||
# 2| Type = [IntType] int
|
||||
@@ -109,7 +109,7 @@ ConditionDecl.cpp:
|
||||
# 3| expr: [VariableAccess] k
|
||||
# 3| Type = [IntType] int
|
||||
# 3| ValueCategory = prvalue(load)
|
||||
# 3| 1: [Block] { ... }
|
||||
# 3| 1: [BlockStmt] { ... }
|
||||
# 5| 2: [ReturnStmt] return ...
|
||||
ConstructorCall.cpp:
|
||||
# 1| [CopyAssignmentOperator] C& C::operator=(C const&)
|
||||
@@ -133,7 +133,7 @@ ConstructorCall.cpp:
|
||||
# 3| 0: [Parameter] i
|
||||
# 3| Type = [IntType] int
|
||||
# 3| initializations:
|
||||
# 3| body: [Block] { ... }
|
||||
# 3| body: [BlockStmt] { ... }
|
||||
# 4| 0: [ReturnStmt] return ...
|
||||
# 7| [CopyAssignmentOperator] D& D::operator=(D const&)
|
||||
# 7| params:
|
||||
@@ -154,7 +154,7 @@ ConstructorCall.cpp:
|
||||
# 9| [Constructor] void D::D()
|
||||
# 9| params:
|
||||
# 9| initializations:
|
||||
# 9| body: [Block] { ... }
|
||||
# 9| body: [BlockStmt] { ... }
|
||||
# 10| 0: [ReturnStmt] return ...
|
||||
# 13| [CopyAssignmentOperator] E& E::operator=(E const&)
|
||||
# 13| params:
|
||||
@@ -172,7 +172,7 @@ ConstructorCall.cpp:
|
||||
# 17| Type = [PointerType] D *
|
||||
# 17| 2: [Parameter] e
|
||||
# 17| Type = [PointerType] E *
|
||||
# 17| body: [Block] { ... }
|
||||
# 17| body: [BlockStmt] { ... }
|
||||
# 18| 0: [ExprStmt] ExprStmt
|
||||
# 18| 0: [AssignExpr] ... = ...
|
||||
# 18| Type = [PointerType] C *
|
||||
@@ -221,7 +221,7 @@ ConstructorCall.cpp:
|
||||
Conversion1.c:
|
||||
# 1| [TopLevelFunction] void Conversion1()
|
||||
# 1| params:
|
||||
# 1| body: [Block] { ... }
|
||||
# 1| body: [BlockStmt] { ... }
|
||||
# 2| 0: [DeclStmt] declaration
|
||||
# 2| 0: [VariableDeclarationEntry] definition of i
|
||||
# 2| Type = [IntType] int
|
||||
@@ -241,7 +241,7 @@ Conversion2.c:
|
||||
# 1| params:
|
||||
# 1| 0: [Parameter] x
|
||||
# 1| Type = [IntType] int
|
||||
# 1| body: [Block] { ... }
|
||||
# 1| body: [BlockStmt] { ... }
|
||||
# 2| 0: [ExprStmt] ExprStmt
|
||||
# 2| 0: [AssignExpr] ... = ...
|
||||
# 2| Type = [IntType] int
|
||||
@@ -277,7 +277,7 @@ Conversion3.cpp:
|
||||
# 1| params:
|
||||
# 1| 0: [Parameter] x
|
||||
# 1| Type = [IntType] int
|
||||
# 1| body: [Block] { ... }
|
||||
# 1| body: [BlockStmt] { ... }
|
||||
# 2| 0: [ExprStmt] ExprStmt
|
||||
# 2| 0: [AssignExpr] ... = ...
|
||||
# 2| Type = [IntType] int
|
||||
@@ -327,7 +327,7 @@ Conversion4.c:
|
||||
# 1| params:
|
||||
# 1| 0: [Parameter] x
|
||||
# 1| Type = [IntType] int
|
||||
# 1| body: [Block] { ... }
|
||||
# 1| body: [BlockStmt] { ... }
|
||||
# 2| 0: [ExprStmt] ExprStmt
|
||||
# 2| 0: [AssignExpr] ... = ...
|
||||
# 2| Type = [IntType] int
|
||||
@@ -350,9 +350,11 @@ Conversion4.c:
|
||||
# 2| ValueCategory = prvalue
|
||||
# 3| 1: [ReturnStmt] return ...
|
||||
DestructorCall.cpp:
|
||||
# 1| [Constructor] void C::C()
|
||||
# 1| params:
|
||||
# 3| [Destructor] void C::~C()
|
||||
# 3| params:
|
||||
# 3| body: [Block] { ... }
|
||||
# 3| body: [BlockStmt] { ... }
|
||||
# 4| 0: [ReturnStmt] return ...
|
||||
# 3| destructions:
|
||||
# 11| [TopLevelFunction] void DestructorCall(C*, D*)
|
||||
@@ -361,7 +363,7 @@ DestructorCall.cpp:
|
||||
# 11| Type = [PointerType] C *
|
||||
# 11| 1: [Parameter] d
|
||||
# 11| Type = [PointerType] D *
|
||||
# 11| body: [Block] { ... }
|
||||
# 11| body: [BlockStmt] { ... }
|
||||
# 12| 0: [ExprStmt] ExprStmt
|
||||
# 12| 0: [DeleteExpr] delete
|
||||
# 12| Type = [VoidType] void
|
||||
@@ -385,7 +387,7 @@ DynamicCast.cpp:
|
||||
# 1| params:
|
||||
#-----| 0: [Parameter] p#0
|
||||
#-----| Type = [LValueReferenceType] const Base &
|
||||
#-----| body: [Block] { ... }
|
||||
#-----| body: [BlockStmt] { ... }
|
||||
#-----| 0: [ReturnStmt] return ...
|
||||
#-----| 0: [ReferenceToExpr] (reference to)
|
||||
#-----| Type = [LValueReferenceType] Base &
|
||||
@@ -412,13 +414,13 @@ DynamicCast.cpp:
|
||||
#-----| Type = [RValueReferenceType] Base &&
|
||||
# 2| [VirtualFunction] void Base::f()
|
||||
# 2| params:
|
||||
# 2| body: [Block] { ... }
|
||||
# 2| body: [BlockStmt] { ... }
|
||||
# 2| 0: [ReturnStmt] return ...
|
||||
# 4| [CopyAssignmentOperator] Derived& Derived::operator=(Derived const&)
|
||||
# 4| params:
|
||||
#-----| 0: [Parameter] p#0
|
||||
#-----| Type = [LValueReferenceType] const Derived &
|
||||
#-----| body: [Block] { ... }
|
||||
#-----| body: [BlockStmt] { ... }
|
||||
#-----| 0: [ExprStmt] ExprStmt
|
||||
#-----| 0: [ReferenceDereferenceExpr] (reference dereference)
|
||||
#-----| Type = [Class] Base
|
||||
@@ -478,7 +480,7 @@ DynamicCast.cpp:
|
||||
#-----| Type = [RValueReferenceType] Derived &&
|
||||
# 5| [VirtualFunction] void Derived::f()
|
||||
# 5| params:
|
||||
# 5| body: [Block] { ... }
|
||||
# 5| body: [BlockStmt] { ... }
|
||||
# 5| 0: [ReturnStmt] return ...
|
||||
# 8| [TopLevelFunction] void DynamicCast(Base*, Derived*)
|
||||
# 8| params:
|
||||
@@ -486,7 +488,7 @@ DynamicCast.cpp:
|
||||
# 8| Type = [PointerType] Base *
|
||||
# 8| 1: [Parameter] d
|
||||
# 8| Type = [PointerType] Derived *
|
||||
# 8| body: [Block] { ... }
|
||||
# 8| body: [BlockStmt] { ... }
|
||||
# 9| 0: [ExprStmt] ExprStmt
|
||||
# 9| 0: [AssignExpr] ... = ...
|
||||
# 9| Type = [PointerType] Derived *
|
||||
@@ -508,7 +510,7 @@ DynamicCast.cpp:
|
||||
# 12| Type = [LValueReferenceType] Base &
|
||||
# 12| 1: [Parameter] d
|
||||
# 12| Type = [LValueReferenceType] Derived &
|
||||
# 12| body: [Block] { ... }
|
||||
# 12| body: [BlockStmt] { ... }
|
||||
# 13| 0: [ExprStmt] ExprStmt
|
||||
# 13| 0: [ReferenceDereferenceExpr] (reference dereference)
|
||||
# 13| Type = [Class] Derived
|
||||
@@ -545,7 +547,7 @@ Parenthesis.c:
|
||||
# 1| params:
|
||||
# 1| 0: [Parameter] i
|
||||
# 1| Type = [IntType] int
|
||||
# 1| body: [Block] { ... }
|
||||
# 1| body: [BlockStmt] { ... }
|
||||
# 2| 0: [ExprStmt] ExprStmt
|
||||
# 2| 0: [AssignExpr] ... = ...
|
||||
# 2| Type = [IntType] int
|
||||
@@ -581,7 +583,7 @@ PointerDereference.c:
|
||||
# 1| Type = [IntPointerType] int *
|
||||
# 1| 1: [Parameter] j
|
||||
# 1| Type = [IntType] int
|
||||
# 1| body: [Block] { ... }
|
||||
# 1| body: [BlockStmt] { ... }
|
||||
# 2| 0: [ExprStmt] ExprStmt
|
||||
# 2| 0: [AssignExpr] ... = ...
|
||||
# 2| Type = [IntType] int
|
||||
@@ -603,7 +605,7 @@ ReferenceDereference.cpp:
|
||||
# 4| Type = [LValueReferenceType] int &
|
||||
# 4| 1: [Parameter] j
|
||||
# 4| Type = [IntType] int
|
||||
# 4| body: [Block] { ... }
|
||||
# 4| body: [BlockStmt] { ... }
|
||||
# 5| 0: [ExprStmt] ExprStmt
|
||||
# 5| 0: [AssignExpr] ... = ...
|
||||
# 5| Type = [IntType] int
|
||||
@@ -623,7 +625,7 @@ ReferenceTo.cpp:
|
||||
# 1| params:
|
||||
# 1| 0: [Parameter] i
|
||||
# 1| Type = [IntPointerType] int *
|
||||
# 1| body: [Block] { ... }
|
||||
# 1| body: [BlockStmt] { ... }
|
||||
# 2| 0: [ReturnStmt] return ...
|
||||
# 2| 0: [ReferenceToExpr] (reference to)
|
||||
# 2| Type = [LValueReferenceType] int &
|
||||
@@ -639,7 +641,7 @@ Sizeof.c:
|
||||
# 1| params:
|
||||
# 1| 0: [Parameter] array
|
||||
# 1| Type = [ArrayType] int[]
|
||||
# 1| body: [Block] { ... }
|
||||
# 1| body: [BlockStmt] { ... }
|
||||
# 2| 0: [DeclStmt] declaration
|
||||
# 2| 0: [VariableDeclarationEntry] definition of i
|
||||
# 2| Type = [IntType] int
|
||||
@@ -676,7 +678,7 @@ Sizeof.c:
|
||||
StatementExpr.c:
|
||||
# 1| [TopLevelFunction] void StatementExpr()
|
||||
# 1| params:
|
||||
# 1| body: [Block] { ... }
|
||||
# 1| body: [BlockStmt] { ... }
|
||||
# 2| 0: [DeclStmt] declaration
|
||||
# 2| 0: [VariableDeclarationEntry] definition of j
|
||||
# 2| Type = [IntType] int
|
||||
@@ -700,7 +702,7 @@ StaticMemberAccess.cpp:
|
||||
# 5| Type = [IntType] int
|
||||
# 5| 1: [Parameter] xref
|
||||
# 5| Type = [LValueReferenceType] X &
|
||||
# 5| body: [Block] { ... }
|
||||
# 5| body: [BlockStmt] { ... }
|
||||
# 7| 0: [ExprStmt] ExprStmt
|
||||
# 7| 0: [AssignExpr] ... = ...
|
||||
# 7| Type = [IntType] int
|
||||
@@ -725,7 +727,7 @@ Subscript.c:
|
||||
# 1| Type = [ArrayType] int[]
|
||||
# 1| 1: [Parameter] j
|
||||
# 1| Type = [IntType] int
|
||||
# 1| body: [Block] { ... }
|
||||
# 1| body: [BlockStmt] { ... }
|
||||
# 2| 0: [ExprStmt] ExprStmt
|
||||
# 2| 0: [AssignExpr] ... = ...
|
||||
# 2| Type = [IntType] int
|
||||
@@ -762,20 +764,20 @@ Throw.cpp:
|
||||
#-----| 0: [Parameter] p#0
|
||||
#-----| Type = [RValueReferenceType] F &&
|
||||
# 2| initializations:
|
||||
# 2| body: [Block] { ... }
|
||||
# 2| body: [BlockStmt] { ... }
|
||||
# 2| 0: [ReturnStmt] return ...
|
||||
# 4| [Constructor] void F::F()
|
||||
# 4| params:
|
||||
# 4| initializations:
|
||||
# 4| body: [Block] { ... }
|
||||
# 4| body: [BlockStmt] { ... }
|
||||
# 4| 0: [ReturnStmt] return ...
|
||||
# 6| [TopLevelFunction] void Throw(int)
|
||||
# 6| params:
|
||||
# 6| 0: [Parameter] i
|
||||
# 6| Type = [IntType] int
|
||||
# 6| body: [Block] { ... }
|
||||
# 6| body: [BlockStmt] { ... }
|
||||
# 7| 0: [TryStmt] try { ... }
|
||||
# 7| 0: [Block] { ... }
|
||||
# 7| 0: [BlockStmt] { ... }
|
||||
# 8| 0: [IfStmt] if (...) ...
|
||||
# 8| 0: [CStyleCast] (bool)...
|
||||
# 8| Conversion = [BoolConversion] conversion to bool
|
||||
@@ -818,13 +820,13 @@ Typeid.cpp:
|
||||
# 7| params:
|
||||
# 13| [VirtualFunction] void Base::v()
|
||||
# 13| params:
|
||||
# 13| body: [Block] { ... }
|
||||
# 13| body: [BlockStmt] { ... }
|
||||
# 13| 0: [ReturnStmt] return ...
|
||||
# 18| [TopLevelFunction] void TypeId(Base*)
|
||||
# 18| params:
|
||||
# 18| 0: [Parameter] bp
|
||||
# 18| Type = [PointerType] Base *
|
||||
# 18| body: [Block] { ... }
|
||||
# 18| body: [BlockStmt] { ... }
|
||||
# 19| 0: [DeclStmt] declaration
|
||||
# 19| 0: [VariableDeclarationEntry] definition of name
|
||||
# 19| Type = [PointerType] const char *
|
||||
@@ -846,7 +848,7 @@ VacuousDestructorCall.cpp:
|
||||
# 2| Type = [TemplateParameter] T
|
||||
# 2| 1: [Parameter] y
|
||||
# 2| Type = [PointerType] T *
|
||||
# 2| body: [Block] { ... }
|
||||
# 2| body: [BlockStmt] { ... }
|
||||
# 3| 0: [ExprStmt] ExprStmt
|
||||
# 3| 0: [ExprCall] call to expression
|
||||
# 3| Type = [UnknownType] unknown
|
||||
@@ -874,7 +876,7 @@ VacuousDestructorCall.cpp:
|
||||
# 2| Type = [IntType] int
|
||||
# 2| 1: [Parameter] y
|
||||
# 2| Type = [IntPointerType] int *
|
||||
# 2| body: [Block] { ... }
|
||||
# 2| body: [BlockStmt] { ... }
|
||||
# 3| 0: [ExprStmt] ExprStmt
|
||||
# 3| 0: [VacuousDestructorCall] (vacuous destructor call)
|
||||
# 3| Type = [VoidType] void
|
||||
@@ -894,7 +896,7 @@ VacuousDestructorCall.cpp:
|
||||
# 7| params:
|
||||
# 7| 0: [Parameter] i
|
||||
# 7| Type = [IntType] int
|
||||
# 7| body: [Block] { ... }
|
||||
# 7| body: [BlockStmt] { ... }
|
||||
# 10| 0: [ExprStmt] ExprStmt
|
||||
# 10| 0: [FunctionCall] call to CallDestructor
|
||||
# 10| Type = [VoidType] void
|
||||
@@ -914,7 +916,7 @@ Varargs.c:
|
||||
# 8| params:
|
||||
# 8| 0: [Parameter] text
|
||||
# 8| Type = [PointerType] const char *
|
||||
# 8| body: [Block] { ... }
|
||||
# 8| body: [BlockStmt] { ... }
|
||||
# 9| 0: [DeclStmt] declaration
|
||||
# 9| 0: [VariableDeclarationEntry] definition of args
|
||||
# 9| Type = [CTypedefType] va_list
|
||||
@@ -947,7 +949,7 @@ macro_etc.c:
|
||||
# 3| params:
|
||||
# 3| 0: [Parameter] i
|
||||
# 3| Type = [IntType] int
|
||||
# 3| body: [Block] { ... }
|
||||
# 3| body: [BlockStmt] { ... }
|
||||
# 4| 0: [DeclStmt] declaration
|
||||
# 4| 0: [TypeDeclarationEntry] definition of u
|
||||
# 4| Type = [LocalUnion] u
|
||||
@@ -997,7 +999,7 @@ macro_etc.c:
|
||||
# 10| ValueCategory = prvalue
|
||||
# 22| [TopLevelFunction] int foo()
|
||||
# 22| params:
|
||||
# 22| body: [Block] { ... }
|
||||
# 22| body: [BlockStmt] { ... }
|
||||
# 23| 0: [DeclStmt] declaration
|
||||
# 23| 0: [VariableDeclarationEntry] definition of t
|
||||
# 23| Type = [IntType] int
|
||||
@@ -1059,7 +1061,7 @@ macro_etc.c:
|
||||
# 27| 0: [VariableAccess] i
|
||||
# 27| Type = [PlainCharType] char
|
||||
# 27| ValueCategory = lvalue
|
||||
# 27| 3: [Block] { ... }
|
||||
# 27| 3: [BlockStmt] { ... }
|
||||
# 27| 0: [ExprStmt] ExprStmt
|
||||
# 27| 0: [AssignAddExpr] ... += ...
|
||||
# 27| Type = [IntType] int
|
||||
@@ -1111,7 +1113,7 @@ macro_etc.c:
|
||||
# 28| 0: [VariableAccess] i
|
||||
# 28| Type = [PlainCharType] char
|
||||
# 28| ValueCategory = lvalue
|
||||
# 28| 3: [Block] { ... }
|
||||
# 28| 3: [BlockStmt] { ... }
|
||||
# 28| 0: [ExprStmt] ExprStmt
|
||||
# 28| 0: [AssignAddExpr] ... += ...
|
||||
# 28| Type = [IntType] int
|
||||
@@ -1210,7 +1212,7 @@ union_etc.cpp:
|
||||
# 2| [Constructor] void S::S()
|
||||
# 2| params:
|
||||
# 2| initializations:
|
||||
# 2| body: [Block] { ... }
|
||||
# 2| body: [BlockStmt] { ... }
|
||||
# 2| 0: [ReturnStmt] return ...
|
||||
# 2| [CopyConstructor] void S::S(S const&)
|
||||
# 2| params:
|
||||
@@ -1240,7 +1242,7 @@ union_etc.cpp:
|
||||
# 6| params:
|
||||
# 6| 0: [Parameter] val
|
||||
# 6| Type = [IntType] int
|
||||
# 6| body: [Block] { ... }
|
||||
# 6| body: [BlockStmt] { ... }
|
||||
# 6| 0: [ExprStmt] ExprStmt
|
||||
# 6| 0: [AssignExpr] ... = ...
|
||||
# 6| Type = [IntType] int
|
||||
@@ -1305,7 +1307,7 @@ union_etc.cpp:
|
||||
#-----| Type = [RValueReferenceType] C &&
|
||||
# 22| [TopLevelFunction] int foo()
|
||||
# 22| params:
|
||||
# 22| body: [Block] { ... }
|
||||
# 22| body: [BlockStmt] { ... }
|
||||
# 23| 0: [DeclStmt] declaration
|
||||
# 23| 0: [VariableDeclarationEntry] definition of s
|
||||
# 23| Type = [Struct] S
|
||||
@@ -1423,7 +1425,7 @@ union_etc.cpp:
|
||||
# 33| params:
|
||||
# 33| 0: [Parameter] val
|
||||
# 33| Type = [IntType] int
|
||||
# 33| body: [Block] { ... }
|
||||
# 33| body: [BlockStmt] { ... }
|
||||
# 33| 0: [ExprStmt] ExprStmt
|
||||
# 33| 0: [AssignExpr] ... = ...
|
||||
# 33| Type = [IntType] int
|
||||
@@ -1440,7 +1442,7 @@ union_etc.cpp:
|
||||
# 33| 1: [ReturnStmt] return ...
|
||||
# 36| [TopLevelFunction] int bar()
|
||||
# 36| params:
|
||||
# 36| body: [Block] { ... }
|
||||
# 36| body: [BlockStmt] { ... }
|
||||
# 37| 0: [DeclStmt] declaration
|
||||
# 37| 0: [VariableDeclarationEntry] definition of s
|
||||
# 37| Type = [PointerType] const T *
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
| foo.h:1:13:1:15 | foo | Function | 1 | <none> |
|
||||
| foo.h:1:13:1:15 | foo | MemberFunction | 1 | C |
|
||||
| foo.h:1:13:1:15 | foo | MemberFunction | 1 | C |
|
||||
| main2.cpp:7:7:7:7 | C | MemberFunction | 0 | C |
|
||||
| main2.cpp:7:7:7:7 | C | MemberFunction | 0 | C |
|
||||
| main2.cpp:7:7:7:7 | operator= | MemberFunction | 0 | C |
|
||||
| main2.cpp:7:7:7:7 | operator= | MemberFunction | 0 | C |
|
||||
| main2.cpp:7:7:7:7 | operator= | MemberFunction | 0 | C |
|
||||
|
||||
@@ -8,89 +8,143 @@
|
||||
| direct_friend::D::f | Can access D::f |
|
||||
| direct_friend::D::f | Can access D::operator= |
|
||||
| direct_friend::D::f | Can access D::x |
|
||||
| field_and_base::P::f | Can access B::B |
|
||||
| field_and_base::P::f | Can access B::operator= |
|
||||
| field_and_base::P::f | Can access P::B |
|
||||
| field_and_base::P::f | Can access P::P |
|
||||
| field_and_base::P::f | Can access P::f |
|
||||
| field_and_base::P::f | Can access P::fieldB |
|
||||
| field_and_base::P::f | Can access P::m |
|
||||
| field_and_base::P::f | Can access P::m_static |
|
||||
| field_and_base::P::f | Can access P::operator= |
|
||||
| friend_class::B::fun | Can access B::B |
|
||||
| friend_class::B::fun | Can access B::a |
|
||||
| friend_class::B::fun | Can access B::b |
|
||||
| friend_class::B::fun | Can access B::fun |
|
||||
| friend_class::B::fun | Can access B::operator= |
|
||||
| friend_class::B::fun | Can access C::C |
|
||||
| friend_class::B::fun | Can access C::operator= |
|
||||
| friend_class::B::fun | Can access D1::D1 |
|
||||
| friend_class::B::fun | Can access D1::operator= |
|
||||
| friend_class::B::fun | Can access D2::D2 |
|
||||
| friend_class::B::fun | Can access D2::operator= |
|
||||
| friend_class::C::fun | Can access B::B |
|
||||
| friend_class::C::fun | Can access B::operator= |
|
||||
| friend_class::C::fun | Can access C::B |
|
||||
| friend_class::C::fun | Can access C::C |
|
||||
| friend_class::C::fun | Can access C::fun |
|
||||
| friend_class::C::fun | Can access C::operator= |
|
||||
| friend_class::C::fun | Can access C::x |
|
||||
| friend_class::C::fun | Can access C::y |
|
||||
| friend_class::C::fun | Can access D1::D1 |
|
||||
| friend_class::C::fun | Can access D1::operator= |
|
||||
| friend_class::C::fun | Can access D2::D2 |
|
||||
| friend_class::C::fun | Can access D2::operator= |
|
||||
| friend_class::D1::fun | Can access B::B |
|
||||
| friend_class::D1::fun | Can access B::a |
|
||||
| friend_class::D1::fun | Can access B::b |
|
||||
| friend_class::D1::fun | Can access B::fun |
|
||||
| friend_class::D1::fun | Can access B::operator= |
|
||||
| friend_class::D1::fun | Can access C::C |
|
||||
| friend_class::D1::fun | Can access C::operator= |
|
||||
| friend_class::D1::fun | Can access D1::C |
|
||||
| friend_class::D1::fun | Can access D1::D1 |
|
||||
| friend_class::D1::fun | Can access D1::fun |
|
||||
| friend_class::D1::fun | Can access D1::operator= |
|
||||
| friend_class::D1::fun | Can access D2::D2 |
|
||||
| friend_class::D1::fun | Can access D2::operator= |
|
||||
| friend_class::D2::fun | Can access B::B |
|
||||
| friend_class::D2::fun | Can access B::a |
|
||||
| friend_class::D2::fun | Can access B::b |
|
||||
| friend_class::D2::fun | Can access B::fun |
|
||||
| friend_class::D2::fun | Can access B::operator= |
|
||||
| friend_class::D2::fun | Can access C::C |
|
||||
| friend_class::D2::fun | Can access C::operator= |
|
||||
| friend_class::D2::fun | Can access D1::D1 |
|
||||
| friend_class::D2::fun | Can access D1::operator= |
|
||||
| friend_class::D2::fun | Can access D2::B |
|
||||
| friend_class::D2::fun | Can access D2::D2 |
|
||||
| friend_class::D2::fun | Can access D2::a |
|
||||
| friend_class::D2::fun | Can access D2::b |
|
||||
| friend_class::D2::fun | Can access D2::fun |
|
||||
| friend_class::D2::fun | Can access D2::operator= |
|
||||
| friend_fun::fun1 | Can access A::operator= |
|
||||
| friend_fun::fun1 | Can access B::B |
|
||||
| friend_fun::fun1 | Can access B::operator= |
|
||||
| friend_fun::fun2 | Can access A::operator= |
|
||||
| friend_fun::fun2 | Can access B::B |
|
||||
| friend_fun::fun2 | Can access B::operator= |
|
||||
| friend_fun::fun2 | Can access B::x |
|
||||
| friend_fun::fun2 | Can access B::y |
|
||||
| mixed::B::fun | Can access A::A |
|
||||
| mixed::B::fun | Can access A::operator= |
|
||||
| mixed::B::fun | Can access B::A |
|
||||
| mixed::B::fun | Can access B::B |
|
||||
| mixed::B::fun | Can access B::fun |
|
||||
| mixed::B::fun | Can access B::operator= |
|
||||
| mixed::B::fun | Can access C::C |
|
||||
| mixed::B::fun | Can access C::operator= |
|
||||
| mixed::B::fun | Can access D::C |
|
||||
| mixed::B::fun | Can access D::D |
|
||||
| mixed::B::fun | Can access D::operator= |
|
||||
| mixed::C::fun | Can access A::A |
|
||||
| mixed::C::fun | Can access A::operator= |
|
||||
| mixed::C::fun | Can access B::B |
|
||||
| mixed::C::fun | Can access B::operator= |
|
||||
| mixed::C::fun | Can access C::B |
|
||||
| mixed::C::fun | Can access C::C |
|
||||
| mixed::C::fun | Can access C::fun |
|
||||
| mixed::C::fun | Can access C::operator= |
|
||||
| mixed::C::fun | Can access D::B |
|
||||
| mixed::C::fun | Can access D::C |
|
||||
| mixed::C::fun | Can access D::D |
|
||||
| mixed::C::fun | Can access D::fun |
|
||||
| mixed::C::fun | Can access D::operator= |
|
||||
| mixed::D::fun | Can access A::A |
|
||||
| mixed::D::fun | Can access A::operator= |
|
||||
| mixed::D::fun | Can access B::B |
|
||||
| mixed::D::fun | Can access B::operator= |
|
||||
| mixed::D::fun | Can access C::B |
|
||||
| mixed::D::fun | Can access C::C |
|
||||
| mixed::D::fun | Can access C::operator= |
|
||||
| mixed::D::fun | Can access D::B |
|
||||
| mixed::D::fun | Can access D::C |
|
||||
| mixed::D::fun | Can access D::D |
|
||||
| mixed::D::fun | Can access D::fun |
|
||||
| mixed::D::fun | Can access D::operator= |
|
||||
| protected_derived::BP::f | Can access B::m |
|
||||
| protected_derived::BP::f | Can access B::operator= |
|
||||
| protected_derived::BP::f | Can access BN::BN |
|
||||
| protected_derived::BP::f | Can access BN::operator= |
|
||||
| protected_derived::BP::f | Can access BP::BP |
|
||||
| protected_derived::BP::f | Can access BP::f |
|
||||
| protected_derived::BP::f | Can access BP::m |
|
||||
| protected_derived::BP::f | Can access BP::operator= |
|
||||
| protected_derived::BP::f | Can access BPNprot::BPNprot |
|
||||
| protected_derived::BP::f | Can access BPNprot::operator= |
|
||||
| protected_derived::BP::f | Can access BPNpub::BP |
|
||||
| protected_derived::BP::f | Can access BPNpub::BPNpub |
|
||||
| protected_derived::BP::f | Can access BPNpub::f |
|
||||
| protected_derived::BP::f | Can access BPNpub::m |
|
||||
| protected_derived::BP::f | Can access BPNpub::operator= |
|
||||
| protected_virtual::P::f | Can access B::B |
|
||||
| protected_virtual::P::f | Can access B::operator= |
|
||||
| protected_virtual::P::f | Can access Nprot::Nprot |
|
||||
| protected_virtual::P::f | Can access Nprot::operator= |
|
||||
| protected_virtual::P::f | Can access Npub::B |
|
||||
| protected_virtual::P::f | Can access Npub::Npub |
|
||||
| protected_virtual::P::f | Can access Npub::m |
|
||||
| protected_virtual::P::f | Can access Npub::operator= |
|
||||
| protected_virtual::P::f | Can access P::B |
|
||||
| protected_virtual::P::f | Can access P::P |
|
||||
| protected_virtual::P::f | Can access P::f |
|
||||
| protected_virtual::P::f | Can access P::m |
|
||||
| protected_virtual::P::f | Can access P::operator= |
|
||||
| simple::Derived::castme | Can access Base::operator= |
|
||||
| simple::Derived::castme | Can access Derived::Derived |
|
||||
| simple::Derived::castme | Can access Derived::castme |
|
||||
| simple::Derived::castme | Can access Derived::operator= |
|
||||
| simple::top | Can access Base::operator= |
|
||||
| simple::top | Can access Derived::Derived |
|
||||
| simple::top | Can access Derived::castme |
|
||||
| simple::top | Can access Derived::operator= |
|
||||
|
||||
@@ -88,14 +88,14 @@ void test_stringstream()
|
||||
ss5 << t;
|
||||
|
||||
sink(ss1);
|
||||
sink(ss2); // tainted [NOT DETECTED]
|
||||
sink(ss2); // tainted
|
||||
sink(ss3); // tainted [NOT DETECTED]
|
||||
sink(ss4); // tainted [NOT DETECTED]
|
||||
sink(ss4); // tainted
|
||||
sink(ss5); // tainted [NOT DETECTED]
|
||||
sink(ss1.str());
|
||||
sink(ss2.str()); // tainted [NOT DETECTED]
|
||||
sink(ss2.str()); // tainted
|
||||
sink(ss3.str()); // tainted [NOT DETECTED]
|
||||
sink(ss4.str()); // tainted [NOT DETECTED]
|
||||
sink(ss4.str()); // tainted
|
||||
sink(ss5.str()); // tainted [NOT DETECTED]
|
||||
}
|
||||
|
||||
|
||||
@@ -197,8 +197,10 @@
|
||||
| globals.cpp:23:15:23:20 | call to getenv | globals.cpp:23:15:23:20 | call to getenv |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | shared.h:5:23:5:31 | sinkparam |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:21:29:21:29 | s |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:43:78:43:104 | p#0 |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:43:114:43:118 | p#1 |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:62:25:62:30 | call to getenv |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:64:36:64:36 | s |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:68:8:68:8 | a |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:68:12:68:17 | call to source |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:70:16:70:21 | call to source |
|
||||
@@ -209,12 +211,31 @@
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:82:16:82:21 | call to source |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:82:16:82:23 | (const char *)... |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:82:16:82:24 | call to basic_string |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:85:6:85:6 | call to operator<< |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:85:6:85:17 | (reference dereference) |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:85:9:85:14 | call to source |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:85:9:85:16 | (const char *)... |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:86:15:86:15 | call to operator<< |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:86:15:86:26 | (reference dereference) |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:86:18:86:23 | call to source |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:86:18:86:25 | (const char *)... |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:87:6:87:6 | call to operator<< |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:87:6:87:19 | (reference dereference) |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:87:6:87:19 | (reference to) |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:87:9:87:14 | call to source |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:87:9:87:16 | (const char *)... |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:87:18:87:18 | call to operator<< |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:87:18:87:26 | (reference dereference) |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:91:7:91:9 | (const stringstream)... |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:91:7:91:9 | (reference to) |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:91:7:91:9 | ss2 |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:93:7:93:9 | (const stringstream)... |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:93:7:93:9 | (reference to) |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:93:7:93:9 | ss4 |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:96:7:96:9 | (const basic_stringstream<char, char_traits<char>, allocator<char>>)... |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:96:7:96:9 | ss2 |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:98:7:98:9 | (const basic_stringstream<char, char_traits<char>, allocator<char>>)... |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:98:7:98:9 | ss4 |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:118:10:118:15 | call to source |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:125:16:125:28 | call to basic_string |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:125:17:125:26 | call to user_input |
|
||||
|
||||
@@ -61,10 +61,31 @@
|
||||
| defaulttainttracking.cpp:208:27:208:32 | call to getenv | defaulttainttracking.cpp:210:8:210:23 | ... + ... | IR only |
|
||||
| globals.cpp:13:15:13:20 | call to getenv | globals.cpp:13:5:13:11 | global1 | AST only |
|
||||
| globals.cpp:23:15:23:20 | call to getenv | globals.cpp:23:5:23:11 | global2 | AST only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:43:78:43:104 | p#0 | IR only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:62:7:62:12 | source | AST only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:64:36:64:36 | s | IR only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:70:16:70:24 | call to basic_string | IR only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:82:16:82:24 | call to basic_string | IR only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:85:6:85:6 | call to operator<< | IR only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:85:6:85:17 | (reference dereference) | IR only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:86:15:86:15 | call to operator<< | IR only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:86:15:86:26 | (reference dereference) | IR only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:87:6:87:6 | call to operator<< | IR only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:87:6:87:19 | (reference dereference) | IR only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:87:6:87:19 | (reference to) | IR only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:87:9:87:16 | (const char *)... | IR only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:87:18:87:18 | call to operator<< | IR only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:87:18:87:26 | (reference dereference) | IR only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:91:7:91:9 | (const stringstream)... | IR only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:91:7:91:9 | (reference to) | IR only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:91:7:91:9 | ss2 | IR only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:93:7:93:9 | (const stringstream)... | IR only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:93:7:93:9 | (reference to) | IR only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:93:7:93:9 | ss4 | IR only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:96:7:96:9 | (const basic_stringstream<char, char_traits<char>, allocator<char>>)... | IR only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:96:7:96:9 | ss2 | IR only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:98:7:98:9 | (const basic_stringstream<char, char_traits<char>, allocator<char>>)... | IR only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:98:7:98:9 | ss4 | IR only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:117:7:117:16 | user_input | AST only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:125:16:125:28 | call to basic_string | IR only |
|
||||
| stl.cpp:62:25:62:30 | call to getenv | stl.cpp:128:9:128:13 | path2 | IR only |
|
||||
|
||||
@@ -48,6 +48,6 @@ void following_pointers(
|
||||
|
||||
int stackArray[2] = { source(), source() };
|
||||
stackArray[0] = source();
|
||||
sink(stackArray); // no flow
|
||||
sink(stackArray); // flow
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
| example.c:24:13:24:18 | coords [post update] | example.c:26:19:26:24 | coords |
|
||||
| example.c:24:13:24:30 | ... = ... | example.c:24:2:24:30 | ... = ... |
|
||||
| example.c:24:13:24:30 | ... = ... | example.c:24:20:24:20 | y [post update] |
|
||||
| example.c:24:20:24:20 | y | example.c:24:13:24:30 | ... = ... |
|
||||
| example.c:24:24:24:30 | ... + ... | example.c:24:13:24:30 | ... = ... |
|
||||
| example.c:26:2:26:25 | ... = ... | example.c:26:9:26:9 | x [post update] |
|
||||
| example.c:26:13:26:16 | call to getX | example.c:26:2:26:25 | ... = ... |
|
||||
|
||||
@@ -428,7 +428,7 @@ void intPointerSourceCaller2() {
|
||||
int local[1];
|
||||
intPointerSource(local);
|
||||
sink(local); // tainted
|
||||
sink(*local); // clean
|
||||
sink(*local); // tainted
|
||||
}
|
||||
|
||||
void intArraySourceCaller() {
|
||||
@@ -441,7 +441,7 @@ void intArraySourceCaller2() {
|
||||
int local[2];
|
||||
intArraySource(local, 2);
|
||||
sink(local); // tainted
|
||||
sink(*local); // clean
|
||||
sink(*local); // tainted
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -468,5 +468,5 @@ void intOutparamSource(int *p) {
|
||||
void viaOutparam() {
|
||||
int x = 0;
|
||||
intOutparamSource(&x);
|
||||
sink(x); // tainted [FALSE NEGATIVE]
|
||||
sink(x); // tainted
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
| clang.cpp:30:27:30:34 | call to getFirst | clang.cpp:28:27:28:32 | call to source |
|
||||
| clang.cpp:37:10:37:11 | m2 | clang.cpp:34:32:34:37 | call to source |
|
||||
| clang.cpp:45:17:45:18 | m2 | clang.cpp:43:35:43:40 | call to source |
|
||||
| clang.cpp:51:8:51:17 | stackArray | clang.cpp:50:19:50:24 | call to source |
|
||||
| dispatch.cpp:11:38:11:38 | x | dispatch.cpp:37:19:37:24 | call to source |
|
||||
| dispatch.cpp:11:38:11:38 | x | dispatch.cpp:45:18:45:23 | call to source |
|
||||
| dispatch.cpp:35:16:35:25 | call to notSource1 | dispatch.cpp:9:37:9:42 | call to source |
|
||||
@@ -79,12 +80,17 @@
|
||||
| test.cpp:424:8:424:12 | local | test.cpp:423:20:423:25 | ref arg & ... |
|
||||
| test.cpp:430:8:430:12 | local | test.cpp:428:7:428:11 | local |
|
||||
| test.cpp:430:8:430:12 | local | test.cpp:429:20:429:24 | ref arg local |
|
||||
| test.cpp:431:8:431:13 | * ... | test.cpp:428:7:428:11 | local |
|
||||
| test.cpp:431:8:431:13 | * ... | test.cpp:429:20:429:24 | ref arg local |
|
||||
| test.cpp:437:8:437:12 | local | test.cpp:435:7:435:11 | local |
|
||||
| test.cpp:437:8:437:12 | local | test.cpp:436:18:436:23 | ref arg & ... |
|
||||
| test.cpp:443:8:443:12 | local | test.cpp:441:7:441:11 | local |
|
||||
| test.cpp:443:8:443:12 | local | test.cpp:442:18:442:22 | ref arg local |
|
||||
| test.cpp:444:8:444:13 | * ... | test.cpp:441:7:441:11 | local |
|
||||
| test.cpp:444:8:444:13 | * ... | test.cpp:442:18:442:22 | ref arg local |
|
||||
| test.cpp:450:9:450:22 | (statement expression) | test.cpp:449:26:449:32 | source1 |
|
||||
| test.cpp:461:8:461:12 | local | test.cpp:449:26:449:32 | source1 |
|
||||
| test.cpp:471:8:471:8 | x | test.cpp:465:8:465:13 | call to source |
|
||||
| true_upon_entry.cpp:21:8:21:8 | x | true_upon_entry.cpp:17:11:17:16 | call to source |
|
||||
| true_upon_entry.cpp:29:8:29:8 | x | true_upon_entry.cpp:27:9:27:14 | call to source |
|
||||
| true_upon_entry.cpp:39:8:39:8 | x | true_upon_entry.cpp:33:11:33:16 | call to source |
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
| BarrierGuard.cpp:60:11:60:16 | BarrierGuard.cpp:62:14:62:14 | AST only |
|
||||
| clang.cpp:12:9:12:20 | clang.cpp:22:8:22:20 | AST only |
|
||||
| clang.cpp:39:42:39:47 | clang.cpp:41:18:41:19 | IR only |
|
||||
| clang.cpp:50:19:50:24 | clang.cpp:51:8:51:17 | AST only |
|
||||
| dispatch.cpp:16:37:16:42 | dispatch.cpp:32:16:32:24 | IR only |
|
||||
| dispatch.cpp:16:37:16:42 | dispatch.cpp:40:15:40:23 | IR only |
|
||||
| dispatch.cpp:22:37:22:42 | dispatch.cpp:31:16:31:24 | IR only |
|
||||
@@ -41,11 +42,16 @@
|
||||
| test.cpp:422:7:422:11 | test.cpp:424:8:424:12 | AST only |
|
||||
| test.cpp:423:20:423:25 | test.cpp:424:8:424:12 | AST only |
|
||||
| test.cpp:428:7:428:11 | test.cpp:430:8:430:12 | AST only |
|
||||
| test.cpp:428:7:428:11 | test.cpp:431:8:431:13 | AST only |
|
||||
| test.cpp:429:20:429:24 | test.cpp:430:8:430:12 | AST only |
|
||||
| test.cpp:429:20:429:24 | test.cpp:431:8:431:13 | AST only |
|
||||
| test.cpp:435:7:435:11 | test.cpp:437:8:437:12 | AST only |
|
||||
| test.cpp:436:18:436:23 | test.cpp:437:8:437:12 | AST only |
|
||||
| test.cpp:441:7:441:11 | test.cpp:443:8:443:12 | AST only |
|
||||
| test.cpp:441:7:441:11 | test.cpp:444:8:444:13 | AST only |
|
||||
| test.cpp:442:18:442:22 | test.cpp:443:8:443:12 | AST only |
|
||||
| test.cpp:442:18:442:22 | test.cpp:444:8:444:13 | AST only |
|
||||
| test.cpp:465:8:465:13 | test.cpp:471:8:471:8 | AST only |
|
||||
| true_upon_entry.cpp:9:11:9:16 | true_upon_entry.cpp:13:8:13:8 | IR only |
|
||||
| true_upon_entry.cpp:62:11:62:16 | true_upon_entry.cpp:66:8:66:8 | IR only |
|
||||
| true_upon_entry.cpp:98:11:98:16 | true_upon_entry.cpp:105:8:105:8 | IR only |
|
||||
|
||||
@@ -104,7 +104,7 @@ public:
|
||||
{
|
||||
if (C1 *c1 = dynamic_cast<C1 *>(c))
|
||||
{
|
||||
sink(c1->a); // $ast $ir
|
||||
sink(c1->a); // $ast,ir
|
||||
}
|
||||
C *cc;
|
||||
if (C2 *c2 = dynamic_cast<C2 *>(c))
|
||||
|
||||
@@ -92,3 +92,12 @@ void nestedAssign() {
|
||||
w.s.m1 = user_input();
|
||||
sink(w.s.m1); // $ast,ir
|
||||
}
|
||||
|
||||
void addressOfField() {
|
||||
S s;
|
||||
s.m1 = user_input();
|
||||
|
||||
S s_copy = s;
|
||||
int* px = &s_copy.m1;
|
||||
sink(*px); // $f-:ast $ir
|
||||
}
|
||||
51
cpp/ql/test/library-tests/dataflow/fields/arrays.cpp
Normal file
51
cpp/ql/test/library-tests/dataflow/fields/arrays.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
void sink(void *o);
|
||||
void *user_input(void);
|
||||
|
||||
void local_array() {
|
||||
void *arr[10] = { 0 };
|
||||
arr[0] = user_input();
|
||||
sink(arr[0]); // $ast,ir
|
||||
sink(arr[1]); // $f+:ast
|
||||
sink(*arr); // $ast,ir
|
||||
sink(*&arr[0]); // $ast,ir
|
||||
}
|
||||
|
||||
void local_array_convoluted_assign() {
|
||||
void *arr[10] = { 0 };
|
||||
*&arr[0] = user_input();
|
||||
sink(arr[0]); // $ast,ir
|
||||
sink(arr[1]); // $f+:ast
|
||||
}
|
||||
|
||||
struct inner {
|
||||
void *data;
|
||||
int unrelated;
|
||||
};
|
||||
|
||||
struct middle {
|
||||
inner arr[10];
|
||||
inner *ptr;
|
||||
};
|
||||
|
||||
struct outer {
|
||||
middle nested;
|
||||
middle *indirect;
|
||||
};
|
||||
|
||||
void nested_array_1(outer o) {
|
||||
o.nested.arr[1].data = user_input();
|
||||
sink(o.nested.arr[1].data); // $ast,ir
|
||||
sink(o.nested.arr[0].data); // $f+:ast
|
||||
}
|
||||
|
||||
void nested_array_2(outer o) {
|
||||
o.indirect->arr[1].data = user_input();
|
||||
sink(o.indirect->arr[1].data); // $ast $f-:ir
|
||||
sink(o.indirect->arr[0].data); // $f+:ast
|
||||
}
|
||||
|
||||
void nested_array_3(outer o) {
|
||||
o.indirect->ptr[1].data = user_input();
|
||||
sink(o.indirect->ptr[1].data); // $f-:ast,ir
|
||||
sink(o.indirect->ptr[0].data);
|
||||
}
|
||||
@@ -109,11 +109,11 @@ void test_outer_with_ptr(Outer *pouter) {
|
||||
|
||||
sink(outer.inner_nested.a); // $ast,ir
|
||||
sink(outer.inner_ptr->a); // $ast $f-:ir
|
||||
sink(outer.a); // $f-:ast $f-:ir
|
||||
sink(outer.a); // $ast $f-:ir
|
||||
|
||||
sink(pouter->inner_nested.a); // $ast,ir
|
||||
sink(pouter->inner_ptr->a); // $ast $f-:ir
|
||||
sink(pouter->a); // $f-:ast $f-:ir
|
||||
sink(pouter->a); // $ast $f-:ir
|
||||
}
|
||||
|
||||
void test_outer_with_ref(Outer *pouter) {
|
||||
|
||||
@@ -30,6 +30,12 @@ argHasPostUpdate
|
||||
| D.cpp:43:24:43:40 | new | ArgumentNode is missing PostUpdateNode. |
|
||||
| D.cpp:50:24:50:40 | new | ArgumentNode is missing PostUpdateNode. |
|
||||
| D.cpp:57:25:57:41 | new | ArgumentNode is missing PostUpdateNode. |
|
||||
| arrays.cpp:7:8:7:13 | access to array | ArgumentNode is missing PostUpdateNode. |
|
||||
| arrays.cpp:8:8:8:13 | access to array | ArgumentNode is missing PostUpdateNode. |
|
||||
| arrays.cpp:9:8:9:11 | * ... | ArgumentNode is missing PostUpdateNode. |
|
||||
| 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. |
|
||||
| by_reference.cpp:51:8:51:8 | s | ArgumentNode is missing PostUpdateNode. |
|
||||
| by_reference.cpp:57:8:57:8 | s | ArgumentNode is missing PostUpdateNode. |
|
||||
| by_reference.cpp:63:8:63:8 | s | ArgumentNode is missing PostUpdateNode. |
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
uniqueEnclosingCallable
|
||||
uniqueType
|
||||
uniqueNodeLocation
|
||||
| D.cpp:1:17:1:17 | o | Node should have one location but has 3. |
|
||||
| by_reference.cpp:1:17:1:17 | o | Node should have one location but has 3. |
|
||||
| file://:0:0:0:0 | p#0 | Node should have one location but has 0. |
|
||||
| file://:0:0:0:0 | p#0 | Node should have one location but has 0. |
|
||||
| file://:0:0:0:0 | p#0 | Node should have one location but has 0. |
|
||||
| file://:0:0:0:0 | p#0 | Node should have one location but has 0. |
|
||||
| qualifiers.cpp:1:17:1:17 | o | Node should have one location but has 3. |
|
||||
missingLocation
|
||||
| Nodes without location: 4 |
|
||||
uniqueNodeToString
|
||||
@@ -20,6 +17,7 @@ localCallNodes
|
||||
postIsNotPre
|
||||
postHasUniquePre
|
||||
| simple.cpp:65:5:65:22 | Store | PostUpdateNode should have one pre-update node but has 0. |
|
||||
| simple.cpp:92:5:92:22 | Store | PostUpdateNode should have one pre-update node but has 0. |
|
||||
uniquePostUpdate
|
||||
postIsInSameCallable
|
||||
reverseRead
|
||||
|
||||
@@ -20,10 +20,18 @@
|
||||
| aliasing.cpp:42:11:42:20 | call to user_input | aliasing.cpp:43:13:43:14 | m1 | IR only |
|
||||
| aliasing.cpp:79:11:79:20 | call to user_input | aliasing.cpp:80:12:80:13 | m1 | IR only |
|
||||
| aliasing.cpp:86:10:86:19 | call to user_input | aliasing.cpp:87:12:87:13 | m1 | IR only |
|
||||
| aliasing.cpp:98:10:98:19 | call to user_input | aliasing.cpp:102:8:102:10 | * ... | IR only |
|
||||
| arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:8:8:8:13 | access to array | AST only |
|
||||
| arrays.cpp:15:14:15:23 | call to user_input | arrays.cpp:17:8:17:13 | access to array | AST only |
|
||||
| arrays.cpp:36:26:36:35 | call to user_input | arrays.cpp:38:24:38:27 | data | AST only |
|
||||
| arrays.cpp:42:29:42:38 | call to user_input | arrays.cpp:43:27:43:30 | data | AST only |
|
||||
| arrays.cpp:42:29:42:38 | call to user_input | arrays.cpp:44:27:44:30 | data | AST only |
|
||||
| by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:111:25:111:25 | a | AST only |
|
||||
| by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:115:27:115:27 | a | AST only |
|
||||
| by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:131:25:131:25 | a | AST only |
|
||||
| by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:135:27:135:27 | a | AST only |
|
||||
| by_reference.cpp:92:9:92:18 | call to user_input | by_reference.cpp:112:14:112:14 | a | AST only |
|
||||
| by_reference.cpp:92:9:92:18 | call to user_input | by_reference.cpp:116:16:116:16 | a | AST only |
|
||||
| by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:132:14:132:14 | a | AST only |
|
||||
| by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:136:16:136:16 | a | AST only |
|
||||
| complex.cpp:62:19:62:28 | call to user_input | complex.cpp:52:18:52:18 | call to b | AST only |
|
||||
@@ -36,5 +44,6 @@
|
||||
| qualifiers.cpp:37:38:37:47 | call to user_input | qualifiers.cpp:38:23:38:23 | a | AST only |
|
||||
| qualifiers.cpp:42:29:42:38 | call to user_input | qualifiers.cpp:43:23:43:23 | a | AST only |
|
||||
| qualifiers.cpp:47:31:47:40 | call to user_input | qualifiers.cpp:48:23:48:23 | a | AST only |
|
||||
| realistic.cpp:53:55:53:64 | call to user_input | realistic.cpp:61:47:61:55 | bufferLen | AST only |
|
||||
| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:33:25:33:25 | a | AST only |
|
||||
| struct_init.c:40:20:40:29 | call to user_input | struct_init.c:15:12:15:12 | a | AST only |
|
||||
|
||||
@@ -60,6 +60,15 @@ edges
|
||||
| aliasing.cpp:79:11:79:20 | call to user_input | aliasing.cpp:80:12:80:13 | m1 |
|
||||
| aliasing.cpp:86:10:86:19 | call to user_input | aliasing.cpp:87:12:87:13 | m1 |
|
||||
| aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:93:12:93:13 | m1 |
|
||||
| aliasing.cpp:98:3:98:21 | Chi [m1] | aliasing.cpp:100:14:100:14 | Store [m1] |
|
||||
| aliasing.cpp:98:3:98:21 | Store | aliasing.cpp:98:3:98:21 | Chi [m1] |
|
||||
| aliasing.cpp:98:10:98:19 | call to user_input | aliasing.cpp:98:3:98:21 | Store |
|
||||
| aliasing.cpp:100:14:100:14 | Store [m1] | aliasing.cpp:102:8:102:10 | * ... |
|
||||
| arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:7:8:7:13 | access to array |
|
||||
| arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:9:8:9:11 | * ... |
|
||||
| arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:10:8:10:15 | * ... |
|
||||
| arrays.cpp:15:14:15:23 | call to user_input | arrays.cpp:16:8:16:13 | access to array |
|
||||
| arrays.cpp:36:26:36:35 | call to user_input | arrays.cpp:37:24:37:27 | data |
|
||||
| by_reference.cpp:50:3:50:3 | setDirectly output argument [a] | by_reference.cpp:51:8:51:8 | Argument -1 indirection [a] |
|
||||
| by_reference.cpp:50:17:50:26 | call to user_input | by_reference.cpp:50:3:50:3 | setDirectly output argument [a] |
|
||||
| by_reference.cpp:51:8:51:8 | Argument -1 indirection [a] | by_reference.cpp:51:10:51:20 | call to getDirectly |
|
||||
@@ -158,6 +167,9 @@ edges
|
||||
| simple.cpp:83:9:83:28 | Store | simple.cpp:83:9:83:28 | Chi [f1] |
|
||||
| simple.cpp:83:17:83:26 | call to user_input | simple.cpp:83:9:83:28 | Store |
|
||||
| simple.cpp:84:14:84:20 | Argument -1 indirection [f1] | simple.cpp:84:14:84:20 | call to getf2f1 |
|
||||
| simple.cpp:92:5:92:22 | Store [i] | simple.cpp:93:20:93:20 | Store [i] |
|
||||
| simple.cpp:92:11:92:20 | call to user_input | simple.cpp:92:5:92:22 | Store [i] |
|
||||
| simple.cpp:93:20:93:20 | Store [i] | simple.cpp:94:13:94:13 | i |
|
||||
| struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:15:12:15:12 | a |
|
||||
| struct_init.c:20:20:20:29 | Chi [a] | struct_init.c:24:10:24:12 | Argument 0 indirection [a] |
|
||||
| struct_init.c:20:20:20:29 | Store | struct_init.c:20:20:20:29 | Chi [a] |
|
||||
@@ -247,6 +259,19 @@ nodes
|
||||
| aliasing.cpp:87:12:87:13 | m1 | semmle.label | m1 |
|
||||
| aliasing.cpp:92:12:92:21 | call to user_input | semmle.label | call to user_input |
|
||||
| aliasing.cpp:93:12:93:13 | m1 | semmle.label | m1 |
|
||||
| aliasing.cpp:98:3:98:21 | Chi [m1] | semmle.label | Chi [m1] |
|
||||
| aliasing.cpp:98:3:98:21 | Store | semmle.label | Store |
|
||||
| aliasing.cpp:98:10:98:19 | call to user_input | semmle.label | call to user_input |
|
||||
| aliasing.cpp:100:14:100:14 | Store [m1] | semmle.label | Store [m1] |
|
||||
| aliasing.cpp:102:8:102:10 | * ... | semmle.label | * ... |
|
||||
| arrays.cpp:6:12:6:21 | call to user_input | semmle.label | call to user_input |
|
||||
| arrays.cpp:7:8:7:13 | access to array | semmle.label | access to array |
|
||||
| arrays.cpp:9:8:9:11 | * ... | semmle.label | * ... |
|
||||
| arrays.cpp:10:8:10:15 | * ... | semmle.label | * ... |
|
||||
| arrays.cpp:15:14:15:23 | call to user_input | semmle.label | call to user_input |
|
||||
| arrays.cpp:16:8:16:13 | access to array | semmle.label | access to array |
|
||||
| arrays.cpp:36:26:36:35 | call to user_input | semmle.label | call to user_input |
|
||||
| arrays.cpp:37:24:37:27 | data | semmle.label | data |
|
||||
| by_reference.cpp:50:3:50:3 | setDirectly output argument [a] | semmle.label | setDirectly output argument [a] |
|
||||
| by_reference.cpp:50:17:50:26 | call to user_input | semmle.label | call to user_input |
|
||||
| by_reference.cpp:51:8:51:8 | Argument -1 indirection [a] | semmle.label | Argument -1 indirection [a] |
|
||||
@@ -354,6 +379,10 @@ nodes
|
||||
| simple.cpp:83:17:83:26 | call to user_input | semmle.label | call to user_input |
|
||||
| simple.cpp:84:14:84:20 | Argument -1 indirection [f1] | semmle.label | Argument -1 indirection [f1] |
|
||||
| simple.cpp:84:14:84:20 | call to getf2f1 | semmle.label | call to getf2f1 |
|
||||
| simple.cpp:92:5:92:22 | Store [i] | semmle.label | Store [i] |
|
||||
| simple.cpp:92:11:92:20 | call to user_input | semmle.label | call to user_input |
|
||||
| simple.cpp:93:20:93:20 | Store [i] | semmle.label | Store [i] |
|
||||
| simple.cpp:94:13:94:13 | i | semmle.label | i |
|
||||
| struct_init.c:14:24:14:25 | *ab [a] | semmle.label | *ab [a] |
|
||||
| struct_init.c:15:12:15:12 | a | semmle.label | a |
|
||||
| struct_init.c:20:20:20:29 | Chi [a] | semmle.label | Chi [a] |
|
||||
@@ -385,6 +414,12 @@ nodes
|
||||
| aliasing.cpp:80:12:80:13 | m1 | aliasing.cpp:79:11:79:20 | call to user_input | aliasing.cpp:80:12:80:13 | m1 | m1 flows from $@ | aliasing.cpp:79:11:79:20 | call to user_input | call to user_input |
|
||||
| aliasing.cpp:87:12:87:13 | m1 | aliasing.cpp:86:10:86:19 | call to user_input | aliasing.cpp:87:12:87:13 | m1 | m1 flows from $@ | aliasing.cpp:86:10:86:19 | call to user_input | call to user_input |
|
||||
| aliasing.cpp:93:12:93:13 | m1 | aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:93:12:93:13 | m1 | m1 flows from $@ | aliasing.cpp:92:12:92:21 | call to user_input | call to user_input |
|
||||
| aliasing.cpp:102:8:102:10 | * ... | aliasing.cpp:98:10:98:19 | call to user_input | aliasing.cpp:102:8:102:10 | * ... | * ... flows from $@ | aliasing.cpp:98:10:98:19 | call to user_input | call to user_input |
|
||||
| arrays.cpp:7:8:7:13 | access to array | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:7:8:7:13 | access to array | access to array flows from $@ | arrays.cpp:6:12:6:21 | call to user_input | call to user_input |
|
||||
| arrays.cpp:9:8:9:11 | * ... | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:9:8:9:11 | * ... | * ... flows from $@ | arrays.cpp:6:12:6:21 | call to user_input | call to user_input |
|
||||
| arrays.cpp:10:8:10:15 | * ... | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:10:8:10:15 | * ... | * ... flows from $@ | arrays.cpp:6:12:6:21 | call to user_input | call to user_input |
|
||||
| arrays.cpp:16:8:16:13 | access to array | arrays.cpp:15:14:15:23 | call to user_input | arrays.cpp:16:8:16:13 | access to array | access to array flows from $@ | arrays.cpp:15:14:15:23 | call to user_input | call to user_input |
|
||||
| arrays.cpp:37:24:37:27 | data | arrays.cpp:36:26:36:35 | call to user_input | arrays.cpp:37:24:37:27 | data | data flows from $@ | arrays.cpp:36:26:36:35 | call to user_input | call to user_input |
|
||||
| by_reference.cpp:51:10:51:20 | call to getDirectly | by_reference.cpp:50:17:50:26 | call to user_input | by_reference.cpp:51:10:51:20 | call to getDirectly | call to getDirectly flows from $@ | by_reference.cpp:50:17:50:26 | call to user_input | call to user_input |
|
||||
| by_reference.cpp:57:10:57:22 | call to getIndirectly | by_reference.cpp:56:19:56:28 | call to user_input | by_reference.cpp:57:10:57:22 | call to getIndirectly | call to getIndirectly flows from $@ | by_reference.cpp:56:19:56:28 | call to user_input | call to user_input |
|
||||
| by_reference.cpp:63:10:63:28 | call to getThroughNonMember | by_reference.cpp:62:25:62:34 | call to user_input | by_reference.cpp:63:10:63:28 | call to getThroughNonMember | call to getThroughNonMember flows from $@ | by_reference.cpp:62:25:62:34 | call to user_input | call to user_input |
|
||||
@@ -407,6 +442,7 @@ nodes
|
||||
| simple.cpp:29:12:29:12 | call to b | simple.cpp:42:12:42:21 | call to user_input | simple.cpp:29:12:29:12 | call to b | call to b flows from $@ | simple.cpp:42:12:42:21 | call to user_input | call to user_input |
|
||||
| simple.cpp:67:13:67:13 | i | simple.cpp:65:11:65:20 | call to user_input | simple.cpp:67:13:67:13 | i | i flows from $@ | simple.cpp:65:11:65:20 | call to user_input | call to user_input |
|
||||
| simple.cpp:84:14:84:20 | call to getf2f1 | simple.cpp:83:17:83:26 | call to user_input | simple.cpp:84:14:84:20 | call to getf2f1 | call to getf2f1 flows from $@ | simple.cpp:83:17:83:26 | call to user_input | call to user_input |
|
||||
| simple.cpp:94:13:94:13 | i | simple.cpp:92:11:92:20 | call to user_input | simple.cpp:94:13:94:13 | i | i flows from $@ | simple.cpp:92:11:92:20 | call to user_input | call to user_input |
|
||||
| struct_init.c:15:12:15:12 | a | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input | call to user_input |
|
||||
| struct_init.c:15:12:15:12 | a | struct_init.c:27:7:27:16 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:27:7:27:16 | call to user_input | call to user_input |
|
||||
| struct_init.c:22:11:22:11 | a | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:22:11:22:11 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input | call to user_input |
|
||||
|
||||
@@ -157,6 +157,44 @@
|
||||
| aliasing.cpp:86:5:86:6 | m1 | AST only |
|
||||
| aliasing.cpp:92:3:92:3 | w | AST only |
|
||||
| aliasing.cpp:92:7:92:8 | m1 | AST only |
|
||||
| aliasing.cpp:98:5:98:6 | m1 | AST only |
|
||||
| arrays.cpp:6:3:6:8 | access to array | AST only |
|
||||
| arrays.cpp:15:3:15:10 | * ... | AST only |
|
||||
| arrays.cpp:36:3:36:3 | o | AST only |
|
||||
| arrays.cpp:36:5:36:10 | nested | AST only |
|
||||
| arrays.cpp:36:19:36:22 | data | AST only |
|
||||
| arrays.cpp:37:8:37:8 | o | AST only |
|
||||
| arrays.cpp:37:8:37:22 | access to array | AST only |
|
||||
| arrays.cpp:37:10:37:15 | nested | AST only |
|
||||
| arrays.cpp:37:24:37:27 | data | AST only |
|
||||
| arrays.cpp:38:8:38:8 | o | AST only |
|
||||
| arrays.cpp:38:8:38:22 | access to array | AST only |
|
||||
| arrays.cpp:38:10:38:15 | nested | AST only |
|
||||
| arrays.cpp:38:24:38:27 | data | AST only |
|
||||
| arrays.cpp:42:3:42:3 | o | AST only |
|
||||
| arrays.cpp:42:3:42:20 | access to array | AST only |
|
||||
| arrays.cpp:42:5:42:12 | indirect | AST only |
|
||||
| arrays.cpp:42:22:42:25 | data | AST only |
|
||||
| arrays.cpp:43:8:43:8 | o | AST only |
|
||||
| arrays.cpp:43:8:43:25 | access to array | AST only |
|
||||
| arrays.cpp:43:10:43:17 | indirect | AST only |
|
||||
| arrays.cpp:43:27:43:30 | data | AST only |
|
||||
| arrays.cpp:44:8:44:8 | o | AST only |
|
||||
| arrays.cpp:44:8:44:25 | access to array | AST only |
|
||||
| arrays.cpp:44:10:44:17 | indirect | AST only |
|
||||
| arrays.cpp:44:27:44:30 | data | AST only |
|
||||
| arrays.cpp:48:3:48:3 | o | AST only |
|
||||
| arrays.cpp:48:3:48:20 | access to array | AST only |
|
||||
| arrays.cpp:48:5:48:12 | indirect | AST only |
|
||||
| arrays.cpp:48:22:48:25 | data | AST only |
|
||||
| arrays.cpp:49:8:49:8 | o | AST only |
|
||||
| arrays.cpp:49:8:49:25 | access to array | AST only |
|
||||
| arrays.cpp:49:10:49:17 | indirect | AST only |
|
||||
| arrays.cpp:49:27:49:30 | data | AST only |
|
||||
| arrays.cpp:50:8:50:8 | o | AST only |
|
||||
| arrays.cpp:50:8:50:25 | access to array | AST only |
|
||||
| arrays.cpp:50:10:50:17 | indirect | AST only |
|
||||
| arrays.cpp:50:27:50:30 | data | AST only |
|
||||
| by_reference.cpp:12:8:12:8 | a | AST only |
|
||||
| by_reference.cpp:16:11:16:11 | a | AST only |
|
||||
| by_reference.cpp:20:5:20:8 | this | AST only |
|
||||
@@ -177,6 +215,8 @@
|
||||
| by_reference.cpp:69:8:69:20 | call to nonMemberGetA | AST only |
|
||||
| by_reference.cpp:84:10:84:10 | a | AST only |
|
||||
| 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 |
|
||||
| by_reference.cpp:102:21:102:39 | & ... | AST only |
|
||||
| by_reference.cpp:102:22:102:26 | outer | AST only |
|
||||
| by_reference.cpp:103:21:103:25 | outer | AST only |
|
||||
@@ -304,6 +344,32 @@
|
||||
| qualifiers.cpp:48:10:48:14 | outer | AST only |
|
||||
| qualifiers.cpp:48:16:48:20 | inner | AST only |
|
||||
| qualifiers.cpp:48:23:48:23 | a | AST only |
|
||||
| realistic.cpp:26:5:26:10 | offset | AST only |
|
||||
| realistic.cpp:42:20:42:20 | o | AST only |
|
||||
| realistic.cpp:49:9:49:11 | foo | AST only |
|
||||
| realistic.cpp:49:20:49:22 | baz | AST only |
|
||||
| realistic.cpp:53:9:53:11 | foo | AST only |
|
||||
| realistic.cpp:53:9:53:18 | access to array | AST only |
|
||||
| realistic.cpp:53:20:53:22 | baz | AST only |
|
||||
| realistic.cpp:53:25:53:33 | userInput | AST only |
|
||||
| realistic.cpp:53:35:53:43 | bufferLen | AST only |
|
||||
| realistic.cpp:54:16:54:18 | foo | AST only |
|
||||
| realistic.cpp:54:16:54:25 | access to array | AST only |
|
||||
| realistic.cpp:54:27:54:29 | baz | AST only |
|
||||
| realistic.cpp:54:32:54:40 | userInput | AST only |
|
||||
| realistic.cpp:54:42:54:47 | buffer | AST only |
|
||||
| realistic.cpp:60:16:60:18 | dst | AST only |
|
||||
| realistic.cpp:61:21:61:23 | foo | AST only |
|
||||
| realistic.cpp:61:21:61:30 | access to array | AST only |
|
||||
| realistic.cpp:61:32:61:34 | baz | AST only |
|
||||
| realistic.cpp:61:37:61:45 | userInput | AST only |
|
||||
| realistic.cpp:61:47:61:55 | bufferLen | AST only |
|
||||
| realistic.cpp:65:21:65:23 | foo | AST only |
|
||||
| realistic.cpp:65:21:65:30 | access to array | AST only |
|
||||
| realistic.cpp:65:32:65:34 | baz | AST only |
|
||||
| realistic.cpp:65:37:65:45 | userInput | AST only |
|
||||
| realistic.cpp:65:47:65:52 | buffer | AST only |
|
||||
| realistic.cpp:66:21:66:23 | dst | AST only |
|
||||
| simple.cpp:20:24:20:25 | a_ | AST only |
|
||||
| simple.cpp:21:24:21:25 | b_ | AST only |
|
||||
| simple.cpp:28:10:28:10 | f | AST only |
|
||||
@@ -320,6 +386,7 @@
|
||||
| simple.cpp:83:9:83:10 | this | AST only |
|
||||
| simple.cpp:83:12:83:13 | f1 | AST only |
|
||||
| simple.cpp:84:14:84:20 | this | AST only |
|
||||
| simple.cpp:92:7:92:7 | i | AST only |
|
||||
| struct_init.c:15:8:15:9 | ab | AST only |
|
||||
| struct_init.c:15:12:15:12 | a | AST only |
|
||||
| struct_init.c:16:8:16:9 | ab | AST only |
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
| aliasing.cpp:79:3:79:3 | s |
|
||||
| aliasing.cpp:86:3:86:3 | s |
|
||||
| aliasing.cpp:92:5:92:5 | s |
|
||||
| aliasing.cpp:98:3:98:3 | s |
|
||||
| arrays.cpp:36:3:36:17 | access to array |
|
||||
| by_reference.cpp:12:5:12:5 | s |
|
||||
| by_reference.cpp:16:5:16:8 | this |
|
||||
| by_reference.cpp:84:3:84:7 | inner |
|
||||
@@ -37,7 +39,9 @@
|
||||
| qualifiers.cpp:9:30:9:33 | this |
|
||||
| qualifiers.cpp:12:49:12:53 | inner |
|
||||
| qualifiers.cpp:13:51:13:55 | inner |
|
||||
| realistic.cpp:49:9:49:18 | access to array |
|
||||
| simple.cpp:20:24:20:25 | this |
|
||||
| simple.cpp:21:24:21:25 | this |
|
||||
| simple.cpp:65:5:65:5 | a |
|
||||
| simple.cpp:83:9:83:10 | f2 |
|
||||
| simple.cpp:92:5:92:5 | a |
|
||||
|
||||
@@ -185,6 +185,46 @@
|
||||
| aliasing.cpp:92:3:92:3 | w |
|
||||
| aliasing.cpp:92:5:92:5 | s |
|
||||
| aliasing.cpp:92:7:92:8 | m1 |
|
||||
| aliasing.cpp:98:3:98:3 | s |
|
||||
| aliasing.cpp:98:5:98:6 | m1 |
|
||||
| arrays.cpp:6:3:6:8 | access to array |
|
||||
| arrays.cpp:15:3:15:10 | * ... |
|
||||
| arrays.cpp:36:3:36:3 | o |
|
||||
| arrays.cpp:36:3:36:17 | access to array |
|
||||
| arrays.cpp:36:5:36:10 | nested |
|
||||
| arrays.cpp:36:19:36:22 | data |
|
||||
| arrays.cpp:37:8:37:8 | o |
|
||||
| arrays.cpp:37:8:37:22 | access to array |
|
||||
| arrays.cpp:37:10:37:15 | nested |
|
||||
| arrays.cpp:37:24:37:27 | data |
|
||||
| arrays.cpp:38:8:38:8 | o |
|
||||
| arrays.cpp:38:8:38:22 | access to array |
|
||||
| arrays.cpp:38:10:38:15 | nested |
|
||||
| arrays.cpp:38:24:38:27 | data |
|
||||
| arrays.cpp:42:3:42:3 | o |
|
||||
| arrays.cpp:42:3:42:20 | access to array |
|
||||
| arrays.cpp:42:5:42:12 | indirect |
|
||||
| arrays.cpp:42:22:42:25 | data |
|
||||
| arrays.cpp:43:8:43:8 | o |
|
||||
| arrays.cpp:43:8:43:25 | access to array |
|
||||
| arrays.cpp:43:10:43:17 | indirect |
|
||||
| arrays.cpp:43:27:43:30 | data |
|
||||
| arrays.cpp:44:8:44:8 | o |
|
||||
| arrays.cpp:44:8:44:25 | access to array |
|
||||
| arrays.cpp:44:10:44:17 | indirect |
|
||||
| arrays.cpp:44:27:44:30 | data |
|
||||
| arrays.cpp:48:3:48:3 | o |
|
||||
| arrays.cpp:48:3:48:20 | access to array |
|
||||
| arrays.cpp:48:5:48:12 | indirect |
|
||||
| arrays.cpp:48:22:48:25 | data |
|
||||
| arrays.cpp:49:8:49:8 | o |
|
||||
| arrays.cpp:49:8:49:25 | access to array |
|
||||
| arrays.cpp:49:10:49:17 | indirect |
|
||||
| arrays.cpp:49:27:49:30 | data |
|
||||
| arrays.cpp:50:8:50:8 | o |
|
||||
| arrays.cpp:50:8:50:25 | access to array |
|
||||
| arrays.cpp:50:10:50:17 | indirect |
|
||||
| arrays.cpp:50:27:50:30 | data |
|
||||
| by_reference.cpp:12:5:12:5 | s |
|
||||
| by_reference.cpp:12:8:12:8 | a |
|
||||
| by_reference.cpp:16:5:16:8 | this |
|
||||
@@ -209,6 +249,8 @@
|
||||
| by_reference.cpp:84:10:84:10 | a |
|
||||
| by_reference.cpp:88:3:88:7 | inner |
|
||||
| by_reference.cpp:88:9:88:9 | a |
|
||||
| by_reference.cpp:92:3:92:5 | * ... |
|
||||
| by_reference.cpp:96:3:96:4 | pa |
|
||||
| by_reference.cpp:102:21:102:39 | & ... |
|
||||
| by_reference.cpp:102:22:102:26 | outer |
|
||||
| by_reference.cpp:103:21:103:25 | outer |
|
||||
@@ -343,6 +385,33 @@
|
||||
| qualifiers.cpp:48:10:48:14 | outer |
|
||||
| qualifiers.cpp:48:16:48:20 | inner |
|
||||
| qualifiers.cpp:48:23:48:23 | a |
|
||||
| realistic.cpp:26:5:26:10 | offset |
|
||||
| realistic.cpp:42:20:42:20 | o |
|
||||
| realistic.cpp:49:9:49:11 | foo |
|
||||
| realistic.cpp:49:9:49:18 | access to array |
|
||||
| realistic.cpp:49:20:49:22 | baz |
|
||||
| realistic.cpp:53:9:53:11 | foo |
|
||||
| realistic.cpp:53:9:53:18 | access to array |
|
||||
| realistic.cpp:53:20:53:22 | baz |
|
||||
| realistic.cpp:53:25:53:33 | userInput |
|
||||
| realistic.cpp:53:35:53:43 | bufferLen |
|
||||
| realistic.cpp:54:16:54:18 | foo |
|
||||
| realistic.cpp:54:16:54:25 | access to array |
|
||||
| realistic.cpp:54:27:54:29 | baz |
|
||||
| realistic.cpp:54:32:54:40 | userInput |
|
||||
| realistic.cpp:54:42:54:47 | buffer |
|
||||
| realistic.cpp:60:16:60:18 | dst |
|
||||
| realistic.cpp:61:21:61:23 | foo |
|
||||
| realistic.cpp:61:21:61:30 | access to array |
|
||||
| realistic.cpp:61:32:61:34 | baz |
|
||||
| realistic.cpp:61:37:61:45 | userInput |
|
||||
| realistic.cpp:61:47:61:55 | bufferLen |
|
||||
| realistic.cpp:65:21:65:23 | foo |
|
||||
| realistic.cpp:65:21:65:30 | access to array |
|
||||
| realistic.cpp:65:32:65:34 | baz |
|
||||
| realistic.cpp:65:37:65:45 | userInput |
|
||||
| realistic.cpp:65:47:65:52 | buffer |
|
||||
| realistic.cpp:66:21:66:23 | dst |
|
||||
| simple.cpp:20:24:20:25 | a_ |
|
||||
| simple.cpp:20:24:20:25 | this |
|
||||
| simple.cpp:21:24:21:25 | b_ |
|
||||
@@ -363,6 +432,8 @@
|
||||
| simple.cpp:83:9:83:10 | this |
|
||||
| simple.cpp:83:12:83:13 | f1 |
|
||||
| simple.cpp:84:14:84:20 | this |
|
||||
| simple.cpp:92:5:92:5 | a |
|
||||
| simple.cpp:92:7:92:7 | i |
|
||||
| struct_init.c:15:8:15:9 | ab |
|
||||
| struct_init.c:15:12:15:12 | a |
|
||||
| struct_init.c:16:8:16:9 | ab |
|
||||
|
||||
@@ -155,6 +155,42 @@ edges
|
||||
| aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:92:3:92:23 | ... = ... |
|
||||
| aliasing.cpp:93:8:93:8 | w [s, m1] | aliasing.cpp:93:10:93:10 | s [m1] |
|
||||
| aliasing.cpp:93:10:93:10 | s [m1] | aliasing.cpp:93:12:93:13 | m1 |
|
||||
| arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:7:8:7:13 | access to array |
|
||||
| arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:8:8:8:13 | access to array |
|
||||
| arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:9:8:9:11 | * ... |
|
||||
| arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:10:8:10:15 | * ... |
|
||||
| arrays.cpp:15:14:15:23 | call to user_input | arrays.cpp:16:8:16:13 | access to array |
|
||||
| arrays.cpp:15:14:15:23 | call to user_input | arrays.cpp:17:8:17:13 | access to array |
|
||||
| arrays.cpp:36:3:36:3 | o [post update] [nested, arr, ... (3)] | arrays.cpp:37:8:37:8 | o [nested, arr, ... (3)] |
|
||||
| arrays.cpp:36:3:36:3 | o [post update] [nested, arr, ... (3)] | arrays.cpp:38:8:38:8 | o [nested, arr, ... (3)] |
|
||||
| arrays.cpp:36:3:36:17 | access to array [post update] [data] | arrays.cpp:36:12:36:14 | arr [inner post update] [data] |
|
||||
| arrays.cpp:36:3:36:37 | ... = ... | arrays.cpp:36:3:36:17 | access to array [post update] [data] |
|
||||
| arrays.cpp:36:5:36:10 | nested [post update] [arr, data] | arrays.cpp:36:3:36:3 | o [post update] [nested, arr, ... (3)] |
|
||||
| arrays.cpp:36:12:36:14 | arr [inner post update] [data] | arrays.cpp:36:5:36:10 | nested [post update] [arr, data] |
|
||||
| arrays.cpp:36:26:36:35 | call to user_input | arrays.cpp:36:3:36:37 | ... = ... |
|
||||
| arrays.cpp:37:8:37:8 | o [nested, arr, ... (3)] | arrays.cpp:37:10:37:15 | nested [arr, data] |
|
||||
| arrays.cpp:37:8:37:22 | access to array [data] | arrays.cpp:37:24:37:27 | data |
|
||||
| arrays.cpp:37:10:37:15 | nested [arr, data] | arrays.cpp:37:17:37:19 | arr [data] |
|
||||
| arrays.cpp:37:17:37:19 | arr [data] | arrays.cpp:37:8:37:22 | access to array [data] |
|
||||
| arrays.cpp:38:8:38:8 | o [nested, arr, ... (3)] | arrays.cpp:38:10:38:15 | nested [arr, data] |
|
||||
| arrays.cpp:38:8:38:22 | access to array [data] | arrays.cpp:38:24:38:27 | data |
|
||||
| arrays.cpp:38:10:38:15 | nested [arr, data] | arrays.cpp:38:17:38:19 | arr [data] |
|
||||
| arrays.cpp:38:17:38:19 | arr [data] | arrays.cpp:38:8:38:22 | access to array [data] |
|
||||
| arrays.cpp:42:3:42:3 | o [post update] [indirect, arr, ... (3)] | arrays.cpp:43:8:43:8 | o [indirect, arr, ... (3)] |
|
||||
| arrays.cpp:42:3:42:3 | o [post update] [indirect, arr, ... (3)] | arrays.cpp:44:8:44:8 | o [indirect, arr, ... (3)] |
|
||||
| arrays.cpp:42:3:42:20 | access to array [post update] [data] | arrays.cpp:42:15:42:17 | arr [inner post update] [data] |
|
||||
| arrays.cpp:42:3:42:40 | ... = ... | arrays.cpp:42:3:42:20 | access to array [post update] [data] |
|
||||
| arrays.cpp:42:5:42:12 | indirect [post update] [arr, data] | arrays.cpp:42:3:42:3 | o [post update] [indirect, arr, ... (3)] |
|
||||
| arrays.cpp:42:15:42:17 | arr [inner post update] [data] | arrays.cpp:42:5:42:12 | indirect [post update] [arr, data] |
|
||||
| arrays.cpp:42:29:42:38 | call to user_input | arrays.cpp:42:3:42:40 | ... = ... |
|
||||
| arrays.cpp:43:8:43:8 | o [indirect, arr, ... (3)] | arrays.cpp:43:10:43:17 | indirect [arr, data] |
|
||||
| arrays.cpp:43:8:43:25 | access to array [data] | arrays.cpp:43:27:43:30 | data |
|
||||
| arrays.cpp:43:10:43:17 | indirect [arr, data] | arrays.cpp:43:20:43:22 | arr [data] |
|
||||
| arrays.cpp:43:20:43:22 | arr [data] | arrays.cpp:43:8:43:25 | access to array [data] |
|
||||
| arrays.cpp:44:8:44:8 | o [indirect, arr, ... (3)] | arrays.cpp:44:10:44:17 | indirect [arr, data] |
|
||||
| arrays.cpp:44:8:44:25 | access to array [data] | arrays.cpp:44:27:44:30 | data |
|
||||
| arrays.cpp:44:10:44:17 | indirect [arr, data] | arrays.cpp:44:20:44:22 | arr [data] |
|
||||
| arrays.cpp:44:20:44:22 | arr [data] | arrays.cpp:44:8:44:25 | access to array [data] |
|
||||
| by_reference.cpp:50:3:50:3 | ref arg s [a] | by_reference.cpp:51:8:51:8 | s [a] |
|
||||
| by_reference.cpp:50:17:50:26 | call to user_input | by_reference.cpp:50:3:50:3 | ref arg s [a] |
|
||||
| by_reference.cpp:51:8:51:8 | s [a] | by_reference.cpp:51:10:51:20 | call to getDirectly |
|
||||
@@ -184,6 +220,9 @@ edges
|
||||
| by_reference.cpp:88:3:88:7 | inner [post update] [a] | by_reference.cpp:127:21:127:38 | ref arg * ... [a] |
|
||||
| by_reference.cpp:88:3:88:24 | ... = ... | by_reference.cpp:88:3:88:7 | inner [post update] [a] |
|
||||
| by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:88:3:88:24 | ... = ... |
|
||||
| by_reference.cpp:92:4:92:5 | pa [inner post update] | by_reference.cpp:104:15:104:22 | ref arg & ... |
|
||||
| by_reference.cpp:92:4:92:5 | pa [inner post update] | by_reference.cpp:108:15:108:24 | ref arg & ... |
|
||||
| by_reference.cpp:92:9:92:18 | call to user_input | by_reference.cpp:92:4:92:5 | pa [inner post update] |
|
||||
| by_reference.cpp:95:25:95:26 | pa | by_reference.cpp:124:21:124:21 | ref arg a |
|
||||
| by_reference.cpp:95:25:95:26 | pa | by_reference.cpp:128:23:128:23 | ref arg a |
|
||||
| by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:95:25:95:26 | pa |
|
||||
@@ -192,19 +231,27 @@ edges
|
||||
| by_reference.cpp:102:28:102:39 | inner_nested [inner post update] [a] | by_reference.cpp:102:22:102:26 | outer [post update] [inner_nested, a] |
|
||||
| by_reference.cpp:103:21:103:25 | outer [post update] [inner_ptr, a] | by_reference.cpp:111:8:111:12 | outer [inner_ptr, a] |
|
||||
| by_reference.cpp:103:27:103:35 | ref arg inner_ptr [a] | by_reference.cpp:103:21:103:25 | outer [post update] [inner_ptr, a] |
|
||||
| by_reference.cpp:104:15:104:22 | ref arg & ... | by_reference.cpp:104:22:104:22 | a [inner post update] |
|
||||
| by_reference.cpp:104:16:104:20 | outer [post update] [a] | by_reference.cpp:112:8:112:12 | outer [a] |
|
||||
| by_reference.cpp:104:22:104:22 | a [inner post update] | by_reference.cpp:104:16:104:20 | outer [post update] [a] |
|
||||
| by_reference.cpp:106:21:106:41 | ref arg & ... [a] | by_reference.cpp:106:30:106:41 | inner_nested [inner post update] [a] |
|
||||
| by_reference.cpp:106:22:106:27 | pouter [post update] [inner_nested, a] | by_reference.cpp:114:8:114:13 | pouter [inner_nested, a] |
|
||||
| by_reference.cpp:106:30:106:41 | inner_nested [inner post update] [a] | by_reference.cpp:106:22:106:27 | pouter [post update] [inner_nested, a] |
|
||||
| by_reference.cpp:107:21:107:26 | pouter [post update] [inner_ptr, a] | by_reference.cpp:115:8:115:13 | pouter [inner_ptr, a] |
|
||||
| by_reference.cpp:107:29:107:37 | ref arg inner_ptr [a] | by_reference.cpp:107:21:107:26 | pouter [post update] [inner_ptr, a] |
|
||||
| by_reference.cpp:108:15:108:24 | ref arg & ... | by_reference.cpp:108:24:108:24 | a [inner post update] |
|
||||
| by_reference.cpp:108:16:108:21 | pouter [post update] [a] | by_reference.cpp:116:8:116:13 | pouter [a] |
|
||||
| by_reference.cpp:108:24:108:24 | a [inner post update] | by_reference.cpp:108:16:108:21 | pouter [post update] [a] |
|
||||
| by_reference.cpp:110:8:110:12 | outer [inner_nested, a] | by_reference.cpp:110:14:110:25 | inner_nested [a] |
|
||||
| by_reference.cpp:110:14:110:25 | inner_nested [a] | by_reference.cpp:110:27:110:27 | a |
|
||||
| by_reference.cpp:111:8:111:12 | outer [inner_ptr, a] | by_reference.cpp:111:14:111:22 | inner_ptr [a] |
|
||||
| by_reference.cpp:111:14:111:22 | inner_ptr [a] | by_reference.cpp:111:25:111:25 | a |
|
||||
| by_reference.cpp:112:8:112:12 | outer [a] | by_reference.cpp:112:14:112:14 | a |
|
||||
| by_reference.cpp:114:8:114:13 | pouter [inner_nested, a] | by_reference.cpp:114:16:114:27 | inner_nested [a] |
|
||||
| by_reference.cpp:114:16:114:27 | inner_nested [a] | by_reference.cpp:114:29:114:29 | a |
|
||||
| by_reference.cpp:115:8:115:13 | pouter [inner_ptr, a] | by_reference.cpp:115:16:115:24 | inner_ptr [a] |
|
||||
| by_reference.cpp:115:16:115:24 | inner_ptr [a] | by_reference.cpp:115:27:115:27 | a |
|
||||
| by_reference.cpp:116:8:116:13 | pouter [a] | by_reference.cpp:116:16:116:16 | a |
|
||||
| by_reference.cpp:122:21:122:25 | outer [post update] [inner_nested, a] | by_reference.cpp:130:8:130:12 | outer [inner_nested, a] |
|
||||
| by_reference.cpp:122:27:122:38 | ref arg inner_nested [a] | by_reference.cpp:122:21:122:25 | outer [post update] [inner_nested, a] |
|
||||
| by_reference.cpp:123:21:123:36 | ref arg * ... [a] | by_reference.cpp:123:28:123:36 | inner_ptr [inner post update] [a] |
|
||||
@@ -307,6 +354,18 @@ edges
|
||||
| qualifiers.cpp:47:31:47:40 | call to user_input | qualifiers.cpp:47:5:47:42 | ... = ... |
|
||||
| qualifiers.cpp:48:10:48:14 | outer [inner, a] | qualifiers.cpp:48:16:48:20 | inner [a] |
|
||||
| qualifiers.cpp:48:16:48:20 | inner [a] | qualifiers.cpp:48:23:48:23 | a |
|
||||
| realistic.cpp:53:9:53:11 | foo [post update] [bar, baz, ... (4)] | realistic.cpp:61:21:61:23 | foo [bar, baz, ... (4)] |
|
||||
| realistic.cpp:53:9:53:18 | access to array [post update] [baz, userInput, ... (3)] | realistic.cpp:53:13:53:15 | bar [inner post update] [baz, userInput, ... (3)] |
|
||||
| realistic.cpp:53:9:53:66 | ... = ... | realistic.cpp:53:25:53:33 | userInput [post update] [bufferLen] |
|
||||
| realistic.cpp:53:13:53:15 | bar [inner post update] [baz, userInput, ... (3)] | realistic.cpp:53:9:53:11 | foo [post update] [bar, baz, ... (4)] |
|
||||
| realistic.cpp:53:20:53:22 | baz [post update] [userInput, bufferLen] | realistic.cpp:53:9:53:18 | access to array [post update] [baz, userInput, ... (3)] |
|
||||
| realistic.cpp:53:25:53:33 | userInput [post update] [bufferLen] | realistic.cpp:53:20:53:22 | baz [post update] [userInput, bufferLen] |
|
||||
| realistic.cpp:53:55:53:64 | call to user_input | realistic.cpp:53:9:53:66 | ... = ... |
|
||||
| realistic.cpp:61:21:61:23 | foo [bar, baz, ... (4)] | realistic.cpp:61:25:61:27 | bar [baz, userInput, ... (3)] |
|
||||
| realistic.cpp:61:21:61:30 | access to array [baz, userInput, ... (3)] | realistic.cpp:61:32:61:34 | baz [userInput, bufferLen] |
|
||||
| realistic.cpp:61:25:61:27 | bar [baz, userInput, ... (3)] | realistic.cpp:61:21:61:30 | access to array [baz, userInput, ... (3)] |
|
||||
| realistic.cpp:61:32:61:34 | baz [userInput, bufferLen] | realistic.cpp:61:37:61:45 | userInput [bufferLen] |
|
||||
| realistic.cpp:61:37:61:45 | userInput [bufferLen] | realistic.cpp:61:47:61:55 | bufferLen |
|
||||
| simple.cpp:26:15:26:15 | f [a_] | simple.cpp:28:10:28:10 | f [a_] |
|
||||
| simple.cpp:26:15:26:15 | f [b_] | simple.cpp:29:10:29:10 | f [b_] |
|
||||
| simple.cpp:28:10:28:10 | f [a_] | simple.cpp:28:12:28:12 | call to a |
|
||||
@@ -332,6 +391,10 @@ edges
|
||||
| simple.cpp:83:9:83:28 | ... = ... | simple.cpp:83:9:83:10 | f2 [post update] [f1] |
|
||||
| simple.cpp:83:17:83:26 | call to user_input | simple.cpp:83:9:83:28 | ... = ... |
|
||||
| simple.cpp:84:14:84:20 | this [f2, f1] | simple.cpp:84:14:84:20 | call to getf2f1 |
|
||||
| simple.cpp:92:5:92:5 | a [post update] [i] | simple.cpp:94:10:94:11 | a2 [i] |
|
||||
| simple.cpp:92:5:92:22 | ... = ... | simple.cpp:92:5:92:5 | a [post update] [i] |
|
||||
| simple.cpp:92:11:92:20 | call to user_input | simple.cpp:92:5:92:22 | ... = ... |
|
||||
| simple.cpp:94:10:94:11 | a2 [i] | simple.cpp:94:13:94:13 | i |
|
||||
| struct_init.c:14:24:14:25 | ab [a] | struct_init.c:15:8:15:9 | ab [a] |
|
||||
| struct_init.c:15:8:15:9 | ab [a] | struct_init.c:15:12:15:12 | a |
|
||||
| struct_init.c:20:17:20:36 | {...} [a] | struct_init.c:22:8:22:9 | ab [a] |
|
||||
@@ -539,6 +602,46 @@ nodes
|
||||
| aliasing.cpp:93:8:93:8 | w [s, m1] | semmle.label | w [s, m1] |
|
||||
| aliasing.cpp:93:10:93:10 | s [m1] | semmle.label | s [m1] |
|
||||
| aliasing.cpp:93:12:93:13 | m1 | semmle.label | m1 |
|
||||
| arrays.cpp:6:12:6:21 | call to user_input | semmle.label | call to user_input |
|
||||
| arrays.cpp:7:8:7:13 | access to array | semmle.label | access to array |
|
||||
| arrays.cpp:8:8:8:13 | access to array | semmle.label | access to array |
|
||||
| arrays.cpp:9:8:9:11 | * ... | semmle.label | * ... |
|
||||
| arrays.cpp:10:8:10:15 | * ... | semmle.label | * ... |
|
||||
| arrays.cpp:15:14:15:23 | call to user_input | semmle.label | call to user_input |
|
||||
| arrays.cpp:16:8:16:13 | access to array | semmle.label | access to array |
|
||||
| arrays.cpp:17:8:17:13 | access to array | semmle.label | access to array |
|
||||
| arrays.cpp:36:3:36:3 | o [post update] [nested, arr, ... (3)] | semmle.label | o [post update] [nested, arr, ... (3)] |
|
||||
| arrays.cpp:36:3:36:17 | access to array [post update] [data] | semmle.label | access to array [post update] [data] |
|
||||
| arrays.cpp:36:3:36:37 | ... = ... | semmle.label | ... = ... |
|
||||
| arrays.cpp:36:5:36:10 | nested [post update] [arr, data] | semmle.label | nested [post update] [arr, data] |
|
||||
| arrays.cpp:36:12:36:14 | arr [inner post update] [data] | semmle.label | arr [inner post update] [data] |
|
||||
| arrays.cpp:36:26:36:35 | call to user_input | semmle.label | call to user_input |
|
||||
| arrays.cpp:37:8:37:8 | o [nested, arr, ... (3)] | semmle.label | o [nested, arr, ... (3)] |
|
||||
| arrays.cpp:37:8:37:22 | access to array [data] | semmle.label | access to array [data] |
|
||||
| arrays.cpp:37:10:37:15 | nested [arr, data] | semmle.label | nested [arr, data] |
|
||||
| arrays.cpp:37:17:37:19 | arr [data] | semmle.label | arr [data] |
|
||||
| arrays.cpp:37:24:37:27 | data | semmle.label | data |
|
||||
| arrays.cpp:38:8:38:8 | o [nested, arr, ... (3)] | semmle.label | o [nested, arr, ... (3)] |
|
||||
| arrays.cpp:38:8:38:22 | access to array [data] | semmle.label | access to array [data] |
|
||||
| arrays.cpp:38:10:38:15 | nested [arr, data] | semmle.label | nested [arr, data] |
|
||||
| arrays.cpp:38:17:38:19 | arr [data] | semmle.label | arr [data] |
|
||||
| arrays.cpp:38:24:38:27 | data | semmle.label | data |
|
||||
| arrays.cpp:42:3:42:3 | o [post update] [indirect, arr, ... (3)] | semmle.label | o [post update] [indirect, arr, ... (3)] |
|
||||
| arrays.cpp:42:3:42:20 | access to array [post update] [data] | semmle.label | access to array [post update] [data] |
|
||||
| arrays.cpp:42:3:42:40 | ... = ... | semmle.label | ... = ... |
|
||||
| arrays.cpp:42:5:42:12 | indirect [post update] [arr, data] | semmle.label | indirect [post update] [arr, data] |
|
||||
| arrays.cpp:42:15:42:17 | arr [inner post update] [data] | semmle.label | arr [inner post update] [data] |
|
||||
| arrays.cpp:42:29:42:38 | call to user_input | semmle.label | call to user_input |
|
||||
| arrays.cpp:43:8:43:8 | o [indirect, arr, ... (3)] | semmle.label | o [indirect, arr, ... (3)] |
|
||||
| arrays.cpp:43:8:43:25 | access to array [data] | semmle.label | access to array [data] |
|
||||
| arrays.cpp:43:10:43:17 | indirect [arr, data] | semmle.label | indirect [arr, data] |
|
||||
| arrays.cpp:43:20:43:22 | arr [data] | semmle.label | arr [data] |
|
||||
| arrays.cpp:43:27:43:30 | data | semmle.label | data |
|
||||
| arrays.cpp:44:8:44:8 | o [indirect, arr, ... (3)] | semmle.label | o [indirect, arr, ... (3)] |
|
||||
| arrays.cpp:44:8:44:25 | access to array [data] | semmle.label | access to array [data] |
|
||||
| arrays.cpp:44:10:44:17 | indirect [arr, data] | semmle.label | indirect [arr, data] |
|
||||
| arrays.cpp:44:20:44:22 | arr [data] | semmle.label | arr [data] |
|
||||
| arrays.cpp:44:27:44:30 | data | semmle.label | data |
|
||||
| by_reference.cpp:50:3:50:3 | ref arg s [a] | semmle.label | ref arg s [a] |
|
||||
| by_reference.cpp:50:17:50:26 | call to user_input | semmle.label | call to user_input |
|
||||
| by_reference.cpp:51:8:51:8 | s [a] | semmle.label | s [a] |
|
||||
@@ -562,6 +665,8 @@ nodes
|
||||
| by_reference.cpp:88:3:88:7 | inner [post update] [a] | semmle.label | inner [post update] [a] |
|
||||
| by_reference.cpp:88:3:88:24 | ... = ... | semmle.label | ... = ... |
|
||||
| by_reference.cpp:88:13:88:22 | call to user_input | semmle.label | call to user_input |
|
||||
| by_reference.cpp:92:4:92:5 | pa [inner post update] | semmle.label | pa [inner post update] |
|
||||
| by_reference.cpp:92:9:92:18 | call to user_input | semmle.label | call to user_input |
|
||||
| by_reference.cpp:95:25:95:26 | pa | semmle.label | pa |
|
||||
| by_reference.cpp:96:8:96:17 | call to user_input | semmle.label | call to user_input |
|
||||
| by_reference.cpp:102:21:102:39 | ref arg & ... [a] | semmle.label | ref arg & ... [a] |
|
||||
@@ -569,23 +674,33 @@ nodes
|
||||
| by_reference.cpp:102:28:102:39 | inner_nested [inner post update] [a] | semmle.label | inner_nested [inner post update] [a] |
|
||||
| by_reference.cpp:103:21:103:25 | outer [post update] [inner_ptr, a] | semmle.label | outer [post update] [inner_ptr, a] |
|
||||
| by_reference.cpp:103:27:103:35 | ref arg inner_ptr [a] | semmle.label | ref arg inner_ptr [a] |
|
||||
| by_reference.cpp:104:15:104:22 | ref arg & ... | semmle.label | ref arg & ... |
|
||||
| by_reference.cpp:104:16:104:20 | outer [post update] [a] | semmle.label | outer [post update] [a] |
|
||||
| by_reference.cpp:104:22:104:22 | a [inner post update] | semmle.label | a [inner post update] |
|
||||
| by_reference.cpp:106:21:106:41 | ref arg & ... [a] | semmle.label | ref arg & ... [a] |
|
||||
| by_reference.cpp:106:22:106:27 | pouter [post update] [inner_nested, a] | semmle.label | pouter [post update] [inner_nested, a] |
|
||||
| by_reference.cpp:106:30:106:41 | inner_nested [inner post update] [a] | semmle.label | inner_nested [inner post update] [a] |
|
||||
| by_reference.cpp:107:21:107:26 | pouter [post update] [inner_ptr, a] | semmle.label | pouter [post update] [inner_ptr, a] |
|
||||
| by_reference.cpp:107:29:107:37 | ref arg inner_ptr [a] | semmle.label | ref arg inner_ptr [a] |
|
||||
| by_reference.cpp:108:15:108:24 | ref arg & ... | semmle.label | ref arg & ... |
|
||||
| by_reference.cpp:108:16:108:21 | pouter [post update] [a] | semmle.label | pouter [post update] [a] |
|
||||
| by_reference.cpp:108:24:108:24 | a [inner post update] | semmle.label | a [inner post update] |
|
||||
| by_reference.cpp:110:8:110:12 | outer [inner_nested, a] | semmle.label | outer [inner_nested, a] |
|
||||
| by_reference.cpp:110:14:110:25 | inner_nested [a] | semmle.label | inner_nested [a] |
|
||||
| by_reference.cpp:110:27:110:27 | a | semmle.label | a |
|
||||
| by_reference.cpp:111:8:111:12 | outer [inner_ptr, a] | semmle.label | outer [inner_ptr, a] |
|
||||
| by_reference.cpp:111:14:111:22 | inner_ptr [a] | semmle.label | inner_ptr [a] |
|
||||
| by_reference.cpp:111:25:111:25 | a | semmle.label | a |
|
||||
| by_reference.cpp:112:8:112:12 | outer [a] | semmle.label | outer [a] |
|
||||
| by_reference.cpp:112:14:112:14 | a | semmle.label | a |
|
||||
| by_reference.cpp:114:8:114:13 | pouter [inner_nested, a] | semmle.label | pouter [inner_nested, a] |
|
||||
| by_reference.cpp:114:16:114:27 | inner_nested [a] | semmle.label | inner_nested [a] |
|
||||
| by_reference.cpp:114:29:114:29 | a | semmle.label | a |
|
||||
| by_reference.cpp:115:8:115:13 | pouter [inner_ptr, a] | semmle.label | pouter [inner_ptr, a] |
|
||||
| by_reference.cpp:115:16:115:24 | inner_ptr [a] | semmle.label | inner_ptr [a] |
|
||||
| by_reference.cpp:115:27:115:27 | a | semmle.label | a |
|
||||
| by_reference.cpp:116:8:116:13 | pouter [a] | semmle.label | pouter [a] |
|
||||
| by_reference.cpp:116:16:116:16 | a | semmle.label | a |
|
||||
| by_reference.cpp:122:21:122:25 | outer [post update] [inner_nested, a] | semmle.label | outer [post update] [inner_nested, a] |
|
||||
| by_reference.cpp:122:27:122:38 | ref arg inner_nested [a] | semmle.label | ref arg inner_nested [a] |
|
||||
| by_reference.cpp:123:21:123:36 | ref arg * ... [a] | semmle.label | ref arg * ... [a] |
|
||||
@@ -703,6 +818,19 @@ nodes
|
||||
| qualifiers.cpp:48:10:48:14 | outer [inner, a] | semmle.label | outer [inner, a] |
|
||||
| qualifiers.cpp:48:16:48:20 | inner [a] | semmle.label | inner [a] |
|
||||
| qualifiers.cpp:48:23:48:23 | a | semmle.label | a |
|
||||
| realistic.cpp:53:9:53:11 | foo [post update] [bar, baz, ... (4)] | semmle.label | foo [post update] [bar, baz, ... (4)] |
|
||||
| realistic.cpp:53:9:53:18 | access to array [post update] [baz, userInput, ... (3)] | semmle.label | access to array [post update] [baz, userInput, ... (3)] |
|
||||
| realistic.cpp:53:9:53:66 | ... = ... | semmle.label | ... = ... |
|
||||
| realistic.cpp:53:13:53:15 | bar [inner post update] [baz, userInput, ... (3)] | semmle.label | bar [inner post update] [baz, userInput, ... (3)] |
|
||||
| realistic.cpp:53:20:53:22 | baz [post update] [userInput, bufferLen] | semmle.label | baz [post update] [userInput, bufferLen] |
|
||||
| realistic.cpp:53:25:53:33 | userInput [post update] [bufferLen] | semmle.label | userInput [post update] [bufferLen] |
|
||||
| realistic.cpp:53:55:53:64 | call to user_input | semmle.label | call to user_input |
|
||||
| realistic.cpp:61:21:61:23 | foo [bar, baz, ... (4)] | semmle.label | foo [bar, baz, ... (4)] |
|
||||
| realistic.cpp:61:21:61:30 | access to array [baz, userInput, ... (3)] | semmle.label | access to array [baz, userInput, ... (3)] |
|
||||
| realistic.cpp:61:25:61:27 | bar [baz, userInput, ... (3)] | semmle.label | bar [baz, userInput, ... (3)] |
|
||||
| realistic.cpp:61:32:61:34 | baz [userInput, bufferLen] | semmle.label | baz [userInput, bufferLen] |
|
||||
| realistic.cpp:61:37:61:45 | userInput [bufferLen] | semmle.label | userInput [bufferLen] |
|
||||
| realistic.cpp:61:47:61:55 | bufferLen | semmle.label | bufferLen |
|
||||
| simple.cpp:26:15:26:15 | f [a_] | semmle.label | f [a_] |
|
||||
| simple.cpp:26:15:26:15 | f [b_] | semmle.label | f [b_] |
|
||||
| simple.cpp:28:10:28:10 | f [a_] | semmle.label | f [a_] |
|
||||
@@ -732,6 +860,11 @@ nodes
|
||||
| simple.cpp:83:17:83:26 | call to user_input | semmle.label | call to user_input |
|
||||
| simple.cpp:84:14:84:20 | call to getf2f1 | semmle.label | call to getf2f1 |
|
||||
| simple.cpp:84:14:84:20 | this [f2, f1] | semmle.label | this [f2, f1] |
|
||||
| simple.cpp:92:5:92:5 | a [post update] [i] | semmle.label | a [post update] [i] |
|
||||
| simple.cpp:92:5:92:22 | ... = ... | semmle.label | ... = ... |
|
||||
| simple.cpp:92:11:92:20 | call to user_input | semmle.label | call to user_input |
|
||||
| simple.cpp:94:10:94:11 | a2 [i] | semmle.label | a2 [i] |
|
||||
| simple.cpp:94:13:94:13 | i | semmle.label | i |
|
||||
| struct_init.c:14:24:14:25 | ab [a] | semmle.label | ab [a] |
|
||||
| struct_init.c:15:8:15:9 | ab [a] | semmle.label | ab [a] |
|
||||
| struct_init.c:15:12:15:12 | a | semmle.label | a |
|
||||
@@ -792,14 +925,26 @@ nodes
|
||||
| aliasing.cpp:30:11:30:12 | m1 | aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:30:11:30:12 | m1 | m1 flows from $@ | aliasing.cpp:13:10:13:19 | call to user_input | call to user_input |
|
||||
| aliasing.cpp:62:14:62:15 | m1 | aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:62:14:62:15 | m1 | m1 flows from $@ | aliasing.cpp:60:11:60:20 | call to user_input | call to user_input |
|
||||
| aliasing.cpp:93:12:93:13 | m1 | aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:93:12:93:13 | m1 | m1 flows from $@ | aliasing.cpp:92:12:92:21 | call to user_input | call to user_input |
|
||||
| arrays.cpp:7:8:7:13 | access to array | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:7:8:7:13 | access to array | access to array flows from $@ | arrays.cpp:6:12:6:21 | call to user_input | call to user_input |
|
||||
| arrays.cpp:8:8:8:13 | access to array | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:8:8:8:13 | access to array | access to array flows from $@ | arrays.cpp:6:12:6:21 | call to user_input | call to user_input |
|
||||
| arrays.cpp:9:8:9:11 | * ... | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:9:8:9:11 | * ... | * ... flows from $@ | arrays.cpp:6:12:6:21 | call to user_input | call to user_input |
|
||||
| arrays.cpp:10:8:10:15 | * ... | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:10:8:10:15 | * ... | * ... flows from $@ | arrays.cpp:6:12:6:21 | call to user_input | call to user_input |
|
||||
| arrays.cpp:16:8:16:13 | access to array | arrays.cpp:15:14:15:23 | call to user_input | arrays.cpp:16:8:16:13 | access to array | access to array flows from $@ | arrays.cpp:15:14:15:23 | call to user_input | call to user_input |
|
||||
| arrays.cpp:17:8:17:13 | access to array | arrays.cpp:15:14:15:23 | call to user_input | arrays.cpp:17:8:17:13 | access to array | access to array flows from $@ | arrays.cpp:15:14:15:23 | call to user_input | call to user_input |
|
||||
| arrays.cpp:37:24:37:27 | data | arrays.cpp:36:26:36:35 | call to user_input | arrays.cpp:37:24:37:27 | data | data flows from $@ | arrays.cpp:36:26:36:35 | call to user_input | call to user_input |
|
||||
| arrays.cpp:38:24:38:27 | data | arrays.cpp:36:26:36:35 | call to user_input | arrays.cpp:38:24:38:27 | data | data flows from $@ | arrays.cpp:36:26:36:35 | call to user_input | call to user_input |
|
||||
| arrays.cpp:43:27:43:30 | data | arrays.cpp:42:29:42:38 | call to user_input | arrays.cpp:43:27:43:30 | data | data flows from $@ | arrays.cpp:42:29:42:38 | call to user_input | call to user_input |
|
||||
| arrays.cpp:44:27:44:30 | data | arrays.cpp:42:29:42:38 | call to user_input | arrays.cpp:44:27:44:30 | data | data flows from $@ | arrays.cpp:42:29:42:38 | call to user_input | call to user_input |
|
||||
| by_reference.cpp:51:10:51:20 | call to getDirectly | by_reference.cpp:50:17:50:26 | call to user_input | by_reference.cpp:51:10:51:20 | call to getDirectly | call to getDirectly flows from $@ | by_reference.cpp:50:17:50:26 | call to user_input | call to user_input |
|
||||
| by_reference.cpp:57:10:57:22 | call to getIndirectly | by_reference.cpp:56:19:56:28 | call to user_input | by_reference.cpp:57:10:57:22 | call to getIndirectly | call to getIndirectly flows from $@ | by_reference.cpp:56:19:56:28 | call to user_input | call to user_input |
|
||||
| by_reference.cpp:63:10:63:28 | call to getThroughNonMember | by_reference.cpp:62:25:62:34 | call to user_input | by_reference.cpp:63:10:63:28 | call to getThroughNonMember | call to getThroughNonMember flows from $@ | by_reference.cpp:62:25:62:34 | call to user_input | call to user_input |
|
||||
| by_reference.cpp:69:8:69:20 | call to nonMemberGetA | by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:69:8:69:20 | call to nonMemberGetA | call to nonMemberGetA flows from $@ | by_reference.cpp:68:21:68:30 | call to user_input | call to user_input |
|
||||
| by_reference.cpp:110:27:110:27 | a | by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:110:27:110:27 | a | a flows from $@ | by_reference.cpp:84:14:84:23 | call to user_input | call to user_input |
|
||||
| by_reference.cpp:111:25:111:25 | a | by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:111:25:111:25 | a | a flows from $@ | by_reference.cpp:84:14:84:23 | call to user_input | call to user_input |
|
||||
| by_reference.cpp:112:14:112:14 | a | by_reference.cpp:92:9:92:18 | call to user_input | by_reference.cpp:112:14:112:14 | a | a flows from $@ | by_reference.cpp:92:9:92:18 | call to user_input | call to user_input |
|
||||
| by_reference.cpp:114:29:114:29 | a | by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:114:29:114:29 | a | a flows from $@ | by_reference.cpp:84:14:84:23 | call to user_input | call to user_input |
|
||||
| by_reference.cpp:115:27:115:27 | a | by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:115:27:115:27 | a | a flows from $@ | by_reference.cpp:84:14:84:23 | call to user_input | call to user_input |
|
||||
| by_reference.cpp:116:16:116:16 | a | by_reference.cpp:92:9:92:18 | call to user_input | by_reference.cpp:116:16:116:16 | a | a flows from $@ | by_reference.cpp:92:9:92:18 | call to user_input | call to user_input |
|
||||
| by_reference.cpp:130:27:130:27 | a | by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:130:27:130:27 | a | a flows from $@ | by_reference.cpp:88:13:88:22 | call to user_input | call to user_input |
|
||||
| by_reference.cpp:131:25:131:25 | a | by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:131:25:131:25 | a | a flows from $@ | by_reference.cpp:88:13:88:22 | call to user_input | call to user_input |
|
||||
| by_reference.cpp:132:14:132:14 | a | by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:132:14:132:14 | a | a flows from $@ | by_reference.cpp:96:8:96:17 | call to user_input | call to user_input |
|
||||
@@ -824,12 +969,14 @@ nodes
|
||||
| qualifiers.cpp:38:23:38:23 | a | qualifiers.cpp:37:38:37:47 | call to user_input | qualifiers.cpp:38:23:38:23 | a | a flows from $@ | qualifiers.cpp:37:38:37:47 | call to user_input | call to user_input |
|
||||
| qualifiers.cpp:43:23:43:23 | a | qualifiers.cpp:42:29:42:38 | call to user_input | qualifiers.cpp:43:23:43:23 | a | a flows from $@ | qualifiers.cpp:42:29:42:38 | call to user_input | call to user_input |
|
||||
| qualifiers.cpp:48:23:48:23 | a | qualifiers.cpp:47:31:47:40 | call to user_input | qualifiers.cpp:48:23:48:23 | a | a flows from $@ | qualifiers.cpp:47:31:47:40 | call to user_input | call to user_input |
|
||||
| realistic.cpp:61:47:61:55 | bufferLen | realistic.cpp:53:55:53:64 | call to user_input | realistic.cpp:61:47:61:55 | bufferLen | bufferLen flows from $@ | realistic.cpp:53:55:53:64 | call to user_input | call to user_input |
|
||||
| simple.cpp:28:12:28:12 | call to a | simple.cpp:39:12:39:21 | call to user_input | simple.cpp:28:12:28:12 | call to a | call to a flows from $@ | simple.cpp:39:12:39:21 | call to user_input | call to user_input |
|
||||
| simple.cpp:28:12:28:12 | call to a | simple.cpp:41:12:41:21 | call to user_input | simple.cpp:28:12:28:12 | call to a | call to a flows from $@ | simple.cpp:41:12:41:21 | call to user_input | call to user_input |
|
||||
| simple.cpp:29:12:29:12 | call to b | simple.cpp:40:12:40:21 | call to user_input | simple.cpp:29:12:29:12 | call to b | call to b flows from $@ | simple.cpp:40:12:40:21 | call to user_input | call to user_input |
|
||||
| simple.cpp:29:12:29:12 | call to b | simple.cpp:42:12:42:21 | call to user_input | simple.cpp:29:12:29:12 | call to b | call to b flows from $@ | simple.cpp:42:12:42:21 | call to user_input | call to user_input |
|
||||
| simple.cpp:67:13:67:13 | i | simple.cpp:65:11:65:20 | call to user_input | simple.cpp:67:13:67:13 | i | i flows from $@ | simple.cpp:65:11:65:20 | call to user_input | call to user_input |
|
||||
| simple.cpp:84:14:84:20 | call to getf2f1 | simple.cpp:83:17:83:26 | call to user_input | simple.cpp:84:14:84:20 | call to getf2f1 | call to getf2f1 flows from $@ | simple.cpp:83:17:83:26 | call to user_input | call to user_input |
|
||||
| simple.cpp:94:13:94:13 | i | simple.cpp:92:11:92:20 | call to user_input | simple.cpp:94:13:94:13 | i | i flows from $@ | simple.cpp:92:11:92:20 | call to user_input | call to user_input |
|
||||
| struct_init.c:15:12:15:12 | a | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input | call to user_input |
|
||||
| struct_init.c:15:12:15:12 | a | struct_init.c:27:7:27:16 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:27:7:27:16 | call to user_input | call to user_input |
|
||||
| struct_init.c:15:12:15:12 | a | struct_init.c:40:20:40:29 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:40:20:40:29 | call to user_input | call to user_input |
|
||||
|
||||
70
cpp/ql/test/library-tests/dataflow/fields/realistic.cpp
Normal file
70
cpp/ql/test/library-tests/dataflow/fields/realistic.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned long size_t;
|
||||
struct UserInput {
|
||||
size_t bufferLen;
|
||||
u8 buffer[256];
|
||||
};
|
||||
struct Baz {
|
||||
int foo;
|
||||
struct UserInput userInput;
|
||||
};
|
||||
struct Bar {
|
||||
u8* foo;
|
||||
struct Baz * baz;
|
||||
};
|
||||
struct Foo {
|
||||
struct Bar bar[128];
|
||||
};
|
||||
void printf(const char *fmt, ...) {
|
||||
return;
|
||||
}
|
||||
void * malloc(size_t size) {
|
||||
static unsigned char buffer[0x1000];
|
||||
static unsigned int offset;
|
||||
if (size + offset >= sizeof(buffer)) return nullptr;
|
||||
void* m = (void*)&buffer[offset];
|
||||
offset += size;
|
||||
return m;
|
||||
}
|
||||
void * memcpy ( void * destination, const void * source, size_t num ) {
|
||||
u8* d = (u8*)destination;
|
||||
u8* s = (u8*)source;
|
||||
u8* e = d + num;
|
||||
while(d != e) {
|
||||
*d++ = *s++;
|
||||
}
|
||||
return destination;
|
||||
}
|
||||
void *user_input(void) {
|
||||
return (void*)"\x0a\x00\x00\x00\x00\x00\x00\x00The quick brown fox jumps over the lazy dog";
|
||||
}
|
||||
void sink(void *o) {
|
||||
printf("%p\n", o);
|
||||
}
|
||||
#define MAX_BAZ 3
|
||||
int main(int argc, char** argv) {
|
||||
char dst[256];
|
||||
struct Foo foo;
|
||||
for (int i = 0; i < MAX_BAZ; i++) {
|
||||
foo.bar[i].baz = (struct Baz*)malloc(sizeof(struct Baz));
|
||||
}
|
||||
int i = 0;
|
||||
while(i < MAX_BAZ) {
|
||||
foo.bar[i].baz->userInput.bufferLen = (size_t)user_input();
|
||||
memcpy(foo.bar[i].baz->userInput.buffer, user_input(), sizeof(foo.bar[i].baz->userInput.buffer));
|
||||
if(foo.bar[i].baz->userInput.bufferLen > sizeof(foo.bar[i].baz->userInput.buffer))
|
||||
{
|
||||
printf("The user-supplied input 0x%lx is larger than the buffer 0x%lx!\n", foo.bar[i].baz->userInput.bufferLen, sizeof(foo.bar[i].baz->userInput.buffer));
|
||||
return -1;
|
||||
}
|
||||
memcpy(dst, foo.bar[i].baz->userInput.buffer, foo.bar[i].baz->userInput.bufferLen);
|
||||
sink((void*)foo.bar[i].baz->userInput.bufferLen); // $ast $f-:ir
|
||||
// There is no flow to the following two `sink` calls because the
|
||||
// source is the _pointer_ returned by `user_input` rather than the
|
||||
// _data_ to which it points.
|
||||
sink((void*)foo.bar[i].baz->userInput.buffer); // $f-:ast,ir
|
||||
sink((void*)dst); // $f-:ast,ir
|
||||
i++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -85,4 +85,13 @@ struct C2
|
||||
}
|
||||
};
|
||||
|
||||
typedef A A_typedef;
|
||||
|
||||
void single_field_test_typedef(A_typedef a)
|
||||
{
|
||||
a.i = user_input();
|
||||
A_typedef a2 = a;
|
||||
sink(a2.i); //$ast,ir
|
||||
}
|
||||
|
||||
} // namespace Simple
|
||||
|
||||
@@ -14,7 +14,7 @@ void test_pointer_deref_assignment()
|
||||
*p_x = source();
|
||||
|
||||
sink(x); // tainted [DETECTED BY IR ONLY]
|
||||
sink(*p_x); // tainted [DETECTED BY IR ONLY]
|
||||
sink(*p_x); // tainted
|
||||
sink(*p2_x); // tainted [DETECTED BY IR ONLY]
|
||||
sink(r_x); // tainted [DETECTED BY IR ONLY]
|
||||
}
|
||||
@@ -137,11 +137,11 @@ void test_array_reference_assignment()
|
||||
|
||||
ptr2 = &(arr2[5]);
|
||||
*ptr2 = source();
|
||||
sink(*ptr2); // tainted [DETECTED BY IR ONLY]
|
||||
sink(*ptr2); // tainted
|
||||
sink(arr2[5]); // tainted [DETECTED BY IR ONLY]
|
||||
|
||||
ptr3 = arr3;
|
||||
ptr3[5] = source();
|
||||
sink(ptr3[5]); // tainted [DETECTED BY IR ONLY]
|
||||
sink(ptr3[5]); // tainted
|
||||
sink(arr3[5]); // tainted [DETECTED BY IR ONLY]
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,68 @@
|
||||
#include "stl.h"
|
||||
|
||||
int source();
|
||||
void sink(int);
|
||||
void sink(int*);
|
||||
|
||||
template<typename T> void sink(std::shared_ptr<T>&);
|
||||
template<typename T> void sink(std::unique_ptr<T>&);
|
||||
|
||||
void test_make_shared() {
|
||||
std::shared_ptr<int> p = std::make_shared<int>(source());
|
||||
sink(*p); // tainted
|
||||
sink(p); // tainted
|
||||
}
|
||||
|
||||
void test_make_shared_array() {
|
||||
std::shared_ptr<int[]> p = std::make_shared<int[]>(source());
|
||||
sink(*p); // not tainted
|
||||
sink(p); // not tainted
|
||||
}
|
||||
|
||||
void test_make_unique() {
|
||||
std::unique_ptr<int> p = std::make_unique<int>(source());
|
||||
sink(*p); // tainted
|
||||
sink(p); // tainted
|
||||
}
|
||||
|
||||
void test_make_unique_array() {
|
||||
std::unique_ptr<int[]> p = std::make_unique<int[]>(source());
|
||||
sink(*p); // not tainted
|
||||
sink(p); // not tainted
|
||||
}
|
||||
|
||||
void test_reverse_taint_shared() {
|
||||
std::shared_ptr<int> p = std::make_shared<int>();
|
||||
|
||||
*p = source();
|
||||
sink(p); // tainted [NOT DETECTED]
|
||||
sink(*p); // tainted [NOT DETECTED]
|
||||
}
|
||||
|
||||
void test_reverse_taint_unique() {
|
||||
std::unique_ptr<int> p = std::unique_ptr<int>();
|
||||
|
||||
*p = source();
|
||||
sink(p); // tainted [NOT DETECTED]
|
||||
sink(*p); // tainted [NOT DETECTED]
|
||||
}
|
||||
|
||||
void test_shared_get() {
|
||||
std::shared_ptr<int> p = std::make_shared<int>(source());
|
||||
sink(p.get()); // tainted
|
||||
}
|
||||
|
||||
void test_unique_get() {
|
||||
std::unique_ptr<int> p = std::make_unique<int>(source());
|
||||
sink(p.get()); // tainted
|
||||
}
|
||||
|
||||
struct A {
|
||||
int x, y;
|
||||
};
|
||||
|
||||
void test_shared_field_member() {
|
||||
std::unique_ptr<A> p = std::make_unique<A>(source(), 0);
|
||||
sink(p->x); // tainted [NOT DETECTED]
|
||||
sink(p->y); // not tainted
|
||||
}
|
||||
@@ -132,16 +132,33 @@ namespace std
|
||||
template <class charT, class traits = char_traits<charT> >
|
||||
class basic_istream /*: virtual public basic_ios<charT,traits> - not needed for this test */ {
|
||||
public:
|
||||
basic_istream<charT,traits>& operator>>(int& n);
|
||||
using char_type = charT;
|
||||
using int_type = int; //typename traits::int_type;
|
||||
|
||||
basic_istream<charT, traits>& operator>>(int& n);
|
||||
|
||||
int_type get();
|
||||
basic_istream<charT, traits>& get(char_type& c);
|
||||
basic_istream<charT, traits>& get(char_type* s, streamsize n);
|
||||
int_type peek();
|
||||
basic_istream<charT, traits>& read (char_type* s, streamsize n);
|
||||
streamsize readsome(char_type* s, streamsize n);
|
||||
basic_istream<charT, traits>& putback(char_type c);
|
||||
|
||||
};
|
||||
|
||||
template<class charT, class traits> basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>&, charT*);
|
||||
template<class charT, class traits, class Allocator> basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str);
|
||||
|
||||
template <class charT, class traits = char_traits<charT> >
|
||||
class basic_ostream /*: virtual public basic_ios<charT,traits> - not needed for this test */ {
|
||||
public:
|
||||
typedef charT char_type;
|
||||
basic_ostream<charT,traits>& write(const char_type* s, streamsize n);
|
||||
|
||||
basic_ostream<charT, traits>& operator<<(int n);
|
||||
|
||||
basic_ostream<charT, traits>& put(char_type c);
|
||||
basic_ostream<charT, traits>& write(const char_type* s, streamsize n);
|
||||
};
|
||||
|
||||
template<class charT, class traits> basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&, const charT*);
|
||||
@@ -156,8 +173,16 @@ namespace std
|
||||
class basic_stringstream : public basic_iostream<charT, traits> {
|
||||
public:
|
||||
explicit basic_stringstream(/*ios_base::openmode which = ios_base::out|ios_base::in - not needed for this test*/);
|
||||
explicit basic_stringstream( const basic_string<charT, traits, Allocator>& str/*, ios_base::openmode which = ios_base::out | ios_base::in*/);
|
||||
basic_stringstream(const basic_stringstream& rhs) = delete;
|
||||
basic_stringstream(basic_stringstream&& rhs);
|
||||
basic_stringstream& operator=(const basic_stringstream& rhs) = delete;
|
||||
basic_stringstream& operator=(basic_stringstream&& rhs);
|
||||
|
||||
void swap(basic_stringstream& rhs);
|
||||
|
||||
basic_string<charT, traits, Allocator> str() const;
|
||||
void str(const basic_string<charT, traits, Allocator>& str);
|
||||
};
|
||||
|
||||
using stringstream = basic_stringstream<char>;
|
||||
@@ -224,3 +249,43 @@ namespace std {
|
||||
void clear() noexcept;
|
||||
};
|
||||
}
|
||||
|
||||
// --- make_shared / make_unique ---
|
||||
|
||||
namespace std {
|
||||
template<typename T>
|
||||
class shared_ptr {
|
||||
public:
|
||||
shared_ptr() noexcept;
|
||||
explicit shared_ptr(T*);
|
||||
template<class U> shared_ptr(const shared_ptr<U>&) noexcept;
|
||||
template<class U> shared_ptr(shared_ptr<U>&&) noexcept;
|
||||
|
||||
shared_ptr<T>& operator=(const shared_ptr<T>&) noexcept;
|
||||
shared_ptr<T>& operator=(shared_ptr<T>&&) noexcept;
|
||||
|
||||
T& operator*() const noexcept;
|
||||
T* operator->() const noexcept;
|
||||
|
||||
T* get() const noexcept;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class unique_ptr {
|
||||
public:
|
||||
constexpr unique_ptr() noexcept;
|
||||
explicit unique_ptr(T*) noexcept;
|
||||
unique_ptr(unique_ptr<T>&&) noexcept;
|
||||
|
||||
unique_ptr<T>& operator=(unique_ptr<T>&&) noexcept;
|
||||
|
||||
T& operator*() const;
|
||||
T* operator->() const noexcept;
|
||||
|
||||
T* get() const noexcept;
|
||||
};
|
||||
|
||||
template<typename T, class... Args> unique_ptr<T> make_unique(Args&&...);
|
||||
|
||||
template<typename T, class... Args> shared_ptr<T> make_shared(Args&&...);
|
||||
}
|
||||
@@ -5,41 +5,194 @@ using namespace std;
|
||||
|
||||
char *source();
|
||||
|
||||
void sink(const std::string &s) {};
|
||||
void sink(const std::stringstream &s) {};
|
||||
|
||||
void test_stringstream()
|
||||
namespace ns_char
|
||||
{
|
||||
std::stringstream ss1, ss2, ss3, ss4, ss5;
|
||||
char source();
|
||||
}
|
||||
|
||||
void sink(int i) {};
|
||||
|
||||
void sink(const std::string &s) {};
|
||||
|
||||
template<class charT>
|
||||
void sink(const std::basic_ostream<charT> &s) {};
|
||||
|
||||
template<class charT>
|
||||
void sink(const std::basic_istream<charT> &s) {};
|
||||
|
||||
template<class charT>
|
||||
void sink(const std::basic_iostream<charT> &s) {};
|
||||
|
||||
void test_stringstream_string(int amount)
|
||||
{
|
||||
std::stringstream ss1, ss2, ss3, ss4, ss5, ss6, ss7, ss8, ss9, ss10, ss11, ss12, ss13;
|
||||
std::string t(source());
|
||||
|
||||
ss1 << "1234";
|
||||
ss2 << source();
|
||||
ss3 << "123" << source();
|
||||
ss4 << source() << "456";
|
||||
ss5 << t;
|
||||
sink(ss1 << "1234");
|
||||
sink(ss2 << source()); // tainted
|
||||
sink(ss3 << "123" << source()); // tainted
|
||||
sink(ss4 << source() << "456"); // tainted
|
||||
sink(ss5 << t); // tainted
|
||||
|
||||
sink(ss1);
|
||||
sink(ss2); // tainted [NOT DETECTED]
|
||||
sink(ss3); // tainted [NOT DETECTED]
|
||||
sink(ss4); // tainted [NOT DETECTED]
|
||||
sink(ss5); // tainted [NOT DETECTED]
|
||||
sink(ss2); // tainted
|
||||
sink(ss3); // tainted
|
||||
sink(ss4); // tainted
|
||||
sink(ss5); // tainted
|
||||
sink(ss1.str());
|
||||
sink(ss2.str()); // tainted [NOT DETECTED]
|
||||
sink(ss3.str()); // tainted [NOT DETECTED]
|
||||
sink(ss4.str()); // tainted [NOT DETECTED]
|
||||
sink(ss5.str()); // tainted [NOT DETECTED]
|
||||
sink(ss2.str()); // tainted
|
||||
sink(ss3.str()); // tainted
|
||||
sink(ss4.str()); // tainted
|
||||
sink(ss5.str()); // tainted
|
||||
|
||||
ss6.str("abc");
|
||||
ss6.str(source()); // (overwrites)
|
||||
ss7.str(source());
|
||||
ss7.str("abc"); // (overwrites)
|
||||
sink(ss6); // tainted
|
||||
sink(ss7); // [FALSE POSITIVE]
|
||||
|
||||
sink(ss8.put('a'));
|
||||
sink(ss9.put(ns_char::source())); // tainted
|
||||
sink(ss10.put('a').put(ns_char::source()).put('z')); // tainted
|
||||
sink(ss8);
|
||||
sink(ss9); // tainted
|
||||
sink(ss10); // tainted
|
||||
|
||||
sink(ss11.write("begin", 5));
|
||||
sink(ss12.write(source(), 5)); // tainted
|
||||
sink(ss13.write("begin", 5).write(source(), amount).write("end", 3)); // tainted
|
||||
sink(ss11);
|
||||
sink(ss12); // tainted
|
||||
sink(ss13); // tainted
|
||||
}
|
||||
|
||||
void test_stringstream_int(int source)
|
||||
{
|
||||
std::stringstream ss1, ss2;
|
||||
int v1 = 0, v2 = 0;
|
||||
|
||||
ss1 << 1234;
|
||||
ss2 << source;
|
||||
sink(ss1 << 1234);
|
||||
sink(ss2 << source); // tainted
|
||||
sink(ss1 >> v1);
|
||||
sink(ss2 >> v2); // tainted [NOT DETECTED]
|
||||
|
||||
sink(ss1);
|
||||
sink(ss2); // tainted [NOT DETECTED]
|
||||
sink(ss2); // tainted
|
||||
sink(ss1.str());
|
||||
sink(ss2.str()); // tainted [NOT DETECTED]
|
||||
sink(ss2.str()); // tainted
|
||||
sink(v1);
|
||||
sink(v2); // tainted [NOT DETECTED]
|
||||
}
|
||||
|
||||
void test_stringstream_constructors()
|
||||
{
|
||||
std::string s1 = "abc";
|
||||
std::string s2 = source();
|
||||
std::stringstream ss1(s1);
|
||||
std::stringstream ss2(s2);
|
||||
std::stringstream ss3 = std::stringstream("abc");
|
||||
std::stringstream ss4 = std::stringstream(source());
|
||||
std::stringstream ss5;
|
||||
std::stringstream ss6;
|
||||
|
||||
sink(ss5 = std::stringstream("abc"));
|
||||
sink(ss6 = std::stringstream(source())); // tainted
|
||||
|
||||
sink(ss1);
|
||||
sink(ss2); // tainted
|
||||
sink(ss3);
|
||||
sink(ss4); // tainted
|
||||
sink(ss5);
|
||||
sink(ss6); // tainted
|
||||
}
|
||||
|
||||
void test_stringstream_swap()
|
||||
{
|
||||
std::stringstream ss1("abc");
|
||||
std::stringstream ss2(source());
|
||||
std::stringstream ss3("abc");
|
||||
std::stringstream ss4(source());
|
||||
|
||||
ss1.swap(ss2);
|
||||
ss4.swap(ss3);
|
||||
|
||||
sink(ss1); // tainted [NOT DETECTED]
|
||||
sink(ss2); // [FALSE POSITIVE]
|
||||
sink(ss3); // tainted [NOT DETECTED]
|
||||
sink(ss4); // [FALSE POSITIVE]
|
||||
}
|
||||
|
||||
void test_stringstream_in()
|
||||
{
|
||||
std::stringstream ss1, ss2;
|
||||
std::string s1, s2, s3, s4;
|
||||
char b1[100] = {0};
|
||||
char b2[100] = {0};
|
||||
char b3[100] = {0};
|
||||
char b4[100] = {0};
|
||||
char b5[100] = {0};
|
||||
char b6[100] = {0};
|
||||
char b7[100] = {0};
|
||||
char b8[100] = {0};
|
||||
char b9[100] = {0};
|
||||
char b10[100] = {0};
|
||||
char c1 = 0, c2 = 0, c3 = 0, c4 = 0, c5 = 0, c6 = 0;
|
||||
|
||||
sink(ss1 << "abc");
|
||||
sink(ss2 << source()); // tainted
|
||||
|
||||
sink(ss1 >> s1);
|
||||
sink(ss2 >> s2); // tainted [NOT DETECTED]
|
||||
sink(ss2 >> s3 >> s4); // tainted [NOT DETECTED]
|
||||
sink(s1);
|
||||
sink(s2); // tainted [NOT DETECTED]
|
||||
sink(s3); // tainted [NOT DETECTED]
|
||||
sink(s4); // tainted [NOT DETECTED]
|
||||
|
||||
sink(ss1 >> b1);
|
||||
sink(ss2 >> b2);
|
||||
sink(ss2 >> b3 >> b4);
|
||||
sink(b1);
|
||||
sink(b2); // tainted [NOT DETECTED]
|
||||
sink(b3); // tainted [NOT DETECTED]
|
||||
sink(b4); // tainted [NOT DETECTED]
|
||||
|
||||
sink(ss1.read(b5, 100));
|
||||
sink(ss2.read(b6, 100)); // tainted [NOT DETECTED]
|
||||
sink(ss1.readsome(b7, 100));
|
||||
sink(ss2.readsome(b8, 100)); // (returns a length, not significantly tainted)
|
||||
sink(ss1.get(b9, 100));
|
||||
sink(ss2.get(b10, 100));
|
||||
sink(b5);
|
||||
sink(b6); // tainted [NOT DETECTED]
|
||||
sink(b7);
|
||||
sink(b8); // tainted [NOT DETECTED]
|
||||
sink(b9);
|
||||
sink(b10); // tainted [NOT DETECTED]
|
||||
|
||||
sink(c1 = ss1.get());
|
||||
sink(c2 = ss2.get()); // tainted [NOT DETECTED]
|
||||
sink(c3 = ss1.peek());
|
||||
sink(c4 = ss2.peek()); // tainted [NOT DETECTED]
|
||||
sink(ss1.get(c5));
|
||||
sink(ss2.get(c6)); // tainted [NOT DETECTED]
|
||||
sink(c1);
|
||||
sink(c2); // tainted [NOT DETECTED]
|
||||
sink(c3);
|
||||
sink(c4); // tainted [NOT DETECTED]
|
||||
sink(c5);
|
||||
sink(c6); // tainted [NOT DETECTED]
|
||||
}
|
||||
|
||||
void test_stringstream_putback()
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
sink(ss.put('a'));
|
||||
sink(ss.get());
|
||||
sink(ss.putback('b'));
|
||||
sink(ss.get());
|
||||
sink(ss.putback(ns_char::source())); // tainted [NOT DETECTED]
|
||||
sink(ss.get()); // tainted [NOT DETECTED]
|
||||
}
|
||||
|
||||
@@ -107,9 +107,9 @@ void array_test(int i) {
|
||||
arr3[5] = 0;
|
||||
|
||||
sink(arr1[5]); // tainted
|
||||
sink(arr1[i]); // tainted [NOT DETECTED]
|
||||
sink(arr2[5]); // tainted [NOT DETECTED]
|
||||
sink(arr2[i]); // tainted [NOT DETECTED]
|
||||
sink(arr1[i]); // tainted
|
||||
sink(arr2[5]); // tainted
|
||||
sink(arr2[i]); // tainted
|
||||
sink(arr3[5]);
|
||||
sink(arr3[i]);
|
||||
}
|
||||
@@ -127,7 +127,7 @@ void pointer_test() {
|
||||
*p2 = source();
|
||||
|
||||
sink(*p1); // tainted
|
||||
sink(*p2); // tainted [NOT DETECTED]
|
||||
sink(*p2); // tainted
|
||||
sink(*p3);
|
||||
|
||||
p3 = &t1;
|
||||
@@ -258,7 +258,7 @@ void test_lambdas()
|
||||
c = source();
|
||||
};
|
||||
e(t, u, w);
|
||||
sink(w); // tainted
|
||||
sink(w); // tainted [NOT DETECTED]
|
||||
}
|
||||
|
||||
// --- taint through return value ---
|
||||
@@ -348,10 +348,10 @@ void test_outparams()
|
||||
myNotAssign(e, t);
|
||||
|
||||
sink(t); // tainted
|
||||
sink(a); // tainted
|
||||
sink(b); // tainted
|
||||
sink(c); // tainted [NOT DETECTED]
|
||||
sink(d); // tainted [NOT DETECTED]
|
||||
sink(a); // tainted [NOT DETECTED by IR]
|
||||
sink(b); // tainted [NOT DETECTED by IR]
|
||||
sink(c); // tainted [NOT DETECTED by IR]
|
||||
sink(d); // tainted [NOT DETECTED by IR]
|
||||
sink(e);
|
||||
}
|
||||
|
||||
@@ -468,7 +468,7 @@ void test_swop() {
|
||||
swop(x, y);
|
||||
|
||||
sink(x); // clean [FALSE POSITIVE]
|
||||
sink(y); // tainted
|
||||
sink(y); // tainted [NOT DETECTED by IR]
|
||||
}
|
||||
|
||||
// --- getdelim ---
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
| arrayassignment.cpp:17:7:17:10 | * ... | arrayassignment.cpp:14:9:14:14 | call to source |
|
||||
| arrayassignment.cpp:33:7:33:9 | r_x | arrayassignment.cpp:29:8:29:13 | call to source |
|
||||
| arrayassignment.cpp:57:10:57:12 | call to get | arrayassignment.cpp:54:9:54:14 | call to source |
|
||||
| arrayassignment.cpp:67:10:67:12 | call to get | arrayassignment.cpp:64:13:64:18 | call to source |
|
||||
| arrayassignment.cpp:101:7:101:18 | access to array | arrayassignment.cpp:99:17:99:22 | call to source |
|
||||
| arrayassignment.cpp:135:7:135:10 | ref1 | arrayassignment.cpp:134:9:134:14 | call to source |
|
||||
| arrayassignment.cpp:140:7:140:11 | * ... | arrayassignment.cpp:139:10:139:15 | call to source |
|
||||
| arrayassignment.cpp:145:7:145:13 | access to array | arrayassignment.cpp:144:12:144:17 | call to source |
|
||||
| copyableclass.cpp:40:8:40:9 | s1 | copyableclass.cpp:34:22:34:27 | call to source |
|
||||
| copyableclass.cpp:41:8:41:9 | s2 | copyableclass.cpp:35:24:35:29 | call to source |
|
||||
| copyableclass.cpp:42:8:42:9 | s3 | copyableclass.cpp:34:22:34:27 | call to source |
|
||||
@@ -37,6 +40,12 @@
|
||||
| movableclass.cpp:55:8:55:9 | s2 | movableclass.cpp:52:23:52:28 | call to source |
|
||||
| movableclass.cpp:64:8:64:9 | s2 | movableclass.cpp:23:55:23:60 | call to source |
|
||||
| movableclass.cpp:65:11:65:11 | call to operator= | movableclass.cpp:65:13:65:18 | call to source |
|
||||
| smart_pointer.cpp:12:10:12:10 | call to operator* | smart_pointer.cpp:11:52:11:57 | call to source |
|
||||
| smart_pointer.cpp:13:10:13:10 | p | smart_pointer.cpp:11:52:11:57 | call to source |
|
||||
| smart_pointer.cpp:24:10:24:10 | call to operator* | smart_pointer.cpp:23:52:23:57 | call to source |
|
||||
| smart_pointer.cpp:25:10:25:10 | p | smart_pointer.cpp:23:52:23:57 | call to source |
|
||||
| smart_pointer.cpp:52:12:52:14 | call to get | smart_pointer.cpp:51:52:51:57 | call to source |
|
||||
| smart_pointer.cpp:57:12:57:14 | call to get | smart_pointer.cpp:56:52:56:57 | call to source |
|
||||
| standalone_iterators.cpp:40:10:40:10 | call to operator* | standalone_iterators.cpp:39:45:39:51 | source1 |
|
||||
| standalone_iterators.cpp:41:10:41:10 | call to operator* | standalone_iterators.cpp:39:45:39:51 | source1 |
|
||||
| standalone_iterators.cpp:42:10:42:10 | call to operator* | standalone_iterators.cpp:39:45:39:51 | source1 |
|
||||
@@ -156,6 +165,38 @@
|
||||
| string.cpp:555:8:555:8 | d | string.cpp:549:27:549:32 | call to source |
|
||||
| string.cpp:556:8:556:8 | e | string.cpp:550:31:550:36 | call to source |
|
||||
| string.cpp:557:8:557:8 | f | string.cpp:551:18:551:23 | call to source |
|
||||
| stringstream.cpp:32:11:32:11 | call to operator<< | stringstream.cpp:32:14:32:19 | call to source |
|
||||
| stringstream.cpp:33:20:33:20 | call to operator<< | stringstream.cpp:33:23:33:28 | call to source |
|
||||
| stringstream.cpp:34:23:34:23 | call to operator<< | stringstream.cpp:34:14:34:19 | call to source |
|
||||
| stringstream.cpp:35:11:35:11 | call to operator<< | stringstream.cpp:29:16:29:21 | call to source |
|
||||
| stringstream.cpp:38:7:38:9 | ss2 | stringstream.cpp:32:14:32:19 | call to source |
|
||||
| stringstream.cpp:39:7:39:9 | ss3 | stringstream.cpp:33:23:33:28 | call to source |
|
||||
| stringstream.cpp:40:7:40:9 | ss4 | stringstream.cpp:34:14:34:19 | call to source |
|
||||
| stringstream.cpp:41:7:41:9 | ss5 | stringstream.cpp:29:16:29:21 | call to source |
|
||||
| stringstream.cpp:43:11:43:13 | call to str | stringstream.cpp:32:14:32:19 | call to source |
|
||||
| stringstream.cpp:44:11:44:13 | call to str | stringstream.cpp:33:23:33:28 | call to source |
|
||||
| stringstream.cpp:45:11:45:13 | call to str | stringstream.cpp:34:14:34:19 | call to source |
|
||||
| stringstream.cpp:46:11:46:13 | call to str | stringstream.cpp:29:16:29:21 | call to source |
|
||||
| stringstream.cpp:52:7:52:9 | ss6 | stringstream.cpp:49:10:49:15 | call to source |
|
||||
| stringstream.cpp:53:7:53:9 | ss7 | stringstream.cpp:50:10:50:15 | call to source |
|
||||
| stringstream.cpp:56:11:56:13 | call to put | stringstream.cpp:56:15:56:29 | call to source |
|
||||
| stringstream.cpp:57:44:57:46 | call to put | stringstream.cpp:57:25:57:39 | call to source |
|
||||
| stringstream.cpp:59:7:59:9 | ss9 | stringstream.cpp:56:15:56:29 | call to source |
|
||||
| stringstream.cpp:60:7:60:10 | ss10 | stringstream.cpp:57:25:57:39 | call to source |
|
||||
| stringstream.cpp:63:12:63:16 | call to write | stringstream.cpp:63:18:63:23 | call to source |
|
||||
| stringstream.cpp:64:54:64:58 | call to write | stringstream.cpp:64:36:64:41 | call to source |
|
||||
| stringstream.cpp:66:7:66:10 | ss12 | stringstream.cpp:63:18:63:23 | call to source |
|
||||
| stringstream.cpp:67:7:67:10 | ss13 | stringstream.cpp:64:36:64:41 | call to source |
|
||||
| stringstream.cpp:76:11:76:11 | call to operator<< | stringstream.cpp:70:32:70:37 | source |
|
||||
| stringstream.cpp:81:7:81:9 | ss2 | stringstream.cpp:70:32:70:37 | source |
|
||||
| stringstream.cpp:83:11:83:13 | call to str | stringstream.cpp:70:32:70:37 | source |
|
||||
| stringstream.cpp:100:11:100:11 | call to operator= | stringstream.cpp:100:31:100:36 | call to source |
|
||||
| stringstream.cpp:103:7:103:9 | ss2 | stringstream.cpp:91:19:91:24 | call to source |
|
||||
| stringstream.cpp:105:7:105:9 | ss4 | stringstream.cpp:95:44:95:49 | call to source |
|
||||
| stringstream.cpp:107:7:107:9 | ss6 | stringstream.cpp:100:31:100:36 | call to source |
|
||||
| stringstream.cpp:121:7:121:9 | ss2 | stringstream.cpp:113:24:113:29 | call to source |
|
||||
| stringstream.cpp:123:7:123:9 | ss4 | stringstream.cpp:115:24:115:29 | call to source |
|
||||
| stringstream.cpp:143:11:143:11 | call to operator<< | stringstream.cpp:143:14:143:19 | call to source |
|
||||
| structlikeclass.cpp:35:8:35:9 | s1 | structlikeclass.cpp:29:22:29:27 | call to source |
|
||||
| structlikeclass.cpp:36:8:36:9 | s2 | structlikeclass.cpp:30:24:30:29 | call to source |
|
||||
| structlikeclass.cpp:37:8:37:9 | s3 | structlikeclass.cpp:29:22:29:27 | call to source |
|
||||
@@ -219,7 +260,12 @@
|
||||
| taint.cpp:91:11:91:11 | d | taint.cpp:77:7:77:12 | call to source |
|
||||
| taint.cpp:93:11:93:11 | b | taint.cpp:71:22:71:27 | call to source |
|
||||
| taint.cpp:94:11:94:11 | c | taint.cpp:72:7:72:12 | call to source |
|
||||
| taint.cpp:109:7:109:13 | access to array | taint.cpp:105:12:105:17 | call to source |
|
||||
| taint.cpp:110:7:110:13 | access to array | taint.cpp:105:12:105:17 | call to source |
|
||||
| taint.cpp:111:7:111:13 | access to array | taint.cpp:106:12:106:17 | call to source |
|
||||
| taint.cpp:112:7:112:13 | access to array | taint.cpp:106:12:106:17 | call to source |
|
||||
| taint.cpp:129:7:129:9 | * ... | taint.cpp:120:11:120:16 | call to source |
|
||||
| taint.cpp:130:7:130:9 | * ... | taint.cpp:127:8:127:13 | call to source |
|
||||
| taint.cpp:134:7:134:9 | * ... | taint.cpp:120:11:120:16 | call to source |
|
||||
| taint.cpp:137:7:137:9 | * ... | taint.cpp:120:11:120:16 | call to source |
|
||||
| taint.cpp:151:7:151:12 | call to select | taint.cpp:151:20:151:25 | call to source |
|
||||
@@ -247,6 +293,8 @@
|
||||
| taint.cpp:350:7:350:7 | t | taint.cpp:330:6:330:11 | call to source |
|
||||
| taint.cpp:351:7:351:7 | a | taint.cpp:330:6:330:11 | call to source |
|
||||
| taint.cpp:352:7:352:7 | b | taint.cpp:330:6:330:11 | call to source |
|
||||
| taint.cpp:353:7:353:7 | c | taint.cpp:330:6:330:11 | call to source |
|
||||
| taint.cpp:354:7:354:7 | d | taint.cpp:330:6:330:11 | call to source |
|
||||
| taint.cpp:372:7:372:7 | a | taint.cpp:365:24:365:29 | source |
|
||||
| taint.cpp:374:7:374:7 | c | taint.cpp:365:24:365:29 | source |
|
||||
| taint.cpp:382:7:382:7 | a | taint.cpp:377:23:377:28 | source |
|
||||
@@ -302,6 +350,7 @@
|
||||
| vector.cpp:139:7:139:8 | v1 | vector.cpp:126:15:126:20 | call to source |
|
||||
| vector.cpp:140:7:140:8 | v2 | vector.cpp:127:15:127:20 | call to source |
|
||||
| vector.cpp:141:7:141:8 | v3 | vector.cpp:128:15:128:20 | call to source |
|
||||
| vector.cpp:162:8:162:15 | access to array | vector.cpp:161:14:161:19 | call to source |
|
||||
| vector.cpp:171:13:171:13 | call to operator[] | vector.cpp:170:14:170:19 | call to source |
|
||||
| vector.cpp:180:13:180:13 | call to operator[] | vector.cpp:179:14:179:19 | call to source |
|
||||
| vector.cpp:201:13:201:13 | call to operator[] | vector.cpp:200:14:200:19 | call to source |
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user