Merge tag 'codeql-cli/latest'

Compatible with the latest released version of the CodeQL CLI
This commit is contained in:
Dilan
2023-10-11 13:02:07 +00:00
1541 changed files with 135924 additions and 95792 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Make __is_trivial a builtin operation
compatibility: full

View File

@@ -1,3 +1,13 @@
## 0.10.0
### Minor Analysis Improvements
* Functions that do not return due to calling functions that don't return (e.g. `exit`) are now detected as
non-returning in the IR and dataflow.
* Treat functions that reach the end of the function as returning in the IR.
They used to be treated as unreachable but it is allowed in C.
* The `DataFlow::asDefiningArgument` predicate now takes its argument from the range starting at `1` instead of `2`. Queries that depend on the single-parameter version of `DataFlow::asDefiningArgument` should have their arguments updated accordingly.
## 0.9.3
No user-facing changes.

View File

@@ -0,0 +1,9 @@
## 0.10.0
### Minor Analysis Improvements
* Functions that do not return due to calling functions that don't return (e.g. `exit`) are now detected as
non-returning in the IR and dataflow.
* Treat functions that reach the end of the function as returning in the IR.
They used to be treated as unreachable but it is allowed in C.
* The `DataFlow::asDefiningArgument` predicate now takes its argument from the range starting at `1` instead of `2`. Queries that depend on the single-parameter version of `DataFlow::asDefiningArgument` should have their arguments updated accordingly.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.9.3
lastReleaseVersion: 0.10.0

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all
version: 0.9.3
version: 0.10.0
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp

View File

@@ -5,155 +5,35 @@
import semmle.code.cpp.Element
import semmle.code.cpp.Declaration
import semmle.code.cpp.metrics.MetricFile
private import codeql.util.FileSystem
private module Input implements InputSig {
abstract class ContainerBase extends @container {
abstract string getAbsolutePath();
ContainerBase getParentContainer() {
containerparent(unresolveElement(result), underlyingElement(this))
}
string toString() { result = this.getAbsolutePath() }
}
class FolderBase extends ContainerBase, @folder {
override string getAbsolutePath() { folders(underlyingElement(this), result) }
}
class FileBase extends ContainerBase, @file {
override string getAbsolutePath() { files(underlyingElement(this), result) }
}
predicate hasSourceLocationPrefix = sourceLocationPrefix/1;
}
private module Impl = Make<Input>;
/** A file or folder. */
class Container extends Locatable, @container {
/**
* Gets the absolute, canonical path of this container, using forward slashes
* as path separator.
*
* The path starts with a _root prefix_ followed by zero or more _path
* segments_ separated by forward slashes.
*
* The root prefix is of one of the following forms:
*
* 1. A single forward slash `/` (Unix-style)
* 2. An upper-case drive letter followed by a colon and a forward slash,
* such as `C:/` (Windows-style)
* 3. Two forward slashes, a computer name, and then another forward slash,
* such as `//FileServer/` (UNC-style)
*
* Path segments are never empty (that is, absolute paths never contain two
* contiguous slashes, except as part of a UNC-style root prefix). Also, path
* segments never contain forward slashes, and no path segment is of the
* form `.` (one dot) or `..` (two dots).
*
* Note that an absolute path never ends with a forward slash, except if it is
* a bare root prefix, that is, the path has no path segments. A container
* whose absolute path has no segments is always a `Folder`, not a `File`.
*/
string getAbsolutePath() { none() } // overridden by subclasses
/**
* Gets the relative path of this file or folder from the root folder of the
* analyzed source location. The relative path of the root folder itself is
* the empty string.
*
* This has no result if the container is outside the source root, that is,
* if the root folder is not a reflexive, transitive parent of this container.
*/
string getRelativePath() {
exists(string absPath, string pref |
absPath = this.getAbsolutePath() and sourceLocationPrefix(pref)
|
absPath = pref and result = ""
or
absPath = pref.regexpReplaceAll("/$", "") + "/" + result and
not result.matches("/%")
)
}
/**
* Gets the base name of this container including extension, that is, the last
* segment of its absolute path, or the empty string if it has no segments.
*
* Here are some examples of absolute paths and the corresponding base names
* (surrounded with quotes to avoid ambiguity):
*
* <table border="1">
* <tr><th>Absolute path</th><th>Base name</th></tr>
* <tr><td>"/tmp/tst.js"</td><td>"tst.js"</td></tr>
* <tr><td>"C:/Program Files (x86)"</td><td>"Program Files (x86)"</td></tr>
* <tr><td>"/"</td><td>""</td></tr>
* <tr><td>"C:/"</td><td>""</td></tr>
* <tr><td>"D:/"</td><td>""</td></tr>
* <tr><td>"//FileServer/"</td><td>""</td></tr>
* </table>
*/
string getBaseName() {
result = this.getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1)
}
/**
* Gets the extension of this container, that is, the suffix of its base name
* after the last dot character, if any.
*
* In particular,
*
* - if the name does not include a dot, there is no extension, so this
* predicate has no result;
* - if the name ends in a dot, the extension is the empty string;
* - if the name contains multiple dots, the extension follows the last dot.
*
* Here are some examples of absolute paths and the corresponding extensions
* (surrounded with quotes to avoid ambiguity):
*
* <table border="1">
* <tr><th>Absolute path</th><th>Extension</th></tr>
* <tr><td>"/tmp/tst.js"</td><td>"js"</td></tr>
* <tr><td>"/tmp/.classpath"</td><td>"classpath"</td></tr>
* <tr><td>"/bin/bash"</td><td>not defined</td></tr>
* <tr><td>"/tmp/tst2."</td><td>""</td></tr>
* <tr><td>"/tmp/x.tar.gz"</td><td>"gz"</td></tr>
* </table>
*/
string getExtension() {
result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3)
}
/**
* Gets the stem of this container, that is, the prefix of its base name up to
* (but not including) the last dot character if there is one, or the entire
* base name if there is not.
*
* Here are some examples of absolute paths and the corresponding stems
* (surrounded with quotes to avoid ambiguity):
*
* <table border="1">
* <tr><th>Absolute path</th><th>Stem</th></tr>
* <tr><td>"/tmp/tst.js"</td><td>"tst"</td></tr>
* <tr><td>"/tmp/.classpath"</td><td>""</td></tr>
* <tr><td>"/bin/bash"</td><td>"bash"</td></tr>
* <tr><td>"/tmp/tst2."</td><td>"tst2"</td></tr>
* <tr><td>"/tmp/x.tar.gz"</td><td>"x.tar"</td></tr>
* </table>
*/
string getStem() {
result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1)
}
/** Gets the parent container of this file or folder, if any. */
Container getParentContainer() {
containerparent(unresolveElement(result), underlyingElement(this))
}
/** Gets a file or sub-folder in this container. */
Container getAChildContainer() { this = result.getParentContainer() }
/** Gets a file in this container. */
File getAFile() { result = this.getAChildContainer() }
/** Gets the file in this container that has the given `baseName`, if any. */
File getFile(string baseName) {
result = this.getAFile() and
result.getBaseName() = baseName
}
/** Gets a sub-folder in this container. */
Folder getAFolder() { result = this.getAChildContainer() }
/** Gets the sub-folder in this container that has the given `baseName`, if any. */
Folder getFolder(string baseName) {
result = this.getAFolder() and
result.getBaseName() = baseName
}
/**
* Gets a textual representation of the path of this container.
*
* This is the absolute path of the container.
*/
override string toString() { result = this.getAbsolutePath() }
class Container extends Locatable, Impl::Container {
override string toString() { result = Impl::Container.super.toString() }
}
/**
@@ -166,9 +46,7 @@ class Container extends Locatable, @container {
*
* To get the full path, use `getAbsolutePath`.
*/
class Folder extends Container, @folder {
override string getAbsolutePath() { folders(underlyingElement(this), result) }
class Folder extends Container, Impl::Folder {
override Location getLocation() {
result.getContainer() = this and
result.hasLocationInfo(_, 0, 0, 0, 0)
@@ -189,9 +67,7 @@ class Folder extends Container, @folder {
* The base name further decomposes into the _stem_ and _extension_ -- see
* `getStem` and `getExtension`. To get the full path, use `getAbsolutePath`.
*/
class File extends Container, @file {
override string getAbsolutePath() { files(underlyingElement(this), result) }
class File extends Container, Impl::File {
override string getAPrimaryQlClass() { result = "File" }
override Location getLocation() {

View File

@@ -73,6 +73,10 @@ private int isSource(Expr bufferExpr, Element why) {
)
}
/** Same as `getBufferSize`, but with the `why` column projected away to prevent large duplications. */
pragma[nomagic]
int getBufferSizeProj(Expr bufferExpr) { result = getBufferSize(bufferExpr, _) }
/**
* Get the size in bytes of the buffer pointed to by an expression (if this can be determined).
*/
@@ -87,7 +91,7 @@ int getBufferSize(Expr bufferExpr, Element why) {
why = bufferVar and
parentPtr = bufferExpr.(VariableAccess).getQualifier() and
parentPtr.getTarget().getUnspecifiedType().(PointerType).getBaseType() = parentClass and
result = getBufferSize(parentPtr, _) + bufferSize - parentClass.getSize()
result = getBufferSizeProj(parentPtr) + bufferSize - parentClass.getSize()
|
if exists(bufferVar.getType().getSize())
then bufferSize = bufferVar.getType().getSize()
@@ -95,7 +99,6 @@ int getBufferSize(Expr bufferExpr, Element why) {
)
or
// dataflow (all sources must be the same size)
result = unique(Expr def | DataFlow::localExprFlowStep(def, bufferExpr) | getBufferSize(def, _)) and
// find reason
result = unique(Expr def | DataFlow::localExprFlowStep(def, bufferExpr) | getBufferSizeProj(def)) and
exists(Expr def | DataFlow::localExprFlowStep(def, bufferExpr) | exists(getBufferSize(def, why)))
}

View File

@@ -26,17 +26,18 @@ predicate callDereferences(FunctionCall fc, int i) {
}
/**
* Holds if evaluation of `op` dereferences `e`.
* Holds if evaluation of `op` dereferences `e` directly.
*
* This predicate does not recurse through function calls or arithmetic operations. To find
* such cases, use `dereferencedByOperation`.
*/
predicate dereferencedByOperation(Expr op, Expr e) {
predicate directDereferencedByOperation(Expr op, Expr e) {
exists(PointerDereferenceExpr deref |
deref.getAChild() = e and
deref = op and
not deref.getParent*() instanceof SizeofOperator
)
or
exists(CrementOperation crement | dereferencedByOperation(e, op) and crement.getOperand() = e)
or
exists(ArrayExpr ae |
(
not ae.getParent() instanceof AddressOfExpr and
@@ -50,6 +51,24 @@ predicate dereferencedByOperation(Expr op, Expr e) {
)
)
or
// ptr->Field
e = op.(FieldAccess).getQualifier() and isClassPointerType(e.getType())
or
// ptr->method()
e = op.(Call).getQualifier() and isClassPointerType(e.getType())
}
/**
* Holds if evaluation of `op` dereferences `e`.
*
* This includes the set of operations identified via `directDereferencedByOperation`, as well
* as calls to function that are known to dereference an argument.
*/
predicate dereferencedByOperation(Expr op, Expr e) {
directDereferencedByOperation(op, e)
or
exists(CrementOperation crement | dereferencedByOperation(e, op) and crement.getOperand() = e)
or
exists(AddressOfExpr addof, ArrayExpr ae |
dereferencedByOperation(addof, op) and
addof.getOperand() = ae and
@@ -74,12 +93,6 @@ predicate dereferencedByOperation(Expr op, Expr e) {
e = fc.getArgument(i) and
op = fc
)
or
// ptr->Field
e = op.(FieldAccess).getQualifier() and isClassPointerType(e.getType())
or
// ptr->method()
e = op.(Call).getQualifier() and isClassPointerType(e.getType())
}
private predicate isClassPointerType(Type t) {

View File

@@ -240,7 +240,7 @@ private class GuardConditionFromIR extends GuardCondition {
*/
private predicate controlsBlock(BasicBlock controlled, boolean testIsTrue) {
exists(IRBlock irb |
forex(IRGuardCondition inst | inst = ir | inst.controls(irb, testIsTrue)) and
ir.controls(irb, testIsTrue) and
irb.getAnInstruction().getAst().(ControlFlowNode).getBasicBlock() = controlled and
not isUnreachedBlock(irb)
)

View File

@@ -79,13 +79,3 @@ class ArgumentPosition extends int {
/** Holds if arguments at position `apos` match parameters at position `ppos`. */
pragma[inline]
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos }
/**
* Holds if flow from `call`'s argument `arg` to parameter `p` is permissible.
*
* This is a temporary hook to support technical debt in the Go language; do not use.
*/
pragma[inline]
predicate golangSpecificParamArgFilter(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
any()
}

View File

@@ -297,6 +297,10 @@ private module Config implements FullStateConfigSig {
predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) }
predicate isBarrierIn(Node node, FlowState state) { none() }
predicate isBarrierOut(Node node, FlowState state) { none() }
predicate isAdditionalFlowStep(Node node1, Node node2) {
singleConfiguration() and
any(Configuration config).isAdditionalFlowStep(node1, node2)

View File

@@ -297,6 +297,10 @@ private module Config implements FullStateConfigSig {
predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) }
predicate isBarrierIn(Node node, FlowState state) { none() }
predicate isBarrierOut(Node node, FlowState state) { none() }
predicate isAdditionalFlowStep(Node node1, Node node2) {
singleConfiguration() and
any(Configuration config).isAdditionalFlowStep(node1, node2)

View File

@@ -297,6 +297,10 @@ private module Config implements FullStateConfigSig {
predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) }
predicate isBarrierIn(Node node, FlowState state) { none() }
predicate isBarrierOut(Node node, FlowState state) { none() }
predicate isAdditionalFlowStep(Node node1, Node node2) {
singleConfiguration() and
any(Configuration config).isAdditionalFlowStep(node1, node2)

View File

@@ -297,6 +297,10 @@ private module Config implements FullStateConfigSig {
predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) }
predicate isBarrierIn(Node node, FlowState state) { none() }
predicate isBarrierOut(Node node, FlowState state) { none() }
predicate isAdditionalFlowStep(Node node1, Node node2) {
singleConfiguration() and
any(Configuration config).isAdditionalFlowStep(node1, node2)

View File

@@ -297,6 +297,10 @@ private module Config implements FullStateConfigSig {
predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) }
predicate isBarrierIn(Node node, FlowState state) { none() }
predicate isBarrierOut(Node node, FlowState state) { none() }
predicate isAdditionalFlowStep(Node node1, Node node2) {
singleConfiguration() and
any(Configuration config).isAdditionalFlowStep(node1, node2)

View File

@@ -208,6 +208,8 @@ predicate expectsContent(Node n, ContentSet c) { none() }
predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() }
predicate localMustFlowStep(Node node1, Node node2) { none() }
/** Gets the type of `n` used for type pruning. */
Type getNodeType(Node n) {
suppressUnusedNode(n) and
@@ -295,12 +297,3 @@ class ContentApprox = Unit;
/** Gets an approximated value for content `c`. */
pragma[inline]
ContentApprox getContentApprox(Content c) { any() }
/**
* Gets an additional term that is added to the `join` and `branch` computations to reflect
* an additional forward or backwards branching factor that is not taken into account
* when calculating the (virtual) dispatch cost.
*
* Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter.
*/
int getAdditionalFlowIntoCallNodeTerm(ArgumentNode arg, ParameterNode p) { none() }

View File

@@ -1547,3 +1547,21 @@ class BuiltInBitCast extends BuiltInOperation, @builtinbitcast {
override string getAPrimaryQlClass() { result = "BuiltInBitCast" }
}
/**
* A C++ `__is_trivial` built-in operation (used by some implementations of the
* `<type_traits>` header).
*
* Returns `true` if a type is a trivial type.
* ```
* template<typename _Tp>
* struct is_trivial
* : public integral_constant<bool, __is_trivial(_Tp)>
* {};
* ```
*/
class BuiltInIsTrivial extends BuiltInOperation, @istrivialexpr {
override string toString() { result = "__is_trivial" }
override string getAPrimaryQlClass() { result = "BuiltInIsTrivial" }
}

View File

@@ -271,13 +271,3 @@ DataFlowCallable viableImplInCallContext(DataFlowCall call, DataFlowCall ctx) {
/** Holds if arguments at position `apos` match parameters at position `ppos`. */
pragma[inline]
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos }
/**
* Holds if flow from `call`'s argument `arg` to parameter `p` is permissible.
*
* This is a temporary hook to support technical debt in the Go language; do not use.
*/
pragma[inline]
predicate golangSpecificParamArgFilter(DataFlowCall call, ParameterNode p, ArgumentNode arg) {
any()
}

View File

@@ -297,6 +297,10 @@ private module Config implements FullStateConfigSig {
predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) }
predicate isBarrierIn(Node node, FlowState state) { none() }
predicate isBarrierOut(Node node, FlowState state) { none() }
predicate isAdditionalFlowStep(Node node1, Node node2) {
singleConfiguration() and
any(Configuration config).isAdditionalFlowStep(node1, node2)

View File

@@ -297,6 +297,10 @@ private module Config implements FullStateConfigSig {
predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) }
predicate isBarrierIn(Node node, FlowState state) { none() }
predicate isBarrierOut(Node node, FlowState state) { none() }
predicate isAdditionalFlowStep(Node node1, Node node2) {
singleConfiguration() and
any(Configuration config).isAdditionalFlowStep(node1, node2)

View File

@@ -297,6 +297,10 @@ private module Config implements FullStateConfigSig {
predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) }
predicate isBarrierIn(Node node, FlowState state) { none() }
predicate isBarrierOut(Node node, FlowState state) { none() }
predicate isAdditionalFlowStep(Node node1, Node node2) {
singleConfiguration() and
any(Configuration config).isAdditionalFlowStep(node1, node2)

View File

@@ -297,6 +297,10 @@ private module Config implements FullStateConfigSig {
predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) }
predicate isBarrierIn(Node node, FlowState state) { none() }
predicate isBarrierOut(Node node, FlowState state) { none() }
predicate isAdditionalFlowStep(Node node1, Node node2) {
singleConfiguration() and
any(Configuration config).isAdditionalFlowStep(node1, node2)

View File

@@ -18,4 +18,6 @@ module CppDataFlow implements InputSig {
import Public
Node exprNode(DataFlowExpr e) { result = Public::exprNode(e) }
predicate getAdditionalFlowIntoCallNodeTerm = Private::getAdditionalFlowIntoCallNodeTerm/2;
}

View File

@@ -804,6 +804,8 @@ predicate expectsContent(Node n, ContentSet c) { none() }
predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() }
predicate localMustFlowStep(Node node1, Node node2) { none() }
/** Gets the type of `n` used for type pruning. */
DataFlowType getNodeType(Node n) {
suppressUnusedNode(n) and

View File

@@ -193,13 +193,23 @@ class Node extends TIRDataFlowNode {
* a `Conversion`, then the result is the underlying non-`Conversion` base
* expression.
*/
Expr asExpr() { result = this.(ExprNode).getExpr() }
Expr asExpr() { result = this.asExpr(_) }
/**
* INTERNAL: Do not use.
*/
Expr asExpr(int n) { result = this.(ExprNode).getExpr(n) }
/**
* INTERNAL: Do not use.
*/
Expr asIndirectExpr(int n, int index) { result = this.(IndirectExprNode).getExpr(n, index) }
/**
* Gets the non-conversion expression that's indirectly tracked by this node
* under `index` number of indirections.
*/
Expr asIndirectExpr(int index) { result = this.(IndirectExprNode).getExpr(index) }
Expr asIndirectExpr(int index) { result = this.asIndirectExpr(_, index) }
/**
* Gets the non-conversion expression that's indirectly tracked by this node
@@ -211,15 +221,26 @@ class Node extends TIRDataFlowNode {
* Gets the expression corresponding to this node, if any. The returned
* expression may be a `Conversion`.
*/
Expr asConvertedExpr() { result = this.(ExprNode).getConvertedExpr() }
Expr asConvertedExpr() { result = this.asConvertedExpr(_) }
/**
* Gets the expression corresponding to this node, if any. The returned
* expression may be a `Conversion`.
*/
Expr asConvertedExpr(int n) { result = this.(ExprNode).getConvertedExpr(n) }
/**
* INTERNAL: Do not use.
*/
Expr asIndirectConvertedExpr(int n, int index) {
result = this.(IndirectExprNode).getConvertedExpr(n, index)
}
/**
* Gets the expression that's indirectly tracked by this node
* behind `index` number of indirections.
*/
Expr asIndirectConvertedExpr(int index) {
result = this.(IndirectExprNode).getConvertedExpr(index)
}
Expr asIndirectConvertedExpr(int index) { result = this.asIndirectConvertedExpr(_, index) }
/**
* Gets the expression that's indirectly tracked by this node behind a
@@ -254,9 +275,7 @@ class Node extends TIRDataFlowNode {
* after the `f` has returned.
*/
Expr asDefiningArgument(int index) {
// Subtract one because `DefinitionByReferenceNode` is defined to be in
// the range `[0 ... n - 1]` for some `n` instead of `[1 ... n]`.
this.(DefinitionByReferenceNode).getIndirectionIndex() = index - 1 and
this.(DefinitionByReferenceNode).getIndirectionIndex() = index and
result = this.(DefinitionByReferenceNode).getArgument()
}
@@ -393,9 +412,10 @@ class Node extends TIRDataFlowNode {
}
private string toExprString(Node n) {
result = n.asExpr().toString()
result = n.asExpr(0).toString()
or
result = n.asIndirectExpr().toString() + " indirection"
not exists(n.asExpr()) and
result = n.asIndirectExpr(0, 1).toString() + " indirection"
}
/**
@@ -935,7 +955,7 @@ class RawIndirectOperand extends Node, TRawIndirectOperand {
}
override string toStringImpl() {
result = instructionNode(this.getOperand().getDef()).toStringImpl() + " indirection"
result = operandNode(this.getOperand()).toStringImpl() + " indirection"
}
}
@@ -1042,77 +1062,130 @@ class RawIndirectInstruction extends Node, TRawIndirectInstruction {
}
}
/** Holds if `node` is an `OperandNode` that should map `node.asExpr()` to `e`. */
predicate exprNodeShouldBeOperand(OperandNode node, Expr e) {
exists(Instruction def |
unique( | | getAUse(def)) = node.getOperand() and
e = def.getConvertedResultExpression()
)
private module GetConvertedResultExpression {
private import semmle.code.cpp.ir.implementation.raw.internal.TranslatedExpr
private import semmle.code.cpp.ir.implementation.raw.internal.InstructionTag
private Operand getAnInitializeDynamicAllocationInstructionAddress() {
result = any(InitializeDynamicAllocationInstruction init).getAllocationAddressOperand()
}
/**
* Gets the expression that should be returned as the result expression from `instr`.
*
* Note that this predicate may return multiple results in cases where a conversion belongs to a
* different AST element than its operand.
*/
Expr getConvertedResultExpression(Instruction instr, int n) {
// Only fully converted instructions have a result for `asConvertedExpr`
not conversionFlow(unique(Operand op |
// The address operand of a `InitializeDynamicAllocationInstruction` is
// special: we need to handle it during dataflow (since it's
// effectively a store to an indirection), but it doesn't appear in
// source syntax, so dataflow node <-> expression conversion shouldn't
// care about it.
op = getAUse(instr) and not op = getAnInitializeDynamicAllocationInstructionAddress()
|
op
), _, false, false) and
result = getConvertedResultExpressionImpl(instr) and
n = 0
or
// If the conversion also has a result then we return multiple results
exists(Operand operand | conversionFlow(operand, instr, false, false) |
n = 1 and
result = getConvertedResultExpressionImpl(operand.getDef())
or
result = getConvertedResultExpression(operand.getDef(), n - 1)
)
}
private Expr getConvertedResultExpressionImpl0(Instruction instr) {
// For an expression such as `i += 2` we pretend that the generated
// `StoreInstruction` contains the result of the expression even though
// this isn't totally aligned with the C/C++ standard.
exists(TranslatedAssignOperation tao |
result = tao.getExpr() and
instr = tao.getInstruction(any(AssignmentStoreTag tag))
)
or
// Similarly for `i++` and `++i` we pretend that the generated
// `StoreInstruction` is contains the result of the expression even though
// this isn't totally aligned with the C/C++ standard.
exists(TranslatedCrementOperation tco |
result = tco.getExpr() and
instr = tco.getInstruction(any(CrementStoreTag tag))
)
or
// IR construction inserts an additional cast to a `size_t` on the extent
// of a `new[]` expression. The resulting `ConvertInstruction` doesn't have
// a result for `getConvertedResultExpression`. We remap this here so that
// this `ConvertInstruction` maps to the result of the expression that
// represents the extent.
exists(TranslatedNonConstantAllocationSize tas |
result = tas.getExtent().getExpr() and
instr = tas.getInstruction(any(AllocationExtentConvertTag tag))
)
or
// There's no instruction that returns `ParenthesisExpr`, but some queries
// expect this
exists(TranslatedTransparentConversion ttc |
result = ttc.getExpr().(ParenthesisExpr) and
instr = ttc.getResult()
)
}
private Expr getConvertedResultExpressionImpl(Instruction instr) {
result = getConvertedResultExpressionImpl0(instr)
or
not exists(getConvertedResultExpressionImpl0(instr)) and
result = instr.getConvertedResultExpression()
}
}
private predicate indirectExprNodeShouldBeIndirectOperand0(
VariableAddressInstruction instr, RawIndirectOperand node, Expr e
) {
instr = node.getOperand().getDef() and
e = instr.getAst().(Expr).getUnconverted()
private import GetConvertedResultExpression
/** Holds if `node` is an `OperandNode` that should map `node.asExpr()` to `e`. */
predicate exprNodeShouldBeOperand(OperandNode node, Expr e, int n) {
exists(Instruction def |
unique( | | getAUse(def)) = node.getOperand() and
e = getConvertedResultExpression(def, n)
)
}
/** Holds if `node` should be an `IndirectOperand` that maps `node.asIndirectExpr()` to `e`. */
private predicate indirectExprNodeShouldBeIndirectOperand(RawIndirectOperand node, Expr e) {
exists(Instruction instr | instr = node.getOperand().getDef() |
exists(Expr e0 |
indirectExprNodeShouldBeIndirectOperand0(instr, node, e0) and
e = e0.getFullyConverted()
)
or
not indirectExprNodeShouldBeIndirectOperand0(_, node, _) and
e = instr.getConvertedResultExpression()
private predicate indirectExprNodeShouldBeIndirectOperand(
IndirectOperand node, Expr e, int n, int indirectionIndex
) {
exists(Instruction def |
node.hasOperandAndIndirectionIndex(unique( | | getAUse(def)), indirectionIndex) and
e = getConvertedResultExpression(def, n)
)
}
private predicate exprNodeShouldBeIndirectOutNode(IndirectArgumentOutNode node, Expr e) {
private predicate exprNodeShouldBeIndirectOutNode(IndirectArgumentOutNode node, Expr e, int n) {
exists(CallInstruction call |
call.getStaticCallTarget() instanceof Constructor and
e = call.getConvertedResultExpression() and
e = getConvertedResultExpression(call, n) and
call.getThisArgumentOperand() = node.getAddressOperand()
)
}
/** Holds if `node` should be an instruction node that maps `node.asExpr()` to `e`. */
predicate exprNodeShouldBeInstruction(Node node, Expr e) {
not exprNodeShouldBeOperand(_, e) and
not exprNodeShouldBeIndirectOutNode(_, e) and
(
e = node.asInstruction().getConvertedResultExpression()
or
// The instruction that contains the result of an `AssignOperation` is
// the unloaded left operand (see the comments in `TranslatedAssignOperation`).
// That means that for cases like
// ```cpp
// int x = ...;
// x += 1;
// ```
// the result of `x += 1` is the `VariableAddressInstruction` that represents `x`. But
// that instruction doesn't receive the flow from this `AssignOperation`. So instead we
// map the operation to the `AddInstruction`.
node.asInstruction().getAst() = e.(AssignOperation)
or
// Same story for `CrementOperation`s (cf. the comments in the subclasses
// of `TranslatedCrementOperation`).
node.asInstruction().getAst() = e.(CrementOperation)
)
predicate exprNodeShouldBeInstruction(Node node, Expr e, int n) {
not exprNodeShouldBeOperand(_, e, n) and
not exprNodeShouldBeIndirectOutNode(_, e, n) and
e = getConvertedResultExpression(node.asInstruction(), n)
}
/** Holds if `node` should be an `IndirectInstruction` that maps `node.asIndirectExpr()` to `e`. */
predicate indirectExprNodeShouldBeIndirectInstruction(IndirectInstruction node, Expr e) {
predicate indirectExprNodeShouldBeIndirectInstruction(
IndirectInstruction node, Expr e, int n, int indirectionIndex
) {
not indirectExprNodeShouldBeIndirectOperand(_, e, n, indirectionIndex) and
exists(Instruction instr |
node.hasInstructionAndIndirectionIndex(instr, _) and
not indirectExprNodeShouldBeIndirectOperand(_, e)
|
e = instr.(VariableAddressInstruction).getAst().(Expr).getFullyConverted()
or
not instr instanceof VariableAddressInstruction and
e = instr.getConvertedResultExpression()
node.hasInstructionAndIndirectionIndex(instr, indirectionIndex) and
e = getConvertedResultExpression(instr, n)
)
}
@@ -1121,30 +1194,32 @@ abstract private class ExprNodeBase extends Node {
* Gets the expression corresponding to this node, if any. The returned
* expression may be a `Conversion`.
*/
abstract Expr getConvertedExpr();
abstract Expr getConvertedExpr(int n);
/** Gets the non-conversion expression corresponding to this node, if any. */
abstract Expr getExpr();
final Expr getExpr(int n) { result = this.getConvertedExpr(n).getUnconverted() }
}
private class InstructionExprNode extends ExprNodeBase, InstructionNode {
InstructionExprNode() { exprNodeShouldBeInstruction(this, _) }
InstructionExprNode() {
exists(Expr e, int n |
exprNodeShouldBeInstruction(this, e, n) and
not exprNodeShouldBeInstruction(_, e, n + 1)
)
}
final override Expr getConvertedExpr() { exprNodeShouldBeInstruction(this, result) }
final override Expr getExpr() { result = this.getConvertedExpr().getUnconverted() }
final override string toStringImpl() { result = this.getConvertedExpr().toString() }
final override Expr getConvertedExpr(int n) { exprNodeShouldBeInstruction(this, result, n) }
}
private class OperandExprNode extends ExprNodeBase, OperandNode {
OperandExprNode() { exprNodeShouldBeOperand(this, _) }
OperandExprNode() {
exists(Expr e, int n |
exprNodeShouldBeOperand(this, e, n) and
not exprNodeShouldBeOperand(_, e, n + 1)
)
}
final override Expr getConvertedExpr() { exprNodeShouldBeOperand(this, result) }
final override Expr getExpr() { result = this.getConvertedExpr().getUnconverted() }
final override string toStringImpl() { result = this.getConvertedExpr().toString() }
final override Expr getConvertedExpr(int n) { exprNodeShouldBeOperand(this, result, n) }
}
abstract private class IndirectExprNodeBase extends Node {
@@ -1152,67 +1227,75 @@ abstract private class IndirectExprNodeBase extends Node {
* Gets the expression corresponding to this node, if any. The returned
* expression may be a `Conversion`.
*/
abstract Expr getConvertedExpr(int indirectionIndex);
abstract Expr getConvertedExpr(int n, int indirectionIndex);
/** Gets the non-conversion expression corresponding to this node, if any. */
abstract Expr getExpr(int indirectionIndex);
}
private class IndirectOperandIndirectExprNode extends IndirectExprNodeBase, RawIndirectOperand {
IndirectOperandIndirectExprNode() { indirectExprNodeShouldBeIndirectOperand(this, _) }
final override Expr getConvertedExpr(int index) {
this.getIndirectionIndex() = index and
indirectExprNodeShouldBeIndirectOperand(this, result)
}
final override Expr getExpr(int index) {
this.getIndirectionIndex() = index and
result = this.getConvertedExpr(index).getUnconverted()
final Expr getExpr(int n, int indirectionIndex) {
result = this.getConvertedExpr(n, indirectionIndex).getUnconverted()
}
}
private class IndirectInstructionIndirectExprNode extends IndirectExprNodeBase,
RawIndirectInstruction
private class IndirectOperandIndirectExprNode extends IndirectExprNodeBase instanceof IndirectOperand
{
IndirectInstructionIndirectExprNode() { indirectExprNodeShouldBeIndirectInstruction(this, _) }
final override Expr getConvertedExpr(int index) {
this.getIndirectionIndex() = index and
indirectExprNodeShouldBeIndirectInstruction(this, result)
IndirectOperandIndirectExprNode() {
exists(Expr e, int n, int indirectionIndex |
indirectExprNodeShouldBeIndirectOperand(this, e, n, indirectionIndex) and
not indirectExprNodeShouldBeIndirectOperand(_, e, n + 1, indirectionIndex)
)
}
final override Expr getExpr(int index) {
this.getIndirectionIndex() = index and
result = this.getConvertedExpr(index).getUnconverted()
final override Expr getConvertedExpr(int n, int index) {
indirectExprNodeShouldBeIndirectOperand(this, result, n, index)
}
}
private class IndirectInstructionIndirectExprNode extends IndirectExprNodeBase instanceof IndirectInstruction
{
IndirectInstructionIndirectExprNode() {
exists(Expr e, int n, int indirectionIndex |
indirectExprNodeShouldBeIndirectInstruction(this, e, n, indirectionIndex) and
not indirectExprNodeShouldBeIndirectInstruction(_, e, n + 1, indirectionIndex)
)
}
final override Expr getConvertedExpr(int n, int index) {
indirectExprNodeShouldBeIndirectInstruction(this, result, n, index)
}
}
private class IndirectArgumentOutExprNode extends ExprNodeBase, IndirectArgumentOutNode {
IndirectArgumentOutExprNode() { exprNodeShouldBeIndirectOutNode(this, _) }
IndirectArgumentOutExprNode() { exprNodeShouldBeIndirectOutNode(this, _, _) }
final override Expr getConvertedExpr() { exprNodeShouldBeIndirectOutNode(this, result) }
final override Expr getExpr() { result = this.getConvertedExpr() }
final override Expr getConvertedExpr(int n) { exprNodeShouldBeIndirectOutNode(this, result, n) }
}
/**
* An expression, viewed as a node in a data flow graph.
*/
class ExprNode extends Node instanceof ExprNodeBase {
/**
* INTERNAL: Do not use.
*/
Expr getExpr(int n) { result = super.getExpr(n) }
/**
* Gets the non-conversion expression corresponding to this node, if any. If
* this node strictly (in the sense of `getConvertedExpr`) corresponds to a
* `Conversion`, then the result is that `Conversion`'s non-`Conversion` base
* expression.
*/
Expr getExpr() { result = super.getExpr() }
final Expr getExpr() { result = this.getExpr(_) }
/**
* INTERNAL: Do not use.
*/
Expr getConvertedExpr(int n) { result = super.getConvertedExpr(n) }
/**
* Gets the expression corresponding to this node, if any. The returned
* expression may be a `Conversion`.
*/
Expr getConvertedExpr() { result = super.getConvertedExpr() }
final Expr getConvertedExpr() { result = this.getConvertedExpr(_) }
}
/**
@@ -1225,13 +1308,27 @@ class IndirectExprNode extends Node instanceof IndirectExprNodeBase {
* `Conversion`, then the result is that `Conversion`'s non-`Conversion` base
* expression.
*/
Expr getExpr(int indirectionIndex) { result = super.getExpr(indirectionIndex) }
final Expr getExpr(int indirectionIndex) { result = this.getExpr(_, indirectionIndex) }
/**
* INTERNAL: Do not use.
*/
Expr getExpr(int n, int indirectionIndex) { result = super.getExpr(n, indirectionIndex) }
/**
* INTERNAL: Do not use.
*/
Expr getConvertedExpr(int n, int indirectionIndex) {
result = super.getConvertedExpr(n, indirectionIndex)
}
/**
* Gets the expression corresponding to this node, if any. The returned
* expression may be a `Conversion`.
*/
Expr getConvertedExpr(int indirectionIndex) { result = super.getConvertedExpr(indirectionIndex) }
Expr getConvertedExpr(int indirectionIndex) {
result = this.getConvertedExpr(_, indirectionIndex)
}
}
/**
@@ -1257,6 +1354,9 @@ class ParameterNode extends Node {
* pointer-indirection parameters are at further negative positions.
*/
predicate isParameterOf(Function f, ParameterPosition pos) { none() } // overridden by subclasses
/** Gets the `Parameter` associated with this node, if it exists. */
Parameter getParameter() { none() } // overridden by subclasses
}
/** An explicit positional parameter, including `this`, but not `...`. */
@@ -1279,10 +1379,9 @@ private class ExplicitParameterNode extends ParameterNode, DirectParameterNode {
f.getParameter(pos.(DirectPosition).getIndex()) = instr.getParameter()
}
/** Gets the `Parameter` associated with this node. */
Parameter getParameter() { result = instr.getParameter() }
override string toStringImpl() { result = instr.getParameter().toString() }
override Parameter getParameter() { result = instr.getParameter() }
}
/** An implicit `this` parameter. */
@@ -1444,7 +1543,7 @@ OperandNode operandNode(Operand operand) { result.getOperand() = operand }
* _out of_ an expression, like when an argument is passed by reference, use
* `definitionByReferenceNodeFromArgument` instead.
*/
ExprNode exprNode(Expr e) { result.getExpr() = e }
ExprNode exprNode(Expr e) { result.getExpr(_) = e }
/**
* Gets the `Node` corresponding to the value of evaluating `e`. Here, `e` may
@@ -1452,7 +1551,7 @@ ExprNode exprNode(Expr e) { result.getExpr() = e }
* argument is passed by reference, use
* `definitionByReferenceNodeFromArgument` instead.
*/
ExprNode convertedExprNode(Expr e) { result.getConvertedExpr() = e }
ExprNode convertedExprNode(Expr e) { result.getConvertedExpr(_) = e }
/**
* Gets the `Node` corresponding to the value of `p` at function entry.

View File

@@ -447,9 +447,16 @@ class GlobalUse extends UseImpl, TGlobalUse {
IRFunction getIRFunction() { result = f }
final override predicate hasIndexInBlock(IRBlock block, int index) {
exists(ExitFunctionInstruction exit |
exit = f.getExitFunctionInstruction() and
block.getInstruction(index) = exit
// Similar to the `FinalParameterUse` case, we want to generate flow out of
// globals at any exit so that we can flow out of non-returning functions.
// Obviously this isn't correct as we can't actually flow but the global flow
// requires this if we want to flow into children.
exists(Instruction return |
return instanceof ReturnInstruction or
return instanceof UnreachedInstruction
|
block.getInstruction(index) = return and
return.getEnclosingIRFunction() = f
)
}
@@ -818,7 +825,7 @@ predicate fromPhiNode(SsaPhiNode nodeFrom, Node nodeTo) {
or
exists(PhiNode phiTo |
phi != phiTo and
lastRefRedefExt(phi, _, _, phiTo) and
lastRefRedefExt(phi, bb1, i1, phiTo) and
nodeTo.(SsaPhiNode).getPhiNode() = phiTo
)
)

View File

@@ -405,9 +405,6 @@ predicate hasUnreachedInstruction(IRFunction func) {
exists(Call c |
c.getEnclosingFunction() = func.getFunction() and
any(Options opt).exits(c.getTarget())
) and
not exists(TranslatedUnreachableReturnStmt return |
return.getEnclosingFunction().getFunction() = func.getFunction()
)
}

View File

@@ -824,6 +824,9 @@ abstract class TranslatedElement extends TTranslatedElement {
/** DEPRECATED: Alias for getAst */
deprecated Locatable getAST() { result = this.getAst() }
/** Gets the location of this element. */
Location getLocation() { result = this.getAst().getLocation() }
/**
* Get the first instruction to be executed in the evaluation of this element.
*/

View File

@@ -1906,8 +1906,10 @@ class TranslatedNonConstantAllocationSize extends TranslatedAllocationSize {
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
resultType = getTypeForPRValue(expr.getAllocator().getParameter(0).getType()) and
(
this.extentNeedsConversion() and
// Convert the extent to `size_t`, because the AST doesn't do this already.
tag = AllocationExtentConvertTag() and opcode instanceof Opcode::Convert
tag = AllocationExtentConvertTag() and
opcode instanceof Opcode::Convert
or
tag = AllocationElementSizeTag() and opcode instanceof Opcode::Constant
or
@@ -1918,6 +1920,7 @@ class TranslatedNonConstantAllocationSize extends TranslatedAllocationSize {
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
kind instanceof GotoEdge and
(
this.extentNeedsConversion() and
tag = AllocationExtentConvertTag() and
result = this.getInstruction(AllocationElementSizeTag())
or
@@ -1933,7 +1936,9 @@ class TranslatedNonConstantAllocationSize extends TranslatedAllocationSize {
final override Instruction getChildSuccessor(TranslatedElement child) {
child = this.getExtent() and
result = this.getInstruction(AllocationExtentConvertTag())
if this.extentNeedsConversion()
then result = this.getInstruction(AllocationExtentConvertTag())
else result = this.getInstruction(AllocationElementSizeTag())
}
final override string getInstructionConstantValue(InstructionTag tag) {
@@ -1945,19 +1950,31 @@ class TranslatedNonConstantAllocationSize extends TranslatedAllocationSize {
tag = AllocationSizeTag() and
(
operandTag instanceof LeftOperandTag and
result = this.getInstruction(AllocationExtentConvertTag())
(
if this.extentNeedsConversion()
then result = this.getInstruction(AllocationExtentConvertTag())
else result = this.getExtent().getResult()
)
or
operandTag instanceof RightOperandTag and
result = this.getInstruction(AllocationElementSizeTag())
)
or
this.extentNeedsConversion() and
tag = AllocationExtentConvertTag() and
operandTag instanceof UnaryOperandTag and
result = this.getExtent().getResult()
}
private TranslatedExpr getExtent() {
result = getTranslatedExpr(expr.getExtent().getFullyConverted())
TranslatedExpr getExtent() { result = getTranslatedExpr(expr.getExtent().getFullyConverted()) }
/**
* Holds if the result of `expr.getExtent()` does not have the same type as
* the allocator's size parameter.
*/
private predicate extentNeedsConversion() {
expr.getExtent().getFullyConverted().getUnspecifiedType() !=
expr.getAllocator().getParameter(0).getUnspecifiedType()
}
}

View File

@@ -22,8 +22,6 @@ class TranslatedStaticStorageDurationVarInit extends TranslatedRootElement,
final override Declaration getFunction() { result = var }
final Location getLocation() { result = var.getLocation() }
override Instruction getFirstInstruction() { result = this.getInstruction(EnterFunctionTag()) }
override TranslatedElement getChild(int n) {

View File

@@ -442,29 +442,26 @@ class TranslatedReturnVoidStmt extends TranslatedReturnStmt {
/**
* The IR translation of an implicit `return` statement generated by the extractor to handle control
* flow that reaches the end of a non-`void`-returning function body. Since such control flow
* produces undefined behavior, we simply generate an `Unreached` instruction to prevent that flow
* from continuing on to pollute other analysis. The assumption is that the developer is certain
* that the implicit `return` is unreachable, even if the compiler cannot prove it.
* flow that reaches the end of a non-`void`-returning function body. Such control flow
* produces undefined behavior in C++ but not in C. However even in C using the return value is
* undefined behaviour. We make it return uninitialized memory to get as much flow as possible.
*/
class TranslatedUnreachableReturnStmt extends TranslatedReturnStmt {
TranslatedUnreachableReturnStmt() {
class TranslatedNoValueReturnStmt extends TranslatedReturnStmt, TranslatedVariableInitialization {
TranslatedNoValueReturnStmt() {
not stmt.hasExpr() and hasReturnValue(stmt.getEnclosingFunction())
}
override TranslatedElement getChild(int id) { none() }
override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
tag = OnlyInstructionTag() and
opcode instanceof Opcode::Unreached and
resultType = getVoidType()
final override Instruction getInitializationSuccessor() {
result = this.getEnclosingFunction().getReturnSuccessorInstruction()
}
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
final override Type getTargetType() { result = this.getEnclosingFunction().getReturnType() }
override Instruction getChildSuccessor(TranslatedElement child) { none() }
final override TranslatedInitialization getInitialization() { none() }
final override IRVariable getIRVariable() {
result = this.getEnclosingFunction().getReturnVariable()
}
}
/**

View File

@@ -10,6 +10,65 @@ predicate isInfeasibleInstructionSuccessor(Instruction instr, EdgeKind kind) {
or
instr.getSuccessor(kind) instanceof UnreachedInstruction and
kind instanceof GotoEdge
or
isCallToNonReturningFunction(instr) and exists(instr.getSuccessor(kind))
}
/**
* Holds if all calls to `f` never return (e.g. they call `exit` or loop forever)
*/
private predicate isNonReturningFunction(IRFunction f) {
// If the function has an instruction with a missing successor then
// the analysis is probably going to be incorrect, so assume they exit.
not hasInstructionWithMissingSuccessor(f) and
(
// If all flows to the exit block are pass through an unreachable then f never returns.
any(UnreachedInstruction instr).getBlock().postDominates(f.getEntryBlock())
or
// If there is no flow to the exit block then f never returns.
not exists(IRBlock entry, IRBlock exit |
exit = f.getExitFunctionInstruction().getBlock() and
entry = f.getEntryBlock() and
exit = entry.getASuccessor*()
)
or
// If all flows to the exit block are pass through a call that never returns then f never returns.
exists(CallInstruction ci |
ci.getBlock().postDominates(f.getEntryBlock()) and
isCallToNonReturningFunction(ci)
)
)
}
/**
* Holds if `f` has an instruction with a missing successor.
* This matches `instructionWithoutSuccessor` from `IRConsistency`, but
* avoids generating the error strings.
*/
predicate hasInstructionWithMissingSuccessor(IRFunction f) {
exists(Instruction missingSucc |
missingSucc.getEnclosingIRFunction() = f and
not exists(missingSucc.getASuccessor()) and
not missingSucc instanceof ExitFunctionInstruction and
// Phi instructions aren't linked into the instruction-level flow graph.
not missingSucc instanceof PhiInstruction and
not missingSucc instanceof UnreachedInstruction
)
}
/**
* Holds if the call `ci` never returns.
*/
private predicate isCallToNonReturningFunction(CallInstruction ci) {
exists(IRFunction callee, Language::Function staticTarget |
staticTarget = ci.getStaticCallTarget() and
staticTarget = callee.getFunction() and
// We can't easily tell if the call is virtual or not
// if the callee is virtual. So assume that the call is virtual
// if the target is.
not staticTarget.isVirtual() and
isNonReturningFunction(callee)
)
}
pragma[noinline]

View File

@@ -1,2 +1,3 @@
import semmle.code.cpp.ir.implementation.raw.IR as IR
import semmle.code.cpp.ir.implementation.raw.constant.ConstantAnalysis as ConstantAnalysis
import semmle.code.cpp.ir.internal.IRCppLanguage as Language

View File

@@ -10,6 +10,65 @@ predicate isInfeasibleInstructionSuccessor(Instruction instr, EdgeKind kind) {
or
instr.getSuccessor(kind) instanceof UnreachedInstruction and
kind instanceof GotoEdge
or
isCallToNonReturningFunction(instr) and exists(instr.getSuccessor(kind))
}
/**
* Holds if all calls to `f` never return (e.g. they call `exit` or loop forever)
*/
private predicate isNonReturningFunction(IRFunction f) {
// If the function has an instruction with a missing successor then
// the analysis is probably going to be incorrect, so assume they exit.
not hasInstructionWithMissingSuccessor(f) and
(
// If all flows to the exit block are pass through an unreachable then f never returns.
any(UnreachedInstruction instr).getBlock().postDominates(f.getEntryBlock())
or
// If there is no flow to the exit block then f never returns.
not exists(IRBlock entry, IRBlock exit |
exit = f.getExitFunctionInstruction().getBlock() and
entry = f.getEntryBlock() and
exit = entry.getASuccessor*()
)
or
// If all flows to the exit block are pass through a call that never returns then f never returns.
exists(CallInstruction ci |
ci.getBlock().postDominates(f.getEntryBlock()) and
isCallToNonReturningFunction(ci)
)
)
}
/**
* Holds if `f` has an instruction with a missing successor.
* This matches `instructionWithoutSuccessor` from `IRConsistency`, but
* avoids generating the error strings.
*/
predicate hasInstructionWithMissingSuccessor(IRFunction f) {
exists(Instruction missingSucc |
missingSucc.getEnclosingIRFunction() = f and
not exists(missingSucc.getASuccessor()) and
not missingSucc instanceof ExitFunctionInstruction and
// Phi instructions aren't linked into the instruction-level flow graph.
not missingSucc instanceof PhiInstruction and
not missingSucc instanceof UnreachedInstruction
)
}
/**
* Holds if the call `ci` never returns.
*/
private predicate isCallToNonReturningFunction(CallInstruction ci) {
exists(IRFunction callee, Language::Function staticTarget |
staticTarget = ci.getStaticCallTarget() and
staticTarget = callee.getFunction() and
// We can't easily tell if the call is virtual or not
// if the callee is virtual. So assume that the call is virtual
// if the target is.
not staticTarget.isVirtual() and
isNonReturningFunction(callee)
)
}
pragma[noinline]

View File

@@ -1,2 +1,3 @@
import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as IR
import semmle.code.cpp.ir.implementation.unaliased_ssa.constant.ConstantAnalysis as ConstantAnalysis
import semmle.code.cpp.ir.internal.IRCppLanguage as Language

View File

@@ -917,25 +917,46 @@ module RangeStage<
bounded(cast.getOperand(), b, delta, upper, fromBackEdge, origdelta, reason)
}
pragma[nomagic]
private predicate initialBoundedUpper(SemExpr e) {
exists(D::Delta d |
initialBounded(e, _, d, false, _, _, _) and
D::toFloat(d) >= 0
)
}
private predicate noOverflow0(SemExpr e, boolean upper) {
exists(boolean lower | lower = upper.booleanNot() |
semExprDoesNotOverflow(lower, e)
or
upper = [true, false] and
not potentiallyOverflowingExpr(lower, e)
)
}
pragma[nomagic]
private predicate initialBoundedLower(SemExpr e) {
exists(D::Delta d |
initialBounded(e, _, d, true, _, _, _) and
D::toFloat(d) <= 0
)
}
pragma[nomagic]
private predicate noOverflow(SemExpr e, boolean upper) {
noOverflow0(e, upper)
or
upper = true and initialBoundedUpper(e)
or
upper = false and initialBoundedLower(e)
}
predicate bounded(
SemExpr e, SemBound b, D::Delta delta, boolean upper, boolean fromBackEdge, D::Delta origdelta,
SemReason reason
) {
initialBounded(e, b, delta, upper, fromBackEdge, origdelta, reason) and
(
semExprDoesNotOverflow(upper.booleanNot(), e)
or
not potentiallyOverflowingExpr(upper.booleanNot(), e)
or
exists(D::Delta otherDelta |
initialBounded(e, _, otherDelta, upper.booleanNot(), _, _, _) and
(
upper = true and D::toFloat(otherDelta) >= 0
or
upper = false and D::toFloat(otherDelta) <= 0
)
)
)
noOverflow(e, upper)
}
predicate potentiallyOverflowingExpr(boolean positively, SemExpr expr) {

View File

@@ -72,7 +72,7 @@ predicate hasSize(HeuristicAllocationExpr alloc, DataFlow::Node n, int state) {
// Compute `delta` as the constant difference between `x` and `x + 1`.
bounded1(any(Instruction instr | instr.getUnconvertedResultExpression() = size),
any(LoadInstruction load | load.getUnconvertedResultExpression() = va), delta) and
n.asConvertedExpr() = va.getFullyConverted() and
n.asExpr() = va and
state = delta
)
}
@@ -210,7 +210,7 @@ private module InterestingPointerAddInstruction {
predicate isSource(DataFlow::Node source) {
// The sources is the same as in the sources for the second
// projection in the `AllocToInvalidPointerConfig` module.
hasSize(source.asConvertedExpr(), _, _)
hasSize(source.asExpr(), _, _)
}
int fieldFlowBranchLimit() { result = allocationToInvalidPointerFieldFlowBranchLimit() }
@@ -243,7 +243,7 @@ private module InterestingPointerAddInstruction {
*/
predicate isInterestingSize(DataFlow::Node n) {
exists(DataFlow::Node alloc |
hasSize(alloc.asConvertedExpr(), n, _) and
hasSize(alloc.asExpr(), n, _) and
flow(alloc, _)
)
}
@@ -268,7 +268,7 @@ private module Config implements ProductFlow::StateConfigSig {
// we use `state2` to remember that there was an offset (in this case an offset of `1`) added
// to the size of the allocation. This state is then checked in `isSinkPair`.
exists(unit) and
hasSize(allocSource.asConvertedExpr(), sizeSource, sizeAddend)
hasSize(allocSource.asExpr(), sizeSource, sizeAddend)
}
int fieldFlowBranchLimit1() { result = allocationToInvalidPointerFieldFlowBranchLimit() }

View File

@@ -1755,6 +1755,7 @@ case @expr.kind of
| @istriviallydestructibleexpr
| @istriviallyassignableexpr
| @isnothrowassignableexpr
| @istrivialexpr
| @isstandardlayoutexpr
| @istriviallycopyableexpr
| @isliteraltypeexpr

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Make __is_trivial a builtin operation
compatibility: full

View File

@@ -1,3 +1,16 @@
## 0.8.0
### Query Metadata Changes
* The `cpp/double-free` query has been further improved to reduce false positives and its precision has been increased from `medium` to `high`.
* The `cpp/use-after-free` query has been further improved to reduce false positives and its precision has been increased from `medium` to `high`.
### Minor Analysis Improvements
* The queries `cpp/double-free` and `cpp/use-after-free` find fewer false positives
in cases where a non-returning function is called.
* The number of duplicated dataflow paths reported by queries has been significantly reduced.
## 0.7.5
No user-facing changes.

View File

@@ -2,7 +2,7 @@
* @name Potential double free
* @description Freeing a resource more than once can lead to undefined behavior and cause memory corruption.
* @kind path-problem
* @precision medium
* @precision high
* @id cpp/double-free
* @problem.severity warning
* @security-severity 9.3

View File

@@ -98,8 +98,11 @@ module FlowFromFree<isSinkSig/2 isASink, isExcludedSig/2 isExcluded> {
* is being freed by a deallocation expression `dealloc`.
*/
predicate isFree(DataFlow::Node n, Expr e, DeallocationExpr dealloc) {
e = dealloc.getFreedExpr() and
e = n.asExpr() and
exists(Expr conv |
e = conv.getUnconverted() and
conv = dealloc.getFreedExpr().getFullyConverted() and
conv = n.asConvertedExpr()
) and
// Ignore realloc functions
not exists(dealloc.(FunctionCall).getTarget().(AllocationFunction).getReallocPtrArg())
}

View File

@@ -2,7 +2,7 @@
* @name Potential use after free
* @description An allocated memory block is used after it has been freed. Behavior in such cases is undefined and can cause memory corruption.
* @kind path-problem
* @precision medium
* @precision high
* @id cpp/use-after-free
* @problem.severity warning
* @security-severity 9.3
@@ -29,8 +29,7 @@ private predicate externalCallNeverDereferences(FormattingFunctionCall call, int
)
}
predicate isUse0(DataFlow::Node n, Expr e) {
e = n.asExpr() and
predicate isUse0(Expr e) {
not isFree(_, e, _) and
(
e = any(PointerDereferenceExpr pde).getOperand()
@@ -43,7 +42,7 @@ predicate isUse0(DataFlow::Node n, Expr e) {
or
// Assume any function without a body will dereference the pointer
exists(int i, Call call, Function f |
n.asExpr() = call.getArgument(i) and
e = call.getArgument(i) and
f = call.getTarget() and
not f.hasEntryPoint() and
// Exclude known functions we know won't dereference the pointer.
@@ -57,7 +56,7 @@ module ParameterSinks {
import semmle.code.cpp.ir.ValueNumbering
predicate flowsToUse(DataFlow::Node n) {
isUse0(n, _)
isUse0(n.asExpr())
or
exists(DataFlow::Node succ |
flowsToUse(succ) and
@@ -90,7 +89,7 @@ module ParameterSinks {
) {
pragma[only_bind_out](source.asParameter()) = pragma[only_bind_out](init.getParameter()) and
paramToUse(source, sink) and
isUse0(sink, _)
isUse0(sink.asExpr())
}
private InitializeParameterInstruction getAnAlwaysDereferencedParameter0() {
@@ -139,7 +138,7 @@ module IsUse {
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplCommon
predicate isUse(DataFlow::Node n, Expr e) {
isUse0(n, e)
isUse0(e) and n.asExpr() = e
or
exists(CallInstruction call, InitializeParameterInstruction init |
n.asOperand().getDef().getUnconvertedResultExpression() = e and

View File

@@ -296,7 +296,7 @@ deprecated class PossibleYearArithmeticOperationCheckConfiguration extends Taint
}
override predicate isSource(DataFlow::Node source) {
exists(Operation op | op = source.asConvertedExpr() |
exists(Operation op | op = source.asExpr() |
op.getAChild*().getValue().toInt() = 365 and
(
not op.getParent() instanceof Expr or
@@ -321,7 +321,7 @@ deprecated class PossibleYearArithmeticOperationCheckConfiguration extends Taint
override predicate isSink(DataFlow::Node sink) {
exists(StructLikeClass dds, FieldAccess fa, AssignExpr aexpr |
aexpr.getRValue() = sink.asConvertedExpr()
aexpr.getRValue() = sink.asExpr()
|
(dds instanceof PackedTimeType or dds instanceof UnpackedTimeType) and
fa.getQualifier().getUnderlyingType() = dds and
@@ -336,7 +336,7 @@ deprecated class PossibleYearArithmeticOperationCheckConfiguration extends Taint
*/
private module PossibleYearArithmeticOperationCheckConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
exists(Operation op | op = source.asConvertedExpr() |
exists(Operation op | op = source.asExpr() |
op.getAChild*().getValue().toInt() = 365 and
(
not op.getParent() instanceof Expr or
@@ -361,7 +361,7 @@ private module PossibleYearArithmeticOperationCheckConfig implements DataFlow::C
predicate isSink(DataFlow::Node sink) {
exists(StructLikeClass dds, FieldAccess fa, AssignExpr aexpr |
aexpr.getRValue() = sink.asConvertedExpr()
aexpr.getRValue() = sink.asExpr()
|
(dds instanceof PackedTimeType or dds instanceof UnpackedTimeType) and
fa.getQualifier().getUnderlyingType() = dds and

View File

@@ -0,0 +1,18 @@
/**
* @name Count AST inconsistencies
* @description Counts the various AST inconsistencies that may occur.
* This query is for internal use only and may change without notice.
* @kind table
* @id cpp/count-ast-inconsistencies
*/
import cpp
predicate hasDuplicateFunctionEntryPointLocation(Function func) {
count(func.getEntryPoint().getLocation()) > 1
}
predicate hasDuplicateFunctionEntryPoint(Function func) { count(func.getEntryPoint()) > 1 }
select count(Function f | hasDuplicateFunctionEntryPoint(f) | f) as duplicateFunctionEntryPoint,
count(Function f | hasDuplicateFunctionEntryPointLocation(f) | f) as duplicateFunctionEntryPointLocation

View File

@@ -30,7 +30,7 @@ Expr asSinkExpr(DataFlow::Node node) {
result = node.asIndirectArgument()
or
// We want the conversion so we only get one node for the expression
result = node.asConvertedExpr()
result = node.asExpr()
}
module SqlTaintedConfig implements DataFlow::ConfigSig {

View File

@@ -38,7 +38,7 @@ predicate hasSize(HeuristicAllocationExpr alloc, DataFlow::Node n, int state) {
// Compute `delta` as the constant difference between `x` and `x + 1`.
bounded(any(Instruction instr | instr.getUnconvertedResultExpression() = size),
any(LoadInstruction load | load.getUnconvertedResultExpression() = va), delta) and
n.asConvertedExpr() = va.getFullyConverted() and
n.asExpr() = va and
state = delta
)
}
@@ -213,7 +213,7 @@ module StringSizeConfig implements ProductFlow::StateConfigSig {
// we use `state2` to remember that there was an offset (in this case an offset of `1`) added
// to the size of the allocation. This state is then checked in `isSinkPair`.
exists(state1) and
hasSize(bufSource.asConvertedExpr(), sizeSource, state2) and
hasSize(bufSource.asExpr(), sizeSource, state2) and
validState(sizeSource, state2)
}

View File

@@ -26,7 +26,7 @@ import TaintedAllocationSize::PathGraph
* taint sink.
*/
predicate allocSink(HeuristicAllocationExpr alloc, DataFlow::Node sink) {
exists(Expr e | e = sink.asConvertedExpr() |
exists(Expr e | e = sink.asExpr() |
e = alloc.getAChild() and
e.getUnspecifiedType() instanceof IntegralType
)

View File

@@ -206,25 +206,22 @@ class Encrypted extends Expr {
* operation `nsr`.
*/
predicate isSinkSendRecv(DataFlow::Node sink, NetworkSendRecv nsr) {
[sink.asIndirectConvertedExpr(), sink.asConvertedExpr()] = nsr.getDataExpr().getFullyConverted()
[sink.asIndirectExpr(), sink.asExpr()] = nsr.getDataExpr()
}
/**
* Holds if `sink` is a node that is encrypted by `enc`.
*/
predicate isSinkEncrypt(DataFlow::Node sink, Encrypted enc) {
sink.asConvertedExpr() = enc.getFullyConverted()
}
predicate isSinkEncrypt(DataFlow::Node sink, Encrypted enc) { sink.asExpr() = enc }
/**
* Holds if `source` represents a use of a sensitive variable, or data returned by a
* function returning sensitive data.
*/
predicate isSourceImpl(DataFlow::Node source) {
exists(Expr e |
e = source.asConvertedExpr() and
e.getUnconverted().(VariableAccess).getTarget() instanceof SourceVariable and
not e.hasConversion()
exists(VariableAccess e |
e = source.asExpr() and
e.getTarget() instanceof SourceVariable
)
or
source.asExpr().(FunctionCall).getTarget() instanceof SourceFunction

View File

@@ -33,14 +33,6 @@ module ExposedSystemDataConfig implements DataFlow::ConfigSig {
module ExposedSystemData = TaintTracking::Global<ExposedSystemDataConfig>;
from ExposedSystemData::PathNode source, ExposedSystemData::PathNode sink
where
ExposedSystemData::flowPath(source, sink) and
not exists(
DataFlow::Node alt // remove duplicate results on conversions
|
ExposedSystemData::flow(source.getNode(), alt) and
alt.asConvertedExpr() = sink.getNode().asIndirectExpr() and
alt != sink.getNode()
)
where ExposedSystemData::flowPath(source, sink)
select sink, source, sink, "This operation exposes system data from $@.", source,
source.getNode().toString()

View File

@@ -34,7 +34,7 @@ class EnvData extends SystemData {
.regexpMatch(".*(user|host|admin|root|home|path|http|ssl|snmp|sock|port|proxy|pass|token|crypt|key).*")
}
override DataFlow::Node getAnExpr() { result.asIndirectConvertedExpr() = this }
override DataFlow::Node getAnExpr() { result.asIndirectExpr() = this }
override predicate isSensitive() {
this.(EnvironmentRead)
@@ -50,7 +50,7 @@ class EnvData extends SystemData {
class SqlClientInfo extends SystemData {
SqlClientInfo() { this.(FunctionCall).getTarget().hasName("mysql_get_client_info") }
override DataFlow::Node getAnExpr() { result.asIndirectConvertedExpr() = this }
override DataFlow::Node getAnExpr() { result.asIndirectExpr() = this }
override predicate isSensitive() { any() }
}

View File

@@ -70,7 +70,7 @@ class XercesDomParserLibrary extends XmlLibrary {
// sink is the read of the qualifier of a call to `AbstractDOMParser.parse`.
exists(Call call |
call.getTarget().getClassAndName("parse") instanceof AbstractDomParserClass and
call.getQualifier() = node.asIndirectConvertedExpr()
call.getQualifier() = node.asIndirectExpr()
) and
flowstate instanceof XercesFlowState and
not encodeXercesFlowState(flowstate, 1, 1) // safe configuration
@@ -114,7 +114,7 @@ class CreateLSParserLibrary extends XmlLibrary {
// sink is the read of the qualifier of a call to `DOMLSParserClass.parse`.
exists(Call call |
call.getTarget().getClassAndName("parse") instanceof DomLSParserClass and
call.getQualifier() = node.asIndirectConvertedExpr()
call.getQualifier() = node.asIndirectExpr()
) and
flowstate instanceof XercesFlowState and
not encodeXercesFlowState(flowstate, 1, 1) // safe configuration
@@ -155,7 +155,7 @@ class SaxParserLibrary extends XmlLibrary {
// sink is the read of the qualifier of a call to `SAXParser.parse`.
exists(Call call |
call.getTarget().getClassAndName("parse") instanceof SaxParserClass and
call.getQualifier() = node.asIndirectConvertedExpr()
call.getQualifier() = node.asIndirectExpr()
) and
flowstate instanceof XercesFlowState and
not encodeXercesFlowState(flowstate, 1, 1) // safe configuration
@@ -192,7 +192,7 @@ class Sax2XmlReaderLibrary extends XmlLibrary {
// sink is the read of the qualifier of a call to `SAX2XMLReader.parse`.
exists(Call call |
call.getTarget().getClassAndName("parse") instanceof Sax2XmlReader and
call.getQualifier() = node.asIndirectConvertedExpr()
call.getQualifier() = node.asIndirectExpr()
) and
flowstate instanceof XercesFlowState and
not encodeXercesFlowState(flowstate, 1, 1) // safe configuration

View File

@@ -0,0 +1,12 @@
## 0.8.0
### Query Metadata Changes
* The `cpp/double-free` query has been further improved to reduce false positives and its precision has been increased from `medium` to `high`.
* The `cpp/use-after-free` query has been further improved to reduce false positives and its precision has been increased from `medium` to `high`.
### Minor Analysis Improvements
* The queries `cpp/double-free` and `cpp/use-after-free` find fewer false positives
in cases where a non-returning function is called.
* The number of duplicated dataflow paths reported by queries has been significantly reduced.

View File

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

View File

@@ -0,0 +1,68 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Using an object after its lifetime has ended results in undefined behavior.
When an object's lifetime has ended it relinquishes ownership of its resources and the memory it occupied may be reused for other purposes.
If the object is accessed after its lifetime has ended, the program may crash or behave in unexpected ways.
</p>
</overview>
<recommendation>
<p>
Ensure that no object is accessed after its lifetime has ended.
Use RAII ("Resource Acquisition Is Initialization") to manage the lifetime of objects, and avoid manual memory management, if possible.
</p>
</recommendation>
<example>
<p>
The following two examples demonstrate common lifetime violations when working with the C++ standard library.
</p>
<p>
The <code>bad_call_c_api</code> function contains a use of an expired lifetime.
First, a temporary object of type <code>std::string</code> is constructed, and a pointer to its internal buffer is stored in a local variable.
Once the <code>c_str()</code> call returns, the temporary object is destroyed, and the memory pointed to by <code>p</code> is freed.
Thus, any attempt to dereference <code>p</code> inside <code>c_api</code> will result in a use-after-free vulnerability.
The <code>good_call_c_api</code> function contains a fixed version of the first example.
The variable <code>hello</code> is declared as a local variable, and the pointer to its internal buffer is stored in <code>p</code>.
The lifetime of hello outlives the call to <code>c_api</code>, so the pointer stored in <code>p</code> remains valid throughout the call to <code>c_api</code>.
</p>
<sample src="UseAfterExpiredLifetime_c_api_call.cpp" />
<p>
The <code>bad_remove_even_numbers</code> function demonstrates a potential issue with iterator invalidation.
Each C++ standard library container comes with a specification of which operations invalidates iterators pointing into the container.
For example, calling <code>erase</code> on an object of type <code>std::vector&lt;T&gt;</code> invalidates all its iterators, and thus any attempt to dereference the iterator can result in a use-after-free vulnerability.
The <code>good_remove_even_numbers</code> function contains a fixd version of the third example.
The <code>erase</code> function returns an iterator to the element following the last element removed, and this return value is used to ensure that <code>it</code> remains valid after the call to <code>erase</code>.
</p>
<sample src="UseAfterExpiredLifetime_iterator_invalidation.cpp" />
</example>
<references>
<li>CERT C Coding Standard:
<a href="https://wiki.sei.cmu.edu/confluence/display/c/MEM30-C.+Do+not+access+freed+memory">MEM30-C. Do not access freed memory</a>.</li>
<li>
OWASP:
<a href="https://owasp.org/www-community/vulnerabilities/Using_freed_memory">Using freed memory</a>.
</li>
<li>
<a href="https://github.com/isocpp/CppCoreGuidelines/blob/master/docs/Lifetime.pdf">Lifetime safety: Preventing common dangling</a>
</li>
<li>
<a href="https://en.cppreference.com/w/cpp/container">Containers library</a>
</li>
<li>
<a href="https://en.cppreference.com/w/cpp/language/raii">RAII</a>
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,736 @@
/**
* @id cpp/use-after-expired-lifetime
* @name Use of object after its lifetime has ended
* @description Accessing an object after its lifetime has ended can result in security vulnerabilities and undefined behavior.
* @kind problem
* @precision medium
* @problem.severity error
* @tags correctness
* security
* experimental
* external/cwe/cwe-416
*/
import cpp
import semmle.code.cpp.dataflow.DataFlow
import semmle.code.cpp.controlflow.Nullness
class StarOperator extends Operator {
StarOperator() {
this.hasName("operator*") and
this.getNumberOfParameters() = 0
}
}
class IncrementOperator extends Operator {
IncrementOperator() {
this.hasName("operator++") and
this.getNumberOfParameters() = 0
}
}
class StructureDerefOperator extends Operator {
StructureDerefOperator() {
this.hasName("operator->") and
this.getNumberOfParameters() = 0
}
}
class SubscriptOperator extends Operator {
SubscriptOperator() {
this.hasName("operator[]") and
this.getNumberOfParameters() = 1
}
}
/**
* A type which is an `Indirection` type according to the Lifetime profile.
*
* An indirection type is either a `LifetimePointerType` or `LifetimeOwnerType`.
*/
abstract class LifetimeIndirectionType extends Type {
/**
* Gets the `DerefType` of this indirection type.
*
* This corresponds to the owned or pointed to type.
*/
Type getDerefType() {
result = this.(PointerType).getBaseType()
or
result = this.(ReferenceType).getBaseType()
or
exists(MemberFunction mf | mf.getDeclaringType() = this |
result = mf.(StarOperator).getType().getUnspecifiedType().(ReferenceType).getBaseType()
or
result = mf.(SubscriptOperator).getType().getUnspecifiedType().(ReferenceType).getBaseType()
or
result =
mf.(StructureDerefOperator).getType().getUnspecifiedType().(PointerType).getBaseType()
or
mf.getName() = "begin" and
result = mf.getType().(LifetimePointerType).getDerefType()
)
}
}
/**
* A lifetime owner type.
*
* A type which owns another object. For example, `std::unique_ptr`. Includes
* `LifetimeSharedOwnerType`.
*/
class LifetimeOwnerType extends LifetimeIndirectionType {
LifetimeOwnerType() {
// Any shared owner types are also owner types
this instanceof LifetimeSharedOwnerType
or
// This is a container type, or a type with a star operator and..
(
this instanceof ContainerType
or
exists(StarOperator mf | mf.getDeclaringType() = this)
) and
// .. has a "user" provided destructor
exists(Destructor d |
d.getDeclaringType() = this and
not d.isCompilerGenerated()
)
or
// Any specified version of an owner type is also an owner type
this.getUnspecifiedType() instanceof LifetimeOwnerType
or
// Has a field which is a lifetime owner type
this.(Class).getAField().getType() instanceof LifetimeOwnerType
or
// Derived from a public base class which is a owner type
exists(ClassDerivation cd |
cd = this.(Class).getADerivation() and
cd.getBaseClass() instanceof LifetimeOwnerType and
cd.getASpecifier().hasName("public")
)
or
// Lifetime profile treats the following types as owner types, even though they don't fully
// adhere to the requirements above
this.(Class)
.hasQualifiedName("std",
["stack", "queue", "priority_queue", "optional", "variant", "any", "regex"])
or
// Explicit annotation on the type
this.getAnAttribute().getName().matches("gsl::Owner%")
}
}
/**
* A `ContainerType`, based on `[container.requirements]` with some adaptions to capture more real
* world containers.
*/
class ContainerType extends Class {
ContainerType() {
// We use a simpler set of heuristics than the `[container.requirements]`, requiring only
// `begin()`/`end()`/`size()` as the minimum API for something to be considered a "container"
// type
this.getAMemberFunction().getName() = "begin" and
this.getAMemberFunction().getName() = "end" and
this.getAMemberFunction().getName() = "size"
or
// This class is a `ContainerType` if it is constructed from a `ContainerType`. This is
// important, because templates may not have instantiated all the required member functions
exists(TemplateClass tc |
this.isConstructedFrom(tc) and
tc instanceof ContainerType
)
}
}
/**
* A lifetime "shared owner" type.
*
* A shared owner is type that "owns" another object, and shares that ownership with other owners.
* Examples include `std::shared_ptr` along with other reference counting types.
*/
class LifetimeSharedOwnerType extends Type {
LifetimeSharedOwnerType() {
/*
* Find all types which can be dereferenced (i.e. have unary * operator), and are therefore
* likely to be "owner"s or "pointer"s to other objects. We then consider these classes to be
* shared owners if:
* - They can be copied (a unique "owner" type would not be copyable)
* - They can destroyed
*/
// unary * (i.e. can be dereferenced)
exists(StarOperator mf | mf.getDeclaringType() = this) and
// "User" provided destructor
exists(Destructor d |
d.getDeclaringType() = this and
not d.isCompilerGenerated()
) and
// A copy constructor and copy assignment operator
exists(CopyConstructor cc | cc.getDeclaringType() = this and not cc.isDeleted()) and
exists(CopyAssignmentOperator cc | cc.getDeclaringType() = this and not cc.isDeleted())
or
// This class is a `SharedOwnerType` if it is constructed from a `SharedOwnerType`. This is
// important, because templates may not have instantiated all the required member functions
exists(TemplateClass tc |
this.(Class).isConstructedFrom(tc) and
tc instanceof LifetimeSharedOwnerType
)
or
// Any specified version of a shared owner type is also a shared owner type
this.getUnspecifiedType() instanceof LifetimeSharedOwnerType
or
// Has a field which is a lifetime shared owner type
this.(Class).getAField().getType() instanceof LifetimeSharedOwnerType
or
// Derived from a public base class which is a shared owner type
exists(ClassDerivation cd |
cd = this.(Class).getADerivation() and
cd.getBaseClass() instanceof LifetimeSharedOwnerType and
cd.getASpecifier().hasName("public")
)
or
// Lifetime profile treats the following types as shared owner types, even though they don't
// fully adhere to the requirements above
this.(Class).hasQualifiedName("std", "shared_future")
or
// Explicit annotation on the type
this.getAnAttribute().getName().matches("gsl::SharedOwner%")
}
}
/**
* An `IteratorType`, based on `[iterator.requirements]` with some adaptions to capture more real
* world iterators.
*/
class IteratorType extends Type {
IteratorType() {
// We consider anything with an increment and * operator to be sufficient to be an iterator type
exists(StarOperator mf |
mf.getDeclaringType() = this and mf.getType().getUnspecifiedType() instanceof ReferenceType
) and
exists(IncrementOperator op |
op.getDeclaringType() = this and op.getType().(ReferenceType).getBaseType() = this
)
or
// Along with unspecified versions of the types above
this.getUnspecifiedType() instanceof IteratorType
}
}
/**
* A lifetime pointer type.
*
* A type which points to another object. For example, `std::unique_ptr`. Includes
* `LifetimeSharedOwnerType`.
*/
class LifetimePointerType extends LifetimeIndirectionType {
LifetimePointerType() {
this instanceof IteratorType
or
this instanceof PointerType
or
this instanceof ReferenceType
or
// A shared owner type is a pointer type, but an owner type is not.
this instanceof LifetimeSharedOwnerType and
not this instanceof LifetimeOwnerType
or
this.(Class).hasQualifiedName("std", "reference_wrapper")
or
exists(Class vectorBool, UserType reference |
vectorBool.hasQualifiedName("std", "vector") and
vectorBool.getATemplateArgument() instanceof BoolType and
reference.hasName("reference") and
reference.getDeclaringType() = vectorBool and
this = reference.getUnderlyingType()
)
or
// Any specified version of a pointer type is also an owner type
this.getUnspecifiedType() instanceof LifetimePointerType
or
// Has a field which is a lifetime pointer type
this.(Class).getAField().getType() instanceof LifetimePointerType
or
// Derived from a public base class which is a pointer type
exists(ClassDerivation cd |
cd = this.(Class).getADerivation() and
cd.getBaseClass() instanceof LifetimePointerType and
cd.getASpecifier().hasName("public")
)
or
// Explicit annotation on the type
this.getAnAttribute().getName().matches("gsl::Pointer%")
}
}
/** A full expression as defined in [intro.execution] of N3797. */
class FullExpr extends Expr {
FullExpr() {
// A full-expression is not a subexpression
not exists(Expr p | this.getParent() = p)
or
// A sub-expression that is an unevaluated operand
this.isUnevaluated()
}
}
/** Gets the `FullExpression` scope of the `TemporaryObjectExpr`. */
FullExpr getTemporaryObjectExprScope(TemporaryObjectExpr toe) {
result = toe.getUnconverted().getParent*()
}
/**
* See `LifetimeLocalVariable` and subclasses.
*/
private newtype TLifetimeLocalVariable =
TLocalScopeVariable(LocalScopeVariable lsv) { not lsv.isStatic() } or
TTemporaryObject(TemporaryObjectExpr toe)
/*
* Note, the lifetime profile also supports locally initialized _aggregates_, which we could
* support with something like this:
* ```
* TAggregateField(TLocalScopeVariable base, Field f) {
* exists(LocalScopeVariable lsv |
* base = TLocalScopeVariable(lsv) and
* lsv.getType() = f.getDeclaringType() and
* lsv.getType() instanceof LifetimeAggregateType
* )
* }
* ```
*/
/**
* A "LocalVariable" as defined by the lifetime profile.
*
* This includes newly introduced objects with a local scope.
*/
class LifetimeLocalVariable extends TLifetimeLocalVariable {
string toString() { none() } // specified in sub-classes
Type getType() { none() }
}
/**
* A parameter or `LocalVariable`, used as a `LifetimeLocalVariable`
*/
class LifetimeLocalScopeVariable extends TLocalScopeVariable, LifetimeLocalVariable {
LocalScopeVariable getVariable() { this = TLocalScopeVariable(result) }
override Type getType() { result = this.getVariable().getType() }
override string toString() { result = this.getVariable().toString() }
}
/**
* A temporary object used as a `LifetimeLocalVariable`.
*/
class LifetimeTemporaryObject extends TTemporaryObject, LifetimeLocalVariable {
TemporaryObjectExpr getTemporaryObjectExpr() { this = TTemporaryObject(result) }
override Type getType() { result = this.getTemporaryObjectExpr().getType() }
override string toString() { result = this.getTemporaryObjectExpr().toString() }
}
newtype TInvalidReason =
/** LifetimeLocalVariable is invalid because it hasn't been initialized. */
TUninitialized(DeclStmt ds, Variable v) { ds.getADeclaration() = v } or
/** LifetimeLocalVariable is invalid because it points to a variable which has gone out of scope. */
TVariableOutOfScope(LocalScopeVariable v, ControlFlowNode cfn) { goesOutOfScopeAt(v, cfn) } or
/** LifetimeLocalVariable is invalid because it points to a temporary object expression which has gone out of scope. */
TTemporaryOutOfScope(TemporaryObjectExpr toe) or
/** LifetimeLocalVariable is invalid because it points to data held by an owner which has since been invalidated. */
TOwnerModified(FunctionCall fc)
/**
* A reason why a pointer may be invalid.
*/
class InvalidReason extends TInvalidReason {
/** Holds if this reason indicates the pointer is accessed before the lifetime of an object began. */
predicate isBeforeLifetime() { this instanceof TUninitialized }
/** Holds if this reason indicates the pointer is accessed after the lifetime of an object has finished. */
predicate isAfterLifetime() { not this.isBeforeLifetime() }
/** Gets a description of the reason why this pointer may be invalid. */
string getDescription() {
exists(DeclStmt ds, Variable v |
this = TUninitialized(ds, v) and
result = "variable " + v.getName() + " was never initialized"
)
or
exists(LocalScopeVariable v, ControlFlowNode cfn |
this = TVariableOutOfScope(v, cfn) and
result = "variable " + v.getName() + " went out of scope"
)
or
exists(TemporaryObjectExpr toe |
this = TTemporaryOutOfScope(toe) and
result = "temporary object went out of scope"
)
or
exists(FunctionCall fc |
this = TOwnerModified(fc) and
result = "owner type was modified"
)
}
string toString() { result = this.getDescription() }
/** Get an element that explains the reason for the invalid determination. */
private Element getExplanatoryElement() {
exists(DeclStmt ds |
this = TUninitialized(ds, _) and
result = ds
)
or
exists(ControlFlowNode cfn |
this = TVariableOutOfScope(_, cfn) and
result = cfn
)
or
exists(TemporaryObjectExpr toe |
this = TTemporaryOutOfScope(toe) and
result = getTemporaryObjectExprScope(toe)
)
or
exists(FunctionCall fc |
this = TOwnerModified(fc) and
result = fc
)
}
/**
* Provides a `message` for use in alert messages.
*
* The message will contain a `$@` placeholder, for which `explanation` and `explanationDesc` are
* the placeholder components which should be added as extra columns.
*/
predicate hasMessage(string message, Element explanation, string explanationDesc) {
message = "because the " + this.getDescription() + " $@." and
explanation = this.getExplanatoryElement() and
explanationDesc = "here"
}
}
/**
* A reason why a pointer may be null.
*/
newtype TNullReason =
// Null because the `NullValue` was assigned
TNullAssignment(NullValue e)
class NullReason extends TNullReason {
/** Gets a description of the reason why this pointer may be null. */
string getDescription() {
exists(NullValue nv |
this = TNullAssignment(nv) and
result = "null value was assigned"
)
}
string toString() { result = this.getDescription() }
}
/** See `PSetEntry` and subclasses. */
newtype TPSetEntry =
/** Points to a lifetime local variable. */
PSetVar(LifetimeLocalVariable lv) or
/** Points to a lifetime local variable that represents an owner type. */
PSetOwner(LifetimeLocalVariable lv, int level) {
level = [0 .. 2] and lv.getType() instanceof LifetimeOwnerType
} or
/** Points to a global variable. */
PSetGlobal() or
/** A null pointer. */
PSetNull(NullReason nr) or
/** An invalid pointer, for the given reason. */
PSetInvalid(InvalidReason ir) or
/** An unknown pointer. */
PSetUnknown()
/**
* An entry in the points-to set for a particular "LifetimeLocalVariable" at a particular
* point in the program.
*/
class PSetEntry extends TPSetEntry {
string toString() {
exists(LifetimeLocalVariable lv |
this = PSetVar(lv) and
result = "Var(" + lv.toString() + ")"
)
or
this = PSetGlobal() and result = "global"
or
exists(LifetimeLocalVariable lv, int level |
this = PSetOwner(lv, level) and
result = "Owner(" + lv.toString() + "," + level + ")"
)
or
exists(NullReason nr | this = PSetNull(nr) and result = "null because" + nr)
or
exists(InvalidReason ir | this = PSetInvalid(ir) and result = "invalid because " + ir)
or
this = PSetUnknown() and result = "unknown"
}
}
/**
* The "pmap" or "points-to map" for a "lifetime" local variable.
*/
predicate pointsToMap(ControlFlowNode cfn, LifetimeLocalVariable lv, PSetEntry ps) {
if isPSetReassigned(cfn, lv)
then ps = getAnAssignedPSetEntry(cfn, lv)
else
// Exclude unknown for now
exists(ControlFlowNode pred, PSetEntry prevPSet |
pred = cfn.getAPredecessor() and
pointsToMap(pred, lv, prevPSet) and
// Not PSetNull() and a non-null successor of a null check
not exists(AnalysedExpr ae |
ps = PSetNull(_) and
cfn = ae.getNonNullSuccessor(lv.(LifetimeLocalScopeVariable).getVariable())
) and
// lv is not out of scope at this node
not goesOutOfScopeAt(lv.(LifetimeLocalScopeVariable).getVariable(), cfn)
|
// Propagate a PSetEntry from the predecessor node, so long as the
// PSetEntry is not invalidated at this node
ps = prevPSet and
not exists(getAnInvalidation(prevPSet, cfn))
or
// Replace prevPSet with an invalidation reason at this node
ps = getAnInvalidation(prevPSet, cfn)
)
}
private predicate isPSetReassigned(ControlFlowNode cfn, LifetimeLocalVariable lv) {
exists(DeclStmt ds |
cfn = ds and
ds.getADeclaration() = lv.(LifetimeLocalScopeVariable).getVariable() and
lv.getType() instanceof PointerType
)
or
exists(TemporaryObjectExpr toe |
toe = lv.(LifetimeTemporaryObject).getTemporaryObjectExpr() and
cfn = toe
)
or
// Assigned a value
cfn = lv.(LifetimeLocalScopeVariable).getVariable().getAnAssignedValue()
or
// If the address of a local var is passed to a function, then assume it initializes it
exists(Call fc, AddressOfExpr aoe |
cfn = aoe and
fc.getAnArgument() = aoe and
lv.(LifetimeLocalScopeVariable).getVariable() = aoe.getOperand().(VariableAccess).getTarget()
)
}
/** Is the `lv` assigned or reassigned at this ControlFlowNode `cfn`. */
private PSetEntry getAnAssignedPSetEntry(ControlFlowNode cfn, LifetimeLocalVariable lv) {
exists(DeclStmt ds |
cfn = ds and
ds.getADeclaration() = lv.(LifetimeLocalScopeVariable).getVariable()
|
lv.getType() instanceof PointerType and
result = PSetInvalid(TUninitialized(ds, lv.(LifetimeLocalScopeVariable).getVariable()))
)
or
exists(TemporaryObjectExpr toe |
toe = lv.(LifetimeTemporaryObject).getTemporaryObjectExpr() and
cfn = toe and
result = PSetVar(lv)
)
or
// Assigned a value
exists(Expr assign |
assign = lv.(LifetimeLocalScopeVariable).getVariable().getAnAssignedValue() and
cfn = assign
|
if isKnownAssignmentType(assign)
then knownAssignmentType(assign, result)
else result = PSetUnknown()
)
or
// If the address of a local var is passed to a function, then assume it initializes it
exists(Call fc, AddressOfExpr aoe |
cfn = aoe and
fc.getAnArgument() = aoe and
lv.(LifetimeLocalScopeVariable).getVariable() = aoe.getOperand().(VariableAccess).getTarget() and
result = PSetUnknown()
)
}
predicate isKnownAssignmentType(Expr assign) {
assign = any(LocalScopeVariable lv).getAnAssignedValue() and
(
exists(Variable v | v = assign.(AddressOfExpr).getOperand().(VariableAccess).getTarget() |
v instanceof LocalScopeVariable
or
v instanceof GlobalVariable
)
or
// Assignment of a previous variable
exists(VariableAccess va |
va = assign and
va.getTarget().(LocalScopeVariable).getType() instanceof LifetimePointerType
)
or
assign instanceof NullValue
or
exists(FunctionCall fc |
assign = fc and
fc.getNumberOfArguments() = 0 and
fc.getType() instanceof LifetimePointerType
|
// A function call is a product of its inputs (just handle qualifiers at the moment)
exists(LifetimeLocalVariable lv |
lv = TTemporaryObject(fc.getQualifier().getConversion())
or
lv = TLocalScopeVariable(fc.getQualifier().(VariableAccess).getTarget())
|
lv.getType() instanceof LifetimePointerType
or
lv.getType() instanceof LifetimeOwnerType
)
)
)
}
/**
* An expression which is assigned to a `LocalScopeVariable`, which has a known PSet value i.e. not
* an "Unknown" PSet value.
*/
predicate knownAssignmentType(Expr assign, PSetEntry ps) {
assign = any(LocalScopeVariable lv).getAnAssignedValue() and
(
// The assigned value is `&v`
exists(Variable v | v = assign.(AddressOfExpr).getOperand().(VariableAccess).getTarget() |
v instanceof LocalScopeVariable and
(
// If the variable we are taking the address of is a reference type, then we are really
// taking the address of whatever the reference type "points-to". Use the `pointsToMap`
// to determine viable `LifetimeLocalScopeVariable`s this could point to.
if v.getType() instanceof ReferenceType
then
pointsToMap(assign.getAPredecessor(),
any(LifetimeLocalScopeVariable lv | lv.getVariable() = v), ps)
else
// This assignment points-to `v` itself.
ps = PSetVar(TLocalScopeVariable(v))
)
or
// If the variable we are taking the address of is a reference variable, then this points-to
// a global. If the variable we taking the address of is a reference type, we need to consider
// that it might point-to a global, even if it is a LocalScopeVariable (this case is required
// so that we still produce a result even if the pointsToMap is empty for `lv`).
(v instanceof GlobalVariable or v.getType() instanceof ReferenceType) and
ps = PSetGlobal()
)
or
// Assignment of a previous variable
exists(VariableAccess va |
va = assign and
va.getTarget().(LocalScopeVariable).getType() instanceof LifetimePointerType and
// PSet of that become PSet of this
pointsToMap(assign.getAPredecessor(),
any(LifetimeLocalScopeVariable lv | lv.getVariable() = va.getTarget()), ps)
)
or
// The `NullValue` class covers all types of null equivalent expressions. This case also handles
// default and value initialization, where an "implicit" null value expression is added by the
// extractor
assign instanceof NullValue and ps = PSetNull(TNullAssignment(assign))
or
exists(FunctionCall fc |
assign = fc and
// If the assignment is being converted via a ReferenceDereferenceExpr, then
// we are essentially copying the original object
not assign.getFullyConverted() instanceof ReferenceDereferenceExpr and
fc.getNumberOfArguments() = 0 and
fc.getType() instanceof LifetimePointerType
|
// A function call is a product of its inputs (just handle qualifiers at the moment)
exists(LifetimeLocalVariable lv |
lv = TTemporaryObject(fc.getQualifier().getConversion())
or
lv = TLocalScopeVariable(fc.getQualifier().(VariableAccess).getTarget())
|
ps = PSetVar(lv) and lv.getType() instanceof LifetimePointerType
or
ps = PSetOwner(lv, 0) and lv.getType() instanceof LifetimeOwnerType
)
)
)
}
/**
* Holds if `cfn` is a node that occur directly after the local scope variable `lv` has gone out of scope.
*/
predicate goesOutOfScopeAt(LocalScopeVariable lv, ControlFlowNode cfn) {
exists(BlockStmt scope |
scope = lv.getParentScope() and
scope.getAChild+() = cfn.getAPredecessor().getEnclosingStmt() and
not scope.getAChild+() = cfn.getEnclosingStmt()
)
}
PSetInvalid getAnInvalidation(PSetEntry ps, ControlFlowNode cfn) {
exists(LifetimeLocalScopeVariable lv | ps = PSetVar(lv) |
result = PSetInvalid(TVariableOutOfScope(lv.getVariable(), cfn))
)
or
exists(LifetimeLocalScopeVariable lv | ps = PSetOwner(lv, _) |
result = PSetInvalid(TVariableOutOfScope(lv.getVariable(), cfn))
or
exists(FunctionCall fc |
fc = cfn and
fc.getQualifier() = lv.getVariable().getAnAccess() and
not fc.getTarget() instanceof ConstMemberFunction and
// non-const versions of begin and end should nevertheless be considered const
not fc.getTarget().hasName(["begin", "end"]) and
result = PSetInvalid(TOwnerModified(fc))
)
)
or
// temporary objects end after the full expression
exists(LifetimeTemporaryObject lto |
ps = PSetVar(lto)
or
ps = PSetOwner(lto, _)
|
cfn = lto.getTemporaryObjectExpr().getUnconverted().getParent*().(FullExpr).getASuccessor() and
result = PSetInvalid(TTemporaryOutOfScope(lto.getTemporaryObjectExpr()))
)
}
/**
* An expression which is dereferenced and may be an "invalid" value.
*/
class InvalidDereference extends VariableAccess {
InvalidReason ir;
InvalidDereference() {
// The local points to map suggests this points to an invalid set
exists(LocalScopeVariable lv |
lv = this.getTarget() and
pointsToMap(this, TLocalScopeVariable(lv), PSetInvalid(ir))
)
}
/** Gets a reason why this dereference could point to an invalid value. */
InvalidReason getAnInvalidReason() { result = ir }
}
from
InvalidDereference e, Element explanation, string explanationDesc, InvalidReason ir,
string invalidMessage
where
ir = e.getAnInvalidReason() and
ir.isAfterLifetime() and
ir.hasMessage(invalidMessage, explanation, explanationDesc)
select e,
e.(VariableAccess).getTarget().getName() + " is dereferenced here but accesses invalid memory " +
invalidMessage, explanation, explanationDesc

View File

@@ -0,0 +1,14 @@
void c_api(const char*);
void bad_call_c_api() {
// BAD: the memory returned by `c_str()` is freed when the temporary string is destroyed
const char* p = std::string("hello").c_str();
c_api(p);
}
void good_call_c_api() {
// GOOD: the "hello" string outlives the pointer returned by `c_str()`, so it's safe to pass it to `c_api()`
std::string hello("hello");
const char* p = hello.c_str();
c_api(p);
}

View File

@@ -0,0 +1,19 @@
void bad_remove_even_numbers(std::vector<int>& v) {
// BAD: the iterator is invalidated after the call to `erase`.
for(std::vector<int>::iterator it = v.begin(); it != v.end(); ++it) {
if(*it % 2 == 0) {
v.erase(it);
}
}
}
void good_remove_even_numbers(std::vector<int>& v) {
// GOOD: `erase` returns the iterator to the next element.
for(std::vector<int>::iterator it = v.begin(); it != v.end(); ) {
if(*it % 2 == 0) {
it = v.erase(it);
} else {
++it;
}
}
}

View File

@@ -1,12 +1,12 @@
name: codeql/cpp-queries
version: 0.7.5
groups:
version: 0.8.0
groups:
- cpp
- queries
dependencies:
codeql/cpp-all: ${workspace}
codeql/suite-helpers: ${workspace}
codeql/util: ${workspace}
codeql/cpp-all: ${workspace}
codeql/suite-helpers: ${workspace}
codeql/util: ${workspace}
suites: codeql-suites
extractor: cpp
defaultSuiteFile: codeql-suites/cpp-code-scanning.qls

View File

@@ -1,2 +1 @@
| printf.cpp:5:5:5:10 | call to printf | Argument to printf isn't hard-coded. |
| printf.cpp:6:5:6:10 | call to printf | Argument to printf isn't hard-coded. |

View File

@@ -1,58 +1,28 @@
edges
| test.cpp:13:33:13:37 | ... * ... | test.cpp:13:33:13:37 | ... * ... |
| test.cpp:15:31:15:35 | ... * ... | test.cpp:15:31:15:35 | ... * ... |
| test.cpp:19:34:19:38 | ... * ... | test.cpp:19:34:19:38 | ... * ... |
| test.cpp:22:17:22:21 | ... * ... | test.cpp:23:33:23:37 | size1 |
| test.cpp:22:17:22:21 | ... * ... | test.cpp:23:33:23:37 | size1 |
| test.cpp:37:24:37:27 | size | test.cpp:37:46:37:49 | size |
| test.cpp:45:36:45:40 | ... * ... | test.cpp:37:24:37:27 | size |
| test.cpp:45:36:45:40 | ... * ... | test.cpp:45:36:45:40 | ... * ... |
| test.cpp:45:36:45:40 | ... * ... | test.cpp:45:36:45:40 | ... * ... |
| test.cpp:46:36:46:40 | ... * ... | test.cpp:46:36:46:40 | ... * ... |
nodes
| test.cpp:13:33:13:37 | ... * ... | semmle.label | ... * ... |
| test.cpp:13:33:13:37 | ... * ... | semmle.label | ... * ... |
| test.cpp:13:33:13:37 | ... * ... | semmle.label | ... * ... |
| test.cpp:15:31:15:35 | ... * ... | semmle.label | ... * ... |
| test.cpp:15:31:15:35 | ... * ... | semmle.label | ... * ... |
| test.cpp:15:31:15:35 | ... * ... | semmle.label | ... * ... |
| test.cpp:19:34:19:38 | ... * ... | semmle.label | ... * ... |
| test.cpp:19:34:19:38 | ... * ... | semmle.label | ... * ... |
| test.cpp:19:34:19:38 | ... * ... | semmle.label | ... * ... |
| test.cpp:22:17:22:21 | ... * ... | semmle.label | ... * ... |
| test.cpp:22:17:22:21 | ... * ... | semmle.label | ... * ... |
| test.cpp:23:33:23:37 | size1 | semmle.label | size1 |
| test.cpp:30:27:30:31 | ... * ... | semmle.label | ... * ... |
| test.cpp:31:27:31:31 | ... * ... | semmle.label | ... * ... |
| test.cpp:30:18:30:32 | ... * ... | semmle.label | ... * ... |
| test.cpp:31:18:31:32 | ... * ... | semmle.label | ... * ... |
| test.cpp:37:24:37:27 | size | semmle.label | size |
| test.cpp:37:46:37:49 | size | semmle.label | size |
| test.cpp:45:36:45:40 | ... * ... | semmle.label | ... * ... |
| test.cpp:45:36:45:40 | ... * ... | semmle.label | ... * ... |
| test.cpp:45:36:45:40 | ... * ... | semmle.label | ... * ... |
| test.cpp:45:36:45:40 | ... * ... | semmle.label | ... * ... |
| test.cpp:46:36:46:40 | ... * ... | semmle.label | ... * ... |
| test.cpp:46:36:46:40 | ... * ... | semmle.label | ... * ... |
| test.cpp:46:36:46:40 | ... * ... | semmle.label | ... * ... |
subpaths
#select
| test.cpp:13:33:13:37 | ... * ... | test.cpp:13:33:13:37 | ... * ... | test.cpp:13:33:13:37 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:13:33:13:37 | ... * ... | multiplication |
| test.cpp:13:33:13:37 | ... * ... | test.cpp:13:33:13:37 | ... * ... | test.cpp:13:33:13:37 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:13:33:13:37 | ... * ... | multiplication |
| test.cpp:13:33:13:37 | ... * ... | test.cpp:13:33:13:37 | ... * ... | test.cpp:13:33:13:37 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:13:33:13:37 | ... * ... | multiplication |
| test.cpp:15:31:15:35 | ... * ... | test.cpp:15:31:15:35 | ... * ... | test.cpp:15:31:15:35 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:15:31:15:35 | ... * ... | multiplication |
| test.cpp:15:31:15:35 | ... * ... | test.cpp:15:31:15:35 | ... * ... | test.cpp:15:31:15:35 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:15:31:15:35 | ... * ... | multiplication |
| test.cpp:15:31:15:35 | ... * ... | test.cpp:15:31:15:35 | ... * ... | test.cpp:15:31:15:35 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:15:31:15:35 | ... * ... | multiplication |
| test.cpp:19:34:19:38 | ... * ... | test.cpp:19:34:19:38 | ... * ... | test.cpp:19:34:19:38 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:19:34:19:38 | ... * ... | multiplication |
| test.cpp:19:34:19:38 | ... * ... | test.cpp:19:34:19:38 | ... * ... | test.cpp:19:34:19:38 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:19:34:19:38 | ... * ... | multiplication |
| test.cpp:19:34:19:38 | ... * ... | test.cpp:19:34:19:38 | ... * ... | test.cpp:19:34:19:38 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:19:34:19:38 | ... * ... | multiplication |
| test.cpp:23:33:23:37 | size1 | test.cpp:22:17:22:21 | ... * ... | test.cpp:23:33:23:37 | size1 | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:22:17:22:21 | ... * ... | multiplication |
| test.cpp:23:33:23:37 | size1 | test.cpp:22:17:22:21 | ... * ... | test.cpp:23:33:23:37 | size1 | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:22:17:22:21 | ... * ... | multiplication |
| test.cpp:30:27:30:31 | ... * ... | test.cpp:30:27:30:31 | ... * ... | test.cpp:30:27:30:31 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:30:27:30:31 | ... * ... | multiplication |
| test.cpp:31:27:31:31 | ... * ... | test.cpp:31:27:31:31 | ... * ... | test.cpp:31:27:31:31 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:31:27:31:31 | ... * ... | multiplication |
| test.cpp:37:46:37:49 | size | test.cpp:45:36:45:40 | ... * ... | test.cpp:37:46:37:49 | size | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:45:36:45:40 | ... * ... | multiplication |
| test.cpp:30:18:30:32 | ... * ... | test.cpp:30:18:30:32 | ... * ... | test.cpp:30:18:30:32 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:30:18:30:32 | ... * ... | multiplication |
| test.cpp:31:18:31:32 | ... * ... | test.cpp:31:18:31:32 | ... * ... | test.cpp:31:18:31:32 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:31:18:31:32 | ... * ... | multiplication |
| test.cpp:37:46:37:49 | size | test.cpp:45:36:45:40 | ... * ... | test.cpp:37:46:37:49 | size | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:45:36:45:40 | ... * ... | multiplication |
| test.cpp:45:36:45:40 | ... * ... | test.cpp:45:36:45:40 | ... * ... | test.cpp:45:36:45:40 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:45:36:45:40 | ... * ... | multiplication |
| test.cpp:45:36:45:40 | ... * ... | test.cpp:45:36:45:40 | ... * ... | test.cpp:45:36:45:40 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:45:36:45:40 | ... * ... | multiplication |
| test.cpp:45:36:45:40 | ... * ... | test.cpp:45:36:45:40 | ... * ... | test.cpp:45:36:45:40 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:45:36:45:40 | ... * ... | multiplication |
| test.cpp:46:36:46:40 | ... * ... | test.cpp:46:36:46:40 | ... * ... | test.cpp:46:36:46:40 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:46:36:46:40 | ... * ... | multiplication |
| test.cpp:46:36:46:40 | ... * ... | test.cpp:46:36:46:40 | ... * ... | test.cpp:46:36:46:40 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:46:36:46:40 | ... * ... | multiplication |
| test.cpp:46:36:46:40 | ... * ... | test.cpp:46:36:46:40 | ... * ... | test.cpp:46:36:46:40 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:46:36:46:40 | ... * ... | multiplication |

View File

@@ -1,6 +1,5 @@
edges
| test.cpp:45:18:45:23 | buffer | test.cpp:45:7:45:10 | func indirection |
| test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode |
| test.cpp:74:24:74:30 | medical | test.cpp:78:24:78:27 | temp |
| test.cpp:74:24:74:30 | medical | test.cpp:81:22:81:28 | medical |
| test.cpp:77:16:77:22 | medical | test.cpp:78:24:78:27 | temp |
@@ -8,23 +7,12 @@ edges
| test.cpp:81:17:81:20 | call to func | test.cpp:82:24:82:28 | buff5 |
| test.cpp:81:22:81:28 | medical | test.cpp:45:18:45:23 | buffer |
| test.cpp:81:22:81:28 | medical | test.cpp:81:17:81:20 | call to func |
| test.cpp:96:37:96:46 | theZipcode | test.cpp:96:37:96:46 | theZipcode |
| test.cpp:96:37:96:46 | theZipcode | test.cpp:96:37:96:46 | theZipcode |
| test.cpp:96:37:96:46 | theZipcode | test.cpp:99:42:99:51 | theZipcode |
| test.cpp:96:37:96:46 | theZipcode | test.cpp:99:42:99:51 | theZipcode |
| test.cpp:96:37:96:46 | theZipcode | test.cpp:99:42:99:51 | theZipcode |
| test.cpp:96:37:96:46 | theZipcode | test.cpp:99:42:99:51 | theZipcode |
| test.cpp:96:37:96:46 | theZipcode | test.cpp:99:42:99:51 | theZipcode |
| test.cpp:96:37:96:46 | theZipcode | test.cpp:99:42:99:51 | theZipcode |
| test.cpp:99:42:99:51 | theZipcode | test.cpp:99:42:99:51 | theZipcode |
| test.cpp:99:61:99:70 | theZipcode | test.cpp:99:42:99:51 | theZipcode |
| test.cpp:99:61:99:70 | theZipcode | test.cpp:99:42:99:51 | theZipcode |
nodes
| test.cpp:45:7:45:10 | func indirection | semmle.label | func indirection |
| test.cpp:45:18:45:23 | buffer | semmle.label | buffer |
| test.cpp:57:9:57:18 | theZipcode | semmle.label | theZipcode |
| test.cpp:57:9:57:18 | theZipcode | semmle.label | theZipcode |
| test.cpp:57:9:57:18 | theZipcode | semmle.label | theZipcode |
| test.cpp:74:24:74:30 | medical | semmle.label | medical |
| test.cpp:74:24:74:30 | medical | semmle.label | medical |
| test.cpp:77:16:77:22 | medical | semmle.label | medical |
@@ -34,19 +22,12 @@ nodes
| test.cpp:82:24:82:28 | buff5 | semmle.label | buff5 |
| test.cpp:96:37:96:46 | theZipcode | semmle.label | theZipcode |
| test.cpp:96:37:96:46 | theZipcode | semmle.label | theZipcode |
| test.cpp:96:37:96:46 | theZipcode | semmle.label | theZipcode |
| test.cpp:96:37:96:46 | theZipcode | semmle.label | theZipcode |
| test.cpp:99:42:99:51 | theZipcode | semmle.label | theZipcode |
| test.cpp:99:42:99:51 | theZipcode | semmle.label | theZipcode |
| test.cpp:99:42:99:51 | theZipcode | semmle.label | theZipcode |
| test.cpp:99:61:99:70 | theZipcode | semmle.label | theZipcode |
| test.cpp:99:61:99:70 | theZipcode | semmle.label | theZipcode |
subpaths
| test.cpp:81:22:81:28 | medical | test.cpp:45:18:45:23 | buffer | test.cpp:45:7:45:10 | func indirection | test.cpp:81:17:81:20 | call to func |
#select
| test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:57:9:57:18 | theZipcode | this source of private data. |
| test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:57:9:57:18 | theZipcode | this source of private data. |
| test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:57:9:57:18 | theZipcode | this source of private data. |
| test.cpp:74:24:74:30 | medical | test.cpp:74:24:74:30 | medical | test.cpp:74:24:74:30 | medical | This write into the external location 'medical' may contain unencrypted data from $@. | test.cpp:74:24:74:30 | medical | this source of private data. |
| test.cpp:78:24:78:27 | temp | test.cpp:74:24:74:30 | medical | test.cpp:78:24:78:27 | temp | This write into the external location 'temp' may contain unencrypted data from $@. | test.cpp:74:24:74:30 | medical | this source of private data. |
| test.cpp:78:24:78:27 | temp | test.cpp:77:16:77:22 | medical | test.cpp:78:24:78:27 | temp | This write into the external location 'temp' may contain unencrypted data from $@. | test.cpp:77:16:77:22 | medical | this source of private data. |
@@ -54,14 +35,6 @@ subpaths
| test.cpp:82:24:82:28 | buff5 | test.cpp:77:16:77:22 | medical | test.cpp:82:24:82:28 | buff5 | This write into the external location 'buff5' may contain unencrypted data from $@. | test.cpp:77:16:77:22 | medical | this source of private data. |
| test.cpp:82:24:82:28 | buff5 | test.cpp:81:22:81:28 | medical | test.cpp:82:24:82:28 | buff5 | This write into the external location 'buff5' may contain unencrypted data from $@. | test.cpp:81:22:81:28 | medical | this source of private data. |
| test.cpp:96:37:96:46 | theZipcode | test.cpp:96:37:96:46 | theZipcode | test.cpp:96:37:96:46 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:96:37:96:46 | theZipcode | this source of private data. |
| test.cpp:96:37:96:46 | theZipcode | test.cpp:96:37:96:46 | theZipcode | test.cpp:96:37:96:46 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:96:37:96:46 | theZipcode | this source of private data. |
| test.cpp:96:37:96:46 | theZipcode | test.cpp:96:37:96:46 | theZipcode | test.cpp:96:37:96:46 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:96:37:96:46 | theZipcode | this source of private data. |
| test.cpp:99:42:99:51 | theZipcode | test.cpp:96:37:96:46 | theZipcode | test.cpp:99:42:99:51 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:96:37:96:46 | theZipcode | this source of private data. |
| test.cpp:99:42:99:51 | theZipcode | test.cpp:96:37:96:46 | theZipcode | test.cpp:99:42:99:51 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:96:37:96:46 | theZipcode | this source of private data. |
| test.cpp:99:42:99:51 | theZipcode | test.cpp:96:37:96:46 | theZipcode | test.cpp:99:42:99:51 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:96:37:96:46 | theZipcode | this source of private data. |
| test.cpp:99:42:99:51 | theZipcode | test.cpp:96:37:96:46 | theZipcode | test.cpp:99:42:99:51 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:96:37:96:46 | theZipcode | this source of private data. |
| test.cpp:99:42:99:51 | theZipcode | test.cpp:99:42:99:51 | theZipcode | test.cpp:99:42:99:51 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:99:42:99:51 | theZipcode | this source of private data. |
| test.cpp:99:42:99:51 | theZipcode | test.cpp:99:42:99:51 | theZipcode | test.cpp:99:42:99:51 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:99:42:99:51 | theZipcode | this source of private data. |
| test.cpp:99:42:99:51 | theZipcode | test.cpp:99:42:99:51 | theZipcode | test.cpp:99:42:99:51 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:99:42:99:51 | theZipcode | this source of private data. |
| test.cpp:99:42:99:51 | theZipcode | test.cpp:99:61:99:70 | theZipcode | test.cpp:99:42:99:51 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:99:61:99:70 | theZipcode | this source of private data. |
| test.cpp:99:42:99:51 | theZipcode | test.cpp:99:61:99:70 | theZipcode | test.cpp:99:42:99:51 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:99:61:99:70 | theZipcode | this source of private data. |

View File

@@ -86,3 +86,10 @@ bool bok_is_void2 = __is_void(int);
bool bok_is_volatile1 = __is_volatile(volatile int);
bool bok_is_volatile2 = __is_volatile(int);
struct S2 {
S2() {}
};
bool bok_is_trivial1 = __is_trivial(int);
bool bok_is_trivial2 = __is_trivial(S2);

View File

@@ -121,6 +121,10 @@
| clang.cpp:87:25:87:51 | volatile int | | <none> |
| clang.cpp:88:25:88:42 | __is_volatile | int | 0 |
| clang.cpp:88:25:88:42 | int | | <none> |
| clang.cpp:94:24:94:40 | __is_trivial | int | 1 |
| clang.cpp:94:24:94:40 | int | | <none> |
| clang.cpp:95:24:95:39 | S2 | | <none> |
| clang.cpp:95:24:95:39 | __is_trivial | S2 | 0 |
| file://:0:0:0:0 | 0 | | 0 |
| file://:0:0:0:0 | 1 | | 1 |
| file://:0:0:0:0 | 2 | | 2 |

View File

@@ -1,4 +1,4 @@
WARNING: Module TaintedWithPath has been deprecated and may be removed in future (tainted.ql:9,8-47)
WARNING: Predicate tainted has been deprecated and may be removed in future (tainted.ql:20,49-74)
failures
testFailures
failures

View File

@@ -97,9 +97,9 @@ int main(int argc, char *argv[]) {
char*** p = &argv; // $ ast,ir-path
sink(*p[0]); // $ ast ir-sink=96:26 ir-sink=98:18
sink(*p[0]); // $ ast ir-sink=96:26 ir-sink=98:18 ir-sink=98:17
calls_sink_with_argv(*p[i]); // $ ir-path=96:26 ir-path=98:18 MISSING:ast
calls_sink_with_argv(*p[i]); // $ ir-path=96:26 ir-path=98:18 ir-path=98:17 MISSING:ast
sink(*(argv + 1)); // $ ast ir-path ir-sink

View File

@@ -4,7 +4,6 @@ uniqueType
uniqueNodeLocation
missingLocation
uniqueNodeToString
missingToString
parameterCallable
localFlowIsLocal
readStepIsLocal
@@ -139,3 +138,5 @@ uniqueParameterNodeAtPosition
uniqueParameterNodePosition
uniqueContentApprox
identityLocalStep
missingArgumentCall
multipleArgumentCall

View File

@@ -4,7 +4,6 @@ uniqueType
uniqueNodeLocation
missingLocation
uniqueNodeToString
missingToString
parameterCallable
localFlowIsLocal
readStepIsLocal
@@ -32,3 +31,5 @@ uniqueParameterNodeAtPosition
uniqueParameterNodePosition
uniqueContentApprox
identityLocalStep
missingArgumentCall
multipleArgumentCall

View File

@@ -0,0 +1,19 @@
int source();
void gard_condition_sink(int);
void use(int);
/*
This test checks that we hit the node corresponding to the expression node that wraps `source`
in the condition `source >= 0`.
*/
void test_guard_condition(int source, bool b)
{
if (b) {
use(source);
}
if (source >= 0) {
use(source);
}
gard_condition_sink(source); // clean
}

View File

@@ -0,0 +1,2 @@
testFailures
failures

View File

@@ -0,0 +1,40 @@
import TestUtilities.InlineExpectationsTest
private import cpp
private import semmle.code.cpp.ir.dataflow.DataFlow
private import semmle.code.cpp.controlflow.IRGuards
module IRTestAllocationConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.asParameter().getName().matches("source%") and
source.getLocation().getFile().getBaseName() = "guard-condition-regression-test.cpp"
}
predicate isSink(DataFlow::Node sink) {
exists(FunctionCall call, Expr e | e = call.getAnArgument() |
call.getTarget().getName() = "gard_condition_sink" and
sink.asExpr() = e
)
}
predicate isBarrier(DataFlow::Node node) {
exists(GuardCondition gc | node.asExpr() = gc.getAChild*())
}
}
private module Flow = DataFlow::Global<IRTestAllocationConfig>;
module GuardConditionRegressionTest implements TestSig {
string getARelevantTag() { result = "guard-condition-regression" }
predicate hasActualResult(Location location, string element, string tag, string value) {
exists(DataFlow::Node sink |
Flow::flowTo(sink) and
location = sink.getLocation() and
element = sink.toString() and
tag = "guard-condition-regression" and
value = ""
)
}
}
import MakeTest<GuardConditionRegressionTest>

View File

@@ -10,7 +10,6 @@ uniqueType
uniqueNodeLocation
missingLocation
uniqueNodeToString
missingToString
parameterCallable
localFlowIsLocal
readStepIsLocal
@@ -192,3 +191,5 @@ uniqueParameterNodeAtPosition
uniqueParameterNodePosition
uniqueContentApprox
identityLocalStep
missingArgumentCall
multipleArgumentCall

View File

@@ -4,7 +4,6 @@ uniqueType
uniqueNodeLocation
missingLocation
uniqueNodeToString
missingToString
parameterCallable
localFlowIsLocal
readStepIsLocal
@@ -53,3 +52,5 @@ uniqueParameterNodeAtPosition
uniqueParameterNodePosition
uniqueContentApprox
identityLocalStep
missingArgumentCall
multipleArgumentCall

View File

@@ -19,7 +19,6 @@ edges
| A.cpp:48:20:48:20 | c | A.cpp:29:23:29:23 | c |
| A.cpp:48:20:48:20 | c | A.cpp:48:12:48:18 | call to make indirection [c] |
| A.cpp:49:10:49:10 | b indirection [c] | A.cpp:49:10:49:13 | c |
| A.cpp:49:10:49:10 | b indirection [c] | A.cpp:49:13:49:13 | c |
| A.cpp:55:5:55:5 | set output argument [c] | A.cpp:56:10:56:10 | b indirection [c] |
| A.cpp:55:12:55:19 | new | A.cpp:27:17:27:17 | c |
| A.cpp:55:12:55:19 | new | A.cpp:55:5:55:5 | set output argument [c] |
@@ -37,13 +36,11 @@ edges
| A.cpp:64:21:64:28 | new | A.cpp:64:21:64:28 | new |
| A.cpp:64:21:64:28 | new | A.cpp:85:26:85:26 | c |
| A.cpp:66:10:66:11 | b2 indirection [c] | A.cpp:66:10:66:14 | c |
| A.cpp:66:10:66:11 | b2 indirection [c] | A.cpp:66:14:66:14 | c |
| A.cpp:73:10:73:19 | call to setOnBWrap indirection [c] | A.cpp:75:10:75:11 | b2 indirection [c] |
| A.cpp:73:25:73:32 | new | A.cpp:73:10:73:19 | call to setOnBWrap indirection [c] |
| A.cpp:73:25:73:32 | new | A.cpp:73:25:73:32 | new |
| A.cpp:73:25:73:32 | new | A.cpp:78:27:78:27 | c |
| A.cpp:75:10:75:11 | b2 indirection [c] | A.cpp:75:10:75:14 | c |
| A.cpp:75:10:75:11 | b2 indirection [c] | A.cpp:75:14:75:14 | c |
| A.cpp:78:27:78:27 | c | A.cpp:81:21:81:21 | c |
| A.cpp:81:10:81:15 | call to setOnB indirection [c] | A.cpp:78:6:78:15 | setOnBWrap indirection [c] |
| A.cpp:81:21:81:21 | c | A.cpp:81:10:81:15 | call to setOnB indirection [c] |
@@ -59,16 +56,13 @@ edges
| A.cpp:103:14:103:14 | c indirection [a] | A.cpp:107:12:107:13 | c1 indirection [a] |
| A.cpp:103:14:103:14 | c indirection [a] | A.cpp:120:12:120:13 | c1 indirection [a] |
| A.cpp:107:12:107:13 | c1 indirection [a] | A.cpp:107:12:107:16 | a |
| A.cpp:107:12:107:13 | c1 indirection [a] | A.cpp:107:16:107:16 | a |
| A.cpp:120:12:120:13 | c1 indirection [a] | A.cpp:120:12:120:16 | a |
| A.cpp:120:12:120:13 | c1 indirection [a] | A.cpp:120:16:120:16 | a |
| A.cpp:126:5:126:5 | set output argument [c] | A.cpp:131:8:131:8 | f7 output argument [c] |
| A.cpp:126:12:126:18 | new | A.cpp:27:17:27:17 | c |
| A.cpp:126:12:126:18 | new | A.cpp:126:5:126:5 | set output argument [c] |
| A.cpp:126:12:126:18 | new | A.cpp:126:12:126:18 | new |
| A.cpp:131:8:131:8 | f7 output argument [c] | A.cpp:132:10:132:10 | b indirection [c] |
| A.cpp:132:10:132:10 | b indirection [c] | A.cpp:132:10:132:13 | c |
| A.cpp:132:10:132:10 | b indirection [c] | A.cpp:132:13:132:13 | c |
| A.cpp:140:13:140:13 | b | A.cpp:143:7:143:31 | ... = ... |
| A.cpp:142:7:142:20 | ... = ... | A.cpp:142:10:142:10 | b indirection [post update] [c] |
| A.cpp:142:10:142:10 | b indirection [post update] [c] | A.cpp:143:7:143:31 | ... = ... indirection [c] |
@@ -87,13 +81,10 @@ edges
| A.cpp:151:18:151:18 | b | A.cpp:140:13:140:13 | b |
| A.cpp:151:18:151:18 | b | A.cpp:151:12:151:24 | call to D [b] |
| A.cpp:152:10:152:10 | d indirection [b] | A.cpp:152:10:152:13 | b |
| A.cpp:152:10:152:10 | d indirection [b] | A.cpp:152:13:152:13 | b |
| A.cpp:153:10:153:10 | d indirection [b indirection, c] | A.cpp:153:13:153:13 | b indirection [c] |
| A.cpp:153:13:153:13 | b indirection [c] | A.cpp:153:10:153:16 | c |
| A.cpp:153:13:153:13 | b indirection [c] | A.cpp:153:13:153:13 | b indirection [c] |
| A.cpp:153:13:153:13 | b indirection [c] | A.cpp:153:16:153:16 | c |
| A.cpp:154:10:154:10 | b indirection [c] | A.cpp:154:10:154:13 | c |
| A.cpp:154:10:154:10 | b indirection [c] | A.cpp:154:13:154:13 | c |
| A.cpp:159:12:159:18 | new | A.cpp:160:29:160:29 | b |
| A.cpp:160:18:160:60 | call to MyList [head] | A.cpp:161:38:161:39 | l1 indirection [head] |
| A.cpp:160:29:160:29 | b | A.cpp:160:18:160:60 | call to MyList [head] |
@@ -110,13 +101,11 @@ edges
| A.cpp:165:14:165:17 | next indirection [next indirection, head] | A.cpp:165:20:165:23 | next indirection [head] |
| A.cpp:165:20:165:23 | next indirection [head] | A.cpp:165:10:165:29 | head |
| A.cpp:165:20:165:23 | next indirection [head] | A.cpp:165:20:165:23 | next indirection [head] |
| A.cpp:165:20:165:23 | next indirection [head] | A.cpp:165:26:165:29 | head |
| A.cpp:167:44:167:44 | l indirection [next indirection, head] | A.cpp:167:47:167:50 | next indirection [head] |
| A.cpp:167:44:167:44 | l indirection [next indirection, next indirection, head] | A.cpp:167:47:167:50 | next indirection [next indirection, head] |
| A.cpp:167:47:167:50 | next indirection [head] | A.cpp:169:12:169:12 | l indirection [head] |
| A.cpp:167:47:167:50 | next indirection [next indirection, head] | A.cpp:167:44:167:44 | l indirection [next indirection, head] |
| A.cpp:169:12:169:12 | l indirection [head] | A.cpp:169:12:169:18 | head |
| A.cpp:169:12:169:12 | l indirection [head] | A.cpp:169:15:169:18 | head |
| A.cpp:181:15:181:21 | newHead | A.cpp:183:7:183:20 | ... = ... |
| A.cpp:181:32:181:35 | next indirection [head] | A.cpp:184:7:184:23 | ... = ... indirection [head] |
| A.cpp:181:32:181:35 | next indirection [next indirection, head] | A.cpp:184:7:184:23 | ... = ... indirection [next indirection, head] |
@@ -133,7 +122,6 @@ edges
| B.cpp:9:10:9:11 | b2 indirection [box1 indirection, elem1] | B.cpp:9:14:9:17 | box1 indirection [elem1] |
| B.cpp:9:14:9:17 | box1 indirection [elem1] | B.cpp:9:10:9:24 | elem1 |
| B.cpp:9:14:9:17 | box1 indirection [elem1] | B.cpp:9:14:9:17 | box1 indirection [elem1] |
| B.cpp:9:14:9:17 | box1 indirection [elem1] | B.cpp:9:20:9:24 | elem1 |
| B.cpp:15:15:15:27 | new | B.cpp:16:37:16:37 | e |
| B.cpp:16:16:16:38 | call to Box1 [elem2] | B.cpp:17:25:17:26 | b1 indirection [elem2] |
| B.cpp:16:37:16:37 | e | B.cpp:16:16:16:38 | call to Box1 [elem2] |
@@ -144,7 +132,6 @@ edges
| B.cpp:19:10:19:11 | b2 indirection [box1 indirection, elem2] | B.cpp:19:14:19:17 | box1 indirection [elem2] |
| B.cpp:19:14:19:17 | box1 indirection [elem2] | B.cpp:19:10:19:24 | elem2 |
| B.cpp:19:14:19:17 | box1 indirection [elem2] | B.cpp:19:14:19:17 | box1 indirection [elem2] |
| B.cpp:19:14:19:17 | box1 indirection [elem2] | B.cpp:19:20:19:24 | elem2 |
| B.cpp:33:16:33:17 | e1 | B.cpp:35:7:35:22 | ... = ... |
| B.cpp:33:26:33:27 | e2 | B.cpp:36:7:36:22 | ... = ... |
| B.cpp:35:7:35:22 | ... = ... | B.cpp:35:13:35:17 | this indirection [post update] [elem1] |
@@ -214,7 +201,6 @@ edges
| D.cpp:64:10:64:17 | this indirection [boxfield indirection, box indirection, elem] | D.cpp:64:10:64:17 | boxfield indirection [box indirection, elem] |
| D.cpp:64:20:64:22 | box indirection [elem] | D.cpp:64:10:64:28 | elem |
| D.cpp:64:20:64:22 | box indirection [elem] | D.cpp:64:20:64:22 | box indirection [elem] |
| D.cpp:64:20:64:22 | box indirection [elem] | D.cpp:64:25:64:28 | elem |
| E.cpp:19:27:19:27 | p indirection [data, buffer indirection] | E.cpp:21:10:21:10 | p indirection [data, buffer indirection] |
| E.cpp:21:10:21:10 | p indirection [data, buffer indirection] | E.cpp:21:13:21:16 | data indirection [buffer indirection] |
| E.cpp:21:13:21:16 | data indirection [buffer indirection] | E.cpp:21:18:21:23 | buffer indirection |
@@ -621,7 +607,6 @@ edges
| conflated.cpp:10:11:10:20 | call to user_input | conflated.cpp:10:3:10:22 | ... = ... |
| conflated.cpp:11:9:11:10 | ra indirection [p indirection] | conflated.cpp:11:8:11:12 | * ... |
| conflated.cpp:19:19:19:21 | argument_source output argument | conflated.cpp:20:8:20:10 | raw indirection |
| conflated.cpp:19:19:19:21 | argument_source output argument | conflated.cpp:20:8:20:10 | raw indirection |
| conflated.cpp:29:3:29:22 | ... = ... | conflated.cpp:29:7:29:7 | pa indirection [post update] [x] |
| conflated.cpp:29:7:29:7 | pa indirection [post update] [x] | conflated.cpp:30:8:30:9 | pa indirection [x] |
| conflated.cpp:29:11:29:20 | call to user_input | conflated.cpp:29:3:29:22 | ... = ... |
@@ -730,13 +715,11 @@ edges
| realistic.cpp:53:25:53:33 | baz indirection [post update] [userInput, bufferLen] | realistic.cpp:53:20:53:22 | access to array indirection [post update] [baz indirection, userInput, bufferLen] |
| realistic.cpp:53:35:53:43 | userInput indirection [post update] [bufferLen] | realistic.cpp:53:25:53:33 | baz indirection [post update] [userInput, bufferLen] |
| realistic.cpp:53:47:53:66 | call to user_input | realistic.cpp:53:9:53:66 | ... = ... |
| realistic.cpp:53:55:53:64 | call to user_input | realistic.cpp:53:9:53:66 | ... = ... |
| realistic.cpp:61:21:61:23 | foo indirection [bar, baz indirection, userInput, bufferLen] | realistic.cpp:61:21:61:30 | access to array indirection [baz indirection, userInput, bufferLen] |
| realistic.cpp:61:21:61:30 | access to array indirection [baz indirection, userInput, bufferLen] | realistic.cpp:61:32:61:34 | baz indirection [userInput, bufferLen] |
| realistic.cpp:61:32:61:34 | baz indirection [userInput, bufferLen] | realistic.cpp:61:32:61:34 | baz indirection [userInput, bufferLen] |
| realistic.cpp:61:32:61:34 | baz indirection [userInput, bufferLen] | realistic.cpp:61:37:61:45 | userInput indirection [bufferLen] |
| realistic.cpp:61:37:61:45 | userInput indirection [bufferLen] | realistic.cpp:61:14:61:55 | bufferLen |
| realistic.cpp:61:37:61:45 | userInput indirection [bufferLen] | realistic.cpp:61:47:61:55 | bufferLen |
| simple.cpp:18:9:18:9 | this indirection [a_] | simple.cpp:18:22:18:23 | this indirection [a_] |
| simple.cpp:18:22:18:23 | a_ | simple.cpp:18:9:18:9 | a indirection |
| simple.cpp:18:22:18:23 | this indirection [a_] | simple.cpp:18:22:18:23 | a_ |
@@ -847,7 +830,6 @@ nodes
| A.cpp:48:20:48:20 | c | semmle.label | c |
| A.cpp:49:10:49:10 | b indirection [c] | semmle.label | b indirection [c] |
| A.cpp:49:10:49:13 | c | semmle.label | c |
| A.cpp:49:13:49:13 | c | semmle.label | c |
| A.cpp:55:5:55:5 | set output argument [c] | semmle.label | set output argument [c] |
| A.cpp:55:12:55:19 | new | semmle.label | new |
| A.cpp:55:12:55:19 | new | semmle.label | new |
@@ -863,13 +845,11 @@ nodes
| A.cpp:64:21:64:28 | new | semmle.label | new |
| A.cpp:66:10:66:11 | b2 indirection [c] | semmle.label | b2 indirection [c] |
| A.cpp:66:10:66:14 | c | semmle.label | c |
| A.cpp:66:14:66:14 | c | semmle.label | c |
| A.cpp:73:10:73:19 | call to setOnBWrap indirection [c] | semmle.label | call to setOnBWrap indirection [c] |
| A.cpp:73:25:73:32 | new | semmle.label | new |
| A.cpp:73:25:73:32 | new | semmle.label | new |
| A.cpp:75:10:75:11 | b2 indirection [c] | semmle.label | b2 indirection [c] |
| A.cpp:75:10:75:14 | c | semmle.label | c |
| A.cpp:75:14:75:14 | c | semmle.label | c |
| A.cpp:78:6:78:15 | setOnBWrap indirection [c] | semmle.label | setOnBWrap indirection [c] |
| A.cpp:78:27:78:27 | c | semmle.label | c |
| A.cpp:81:10:81:15 | call to setOnB indirection [c] | semmle.label | call to setOnB indirection [c] |
@@ -885,17 +865,14 @@ nodes
| A.cpp:103:14:103:14 | c indirection [a] | semmle.label | c indirection [a] |
| A.cpp:107:12:107:13 | c1 indirection [a] | semmle.label | c1 indirection [a] |
| A.cpp:107:12:107:16 | a | semmle.label | a |
| A.cpp:107:16:107:16 | a | semmle.label | a |
| A.cpp:120:12:120:13 | c1 indirection [a] | semmle.label | c1 indirection [a] |
| A.cpp:120:12:120:16 | a | semmle.label | a |
| A.cpp:120:16:120:16 | a | semmle.label | a |
| A.cpp:126:5:126:5 | set output argument [c] | semmle.label | set output argument [c] |
| A.cpp:126:12:126:18 | new | semmle.label | new |
| A.cpp:126:12:126:18 | new | semmle.label | new |
| A.cpp:131:8:131:8 | f7 output argument [c] | semmle.label | f7 output argument [c] |
| A.cpp:132:10:132:10 | b indirection [c] | semmle.label | b indirection [c] |
| A.cpp:132:10:132:13 | c | semmle.label | c |
| A.cpp:132:13:132:13 | c | semmle.label | c |
| A.cpp:140:13:140:13 | b | semmle.label | b |
| A.cpp:142:7:142:20 | ... = ... | semmle.label | ... = ... |
| A.cpp:142:10:142:10 | b indirection [post update] [c] | semmle.label | b indirection [post update] [c] |
@@ -914,14 +891,11 @@ nodes
| A.cpp:151:18:151:18 | b | semmle.label | b |
| A.cpp:152:10:152:10 | d indirection [b] | semmle.label | d indirection [b] |
| A.cpp:152:10:152:13 | b | semmle.label | b |
| A.cpp:152:13:152:13 | b | semmle.label | b |
| A.cpp:153:10:153:10 | d indirection [b indirection, c] | semmle.label | d indirection [b indirection, c] |
| A.cpp:153:10:153:16 | c | semmle.label | c |
| A.cpp:153:13:153:13 | b indirection [c] | semmle.label | b indirection [c] |
| A.cpp:153:16:153:16 | c | semmle.label | c |
| A.cpp:154:10:154:10 | b indirection [c] | semmle.label | b indirection [c] |
| A.cpp:154:10:154:13 | c | semmle.label | c |
| A.cpp:154:13:154:13 | c | semmle.label | c |
| A.cpp:159:12:159:18 | new | semmle.label | new |
| A.cpp:160:18:160:60 | call to MyList [head] | semmle.label | call to MyList [head] |
| A.cpp:160:29:160:29 | b | semmle.label | b |
@@ -933,14 +907,12 @@ nodes
| A.cpp:165:10:165:29 | head | semmle.label | head |
| A.cpp:165:14:165:17 | next indirection [next indirection, head] | semmle.label | next indirection [next indirection, head] |
| A.cpp:165:20:165:23 | next indirection [head] | semmle.label | next indirection [head] |
| A.cpp:165:26:165:29 | head | semmle.label | head |
| A.cpp:167:44:167:44 | l indirection [next indirection, head] | semmle.label | l indirection [next indirection, head] |
| A.cpp:167:44:167:44 | l indirection [next indirection, next indirection, head] | semmle.label | l indirection [next indirection, next indirection, head] |
| A.cpp:167:47:167:50 | next indirection [head] | semmle.label | next indirection [head] |
| A.cpp:167:47:167:50 | next indirection [next indirection, head] | semmle.label | next indirection [next indirection, head] |
| A.cpp:169:12:169:12 | l indirection [head] | semmle.label | l indirection [head] |
| A.cpp:169:12:169:18 | head | semmle.label | head |
| A.cpp:169:15:169:18 | head | semmle.label | head |
| A.cpp:181:15:181:21 | newHead | semmle.label | newHead |
| A.cpp:181:32:181:35 | next indirection [head] | semmle.label | next indirection [head] |
| A.cpp:181:32:181:35 | next indirection [next indirection, head] | semmle.label | next indirection [next indirection, head] |
@@ -958,7 +930,6 @@ nodes
| B.cpp:9:10:9:11 | b2 indirection [box1 indirection, elem1] | semmle.label | b2 indirection [box1 indirection, elem1] |
| B.cpp:9:10:9:24 | elem1 | semmle.label | elem1 |
| B.cpp:9:14:9:17 | box1 indirection [elem1] | semmle.label | box1 indirection [elem1] |
| B.cpp:9:20:9:24 | elem1 | semmle.label | elem1 |
| B.cpp:15:15:15:27 | new | semmle.label | new |
| B.cpp:16:16:16:38 | call to Box1 [elem2] | semmle.label | call to Box1 [elem2] |
| B.cpp:16:37:16:37 | e | semmle.label | e |
@@ -967,7 +938,6 @@ nodes
| B.cpp:19:10:19:11 | b2 indirection [box1 indirection, elem2] | semmle.label | b2 indirection [box1 indirection, elem2] |
| B.cpp:19:10:19:24 | elem2 | semmle.label | elem2 |
| B.cpp:19:14:19:17 | box1 indirection [elem2] | semmle.label | box1 indirection [elem2] |
| B.cpp:19:20:19:24 | elem2 | semmle.label | elem2 |
| B.cpp:33:16:33:17 | e1 | semmle.label | e1 |
| B.cpp:33:26:33:27 | e2 | semmle.label | e2 |
| B.cpp:35:7:35:22 | ... = ... | semmle.label | ... = ... |
@@ -1042,7 +1012,6 @@ nodes
| D.cpp:64:10:64:17 | this indirection [boxfield indirection, box indirection, elem] | semmle.label | this indirection [boxfield indirection, box indirection, elem] |
| D.cpp:64:10:64:28 | elem | semmle.label | elem |
| D.cpp:64:20:64:22 | box indirection [elem] | semmle.label | box indirection [elem] |
| D.cpp:64:25:64:28 | elem | semmle.label | elem |
| E.cpp:19:27:19:27 | p indirection [data, buffer indirection] | semmle.label | p indirection [data, buffer indirection] |
| E.cpp:21:10:21:10 | p indirection [data, buffer indirection] | semmle.label | p indirection [data, buffer indirection] |
| E.cpp:21:13:21:16 | data indirection [buffer indirection] | semmle.label | data indirection [buffer indirection] |
@@ -1439,7 +1408,6 @@ nodes
| conflated.cpp:11:9:11:10 | ra indirection [p indirection] | semmle.label | ra indirection [p indirection] |
| conflated.cpp:19:19:19:21 | argument_source output argument | semmle.label | argument_source output argument |
| conflated.cpp:20:8:20:10 | raw indirection | semmle.label | raw indirection |
| conflated.cpp:20:8:20:10 | raw indirection | semmle.label | raw indirection |
| conflated.cpp:29:3:29:22 | ... = ... | semmle.label | ... = ... |
| conflated.cpp:29:7:29:7 | pa indirection [post update] [x] | semmle.label | pa indirection [post update] [x] |
| conflated.cpp:29:11:29:20 | call to user_input | semmle.label | call to user_input |
@@ -1550,13 +1518,11 @@ nodes
| realistic.cpp:53:25:53:33 | baz indirection [post update] [userInput, bufferLen] | semmle.label | baz indirection [post update] [userInput, bufferLen] |
| realistic.cpp:53:35:53:43 | userInput indirection [post update] [bufferLen] | semmle.label | userInput indirection [post update] [bufferLen] |
| realistic.cpp:53:47:53:66 | call to user_input | semmle.label | call to user_input |
| realistic.cpp:53:55:53:64 | call to user_input | semmle.label | call to user_input |
| realistic.cpp:61:14:61:55 | bufferLen | semmle.label | bufferLen |
| realistic.cpp:61:21:61:23 | foo indirection [bar, baz indirection, userInput, bufferLen] | semmle.label | foo indirection [bar, baz indirection, userInput, bufferLen] |
| realistic.cpp:61:21:61:30 | access to array indirection [baz indirection, userInput, bufferLen] | semmle.label | access to array indirection [baz indirection, userInput, bufferLen] |
| realistic.cpp:61:32:61:34 | baz indirection [userInput, bufferLen] | semmle.label | baz indirection [userInput, bufferLen] |
| realistic.cpp:61:37:61:45 | userInput indirection [bufferLen] | semmle.label | userInput indirection [bufferLen] |
| realistic.cpp:61:47:61:55 | bufferLen | semmle.label | bufferLen |
| simple.cpp:18:9:18:9 | a indirection | semmle.label | a indirection |
| simple.cpp:18:9:18:9 | this indirection [a_] | semmle.label | this indirection [a_] |
| simple.cpp:18:22:18:23 | a_ | semmle.label | a_ |
@@ -1706,40 +1672,24 @@ subpaths
| A.cpp:43:10:43:12 | & ... indirection | A.cpp:41:15:41:21 | new | A.cpp:43:10:43:12 | & ... indirection | & ... indirection flows from $@ | A.cpp:41:15:41:21 | new | new |
| A.cpp:43:10:43:12 | & ... indirection | A.cpp:41:15:41:21 | new | A.cpp:43:10:43:12 | & ... indirection | & ... indirection flows from $@ | A.cpp:41:15:41:21 | new | new |
| A.cpp:49:10:49:13 | c | A.cpp:47:12:47:18 | new | A.cpp:49:10:49:13 | c | c flows from $@ | A.cpp:47:12:47:18 | new | new |
| A.cpp:49:13:49:13 | c | A.cpp:47:12:47:18 | new | A.cpp:49:13:49:13 | c | c flows from $@ | A.cpp:47:12:47:18 | new | new |
| A.cpp:56:10:56:17 | call to get | A.cpp:55:12:55:19 | new | A.cpp:56:10:56:17 | call to get | call to get flows from $@ | A.cpp:55:12:55:19 | new | new |
| A.cpp:56:10:56:17 | call to get | A.cpp:55:12:55:19 | new | A.cpp:56:10:56:17 | call to get | call to get flows from $@ | A.cpp:55:12:55:19 | new | new |
| A.cpp:57:10:57:32 | call to get | A.cpp:57:17:57:23 | new | A.cpp:57:10:57:32 | call to get | call to get flows from $@ | A.cpp:57:17:57:23 | new | new |
| A.cpp:66:10:66:14 | c | A.cpp:64:21:64:28 | new | A.cpp:66:10:66:14 | c | c flows from $@ | A.cpp:64:21:64:28 | new | new |
| A.cpp:66:10:66:14 | c | A.cpp:64:21:64:28 | new | A.cpp:66:10:66:14 | c | c flows from $@ | A.cpp:64:21:64:28 | new | new |
| A.cpp:66:14:66:14 | c | A.cpp:64:21:64:28 | new | A.cpp:66:14:66:14 | c | c flows from $@ | A.cpp:64:21:64:28 | new | new |
| A.cpp:66:14:66:14 | c | A.cpp:64:21:64:28 | new | A.cpp:66:14:66:14 | c | c flows from $@ | A.cpp:64:21:64:28 | new | new |
| A.cpp:75:10:75:14 | c | A.cpp:73:25:73:32 | new | A.cpp:75:10:75:14 | c | c flows from $@ | A.cpp:73:25:73:32 | new | new |
| A.cpp:75:10:75:14 | c | A.cpp:73:25:73:32 | new | A.cpp:75:10:75:14 | c | c flows from $@ | A.cpp:73:25:73:32 | new | new |
| A.cpp:75:14:75:14 | c | A.cpp:73:25:73:32 | new | A.cpp:75:14:75:14 | c | c flows from $@ | A.cpp:73:25:73:32 | new | new |
| A.cpp:75:14:75:14 | c | A.cpp:73:25:73:32 | new | A.cpp:75:14:75:14 | c | c flows from $@ | A.cpp:73:25:73:32 | new | new |
| A.cpp:107:12:107:16 | a | A.cpp:98:12:98:18 | new | A.cpp:107:12:107:16 | a | a flows from $@ | A.cpp:98:12:98:18 | new | new |
| A.cpp:107:16:107:16 | a | A.cpp:98:12:98:18 | new | A.cpp:107:16:107:16 | a | a flows from $@ | A.cpp:98:12:98:18 | new | new |
| A.cpp:120:12:120:16 | a | A.cpp:98:12:98:18 | new | A.cpp:120:12:120:16 | a | a flows from $@ | A.cpp:98:12:98:18 | new | new |
| A.cpp:120:16:120:16 | a | A.cpp:98:12:98:18 | new | A.cpp:120:16:120:16 | a | a flows from $@ | A.cpp:98:12:98:18 | new | new |
| A.cpp:132:10:132:13 | c | A.cpp:126:12:126:18 | new | A.cpp:132:10:132:13 | c | c flows from $@ | A.cpp:126:12:126:18 | new | new |
| A.cpp:132:13:132:13 | c | A.cpp:126:12:126:18 | new | A.cpp:132:13:132:13 | c | c flows from $@ | A.cpp:126:12:126:18 | new | new |
| A.cpp:152:10:152:13 | b | A.cpp:143:25:143:31 | new | A.cpp:152:10:152:13 | b | b flows from $@ | A.cpp:143:25:143:31 | new | new |
| A.cpp:152:10:152:13 | b | A.cpp:150:12:150:18 | new | A.cpp:152:10:152:13 | b | b flows from $@ | A.cpp:150:12:150:18 | new | new |
| A.cpp:152:13:152:13 | b | A.cpp:143:25:143:31 | new | A.cpp:152:13:152:13 | b | b flows from $@ | A.cpp:143:25:143:31 | new | new |
| A.cpp:152:13:152:13 | b | A.cpp:150:12:150:18 | new | A.cpp:152:13:152:13 | b | b flows from $@ | A.cpp:150:12:150:18 | new | new |
| A.cpp:153:10:153:16 | c | A.cpp:142:14:142:20 | new | A.cpp:153:10:153:16 | c | c flows from $@ | A.cpp:142:14:142:20 | new | new |
| A.cpp:153:16:153:16 | c | A.cpp:142:14:142:20 | new | A.cpp:153:16:153:16 | c | c flows from $@ | A.cpp:142:14:142:20 | new | new |
| A.cpp:154:10:154:13 | c | A.cpp:142:14:142:20 | new | A.cpp:154:10:154:13 | c | c flows from $@ | A.cpp:142:14:142:20 | new | new |
| A.cpp:154:13:154:13 | c | A.cpp:142:14:142:20 | new | A.cpp:154:13:154:13 | c | c flows from $@ | A.cpp:142:14:142:20 | new | new |
| A.cpp:165:10:165:29 | head | A.cpp:159:12:159:18 | new | A.cpp:165:10:165:29 | head | head flows from $@ | A.cpp:159:12:159:18 | new | new |
| A.cpp:165:26:165:29 | head | A.cpp:159:12:159:18 | new | A.cpp:165:26:165:29 | head | head flows from $@ | A.cpp:159:12:159:18 | new | new |
| A.cpp:169:12:169:18 | head | A.cpp:159:12:159:18 | new | A.cpp:169:12:169:18 | head | head flows from $@ | A.cpp:159:12:159:18 | new | new |
| A.cpp:169:15:169:18 | head | A.cpp:159:12:159:18 | new | A.cpp:169:15:169:18 | head | head flows from $@ | A.cpp:159:12:159:18 | new | new |
| B.cpp:9:10:9:24 | elem1 | B.cpp:6:15:6:24 | new | B.cpp:9:10:9:24 | elem1 | elem1 flows from $@ | B.cpp:6:15:6:24 | new | new |
| B.cpp:9:20:9:24 | elem1 | B.cpp:6:15:6:24 | new | B.cpp:9:20:9:24 | elem1 | elem1 flows from $@ | B.cpp:6:15:6:24 | new | new |
| B.cpp:19:10:19:24 | elem2 | B.cpp:15:15:15:27 | new | B.cpp:19:10:19:24 | elem2 | elem2 flows from $@ | B.cpp:15:15:15:27 | new | new |
| B.cpp:19:20:19:24 | elem2 | B.cpp:15:15:15:27 | new | B.cpp:19:20:19:24 | elem2 | elem2 flows from $@ | B.cpp:15:15:15:27 | new | new |
| C.cpp:29:10:29:11 | s1 | C.cpp:22:12:22:21 | new | C.cpp:29:10:29:11 | s1 | s1 flows from $@ | C.cpp:22:12:22:21 | new | new |
| C.cpp:31:10:31:11 | s3 | C.cpp:24:16:24:25 | new | C.cpp:31:10:31:11 | s3 | s3 flows from $@ | C.cpp:24:16:24:25 | new | new |
| D.cpp:22:10:22:33 | call to getElem | D.cpp:28:15:28:24 | new | D.cpp:22:10:22:33 | call to getElem | call to getElem flows from $@ | D.cpp:28:15:28:24 | new | new |
@@ -1747,7 +1697,6 @@ subpaths
| D.cpp:22:10:22:33 | call to getElem | D.cpp:42:15:42:24 | new | D.cpp:22:10:22:33 | call to getElem | call to getElem flows from $@ | D.cpp:42:15:42:24 | new | new |
| D.cpp:22:10:22:33 | call to getElem | D.cpp:49:15:49:24 | new | D.cpp:22:10:22:33 | call to getElem | call to getElem flows from $@ | D.cpp:49:15:49:24 | new | new |
| D.cpp:64:10:64:28 | elem | D.cpp:56:15:56:24 | new | D.cpp:64:10:64:28 | elem | elem flows from $@ | D.cpp:56:15:56:24 | new | new |
| D.cpp:64:25:64:28 | elem | D.cpp:56:15:56:24 | new | D.cpp:64:25:64:28 | elem | elem flows from $@ | D.cpp:56:15:56:24 | new | new |
| E.cpp:21:18:21:23 | buffer indirection | E.cpp:30:21:30:33 | argument_source output argument | E.cpp:21:18:21:23 | buffer indirection | buffer indirection flows from $@ | E.cpp:30:21:30:33 | argument_source output argument | argument_source output argument |
| E.cpp:31:10:31:12 | raw indirection | E.cpp:28:21:28:23 | argument_source output argument | E.cpp:31:10:31:12 | raw indirection | raw indirection flows from $@ | E.cpp:28:21:28:23 | argument_source output argument | argument_source output argument |
| E.cpp:32:13:32:18 | buffer indirection | E.cpp:29:21:29:29 | argument_source output argument | E.cpp:32:13:32:18 | buffer indirection | buffer indirection flows from $@ | E.cpp:29:21:29:29 | argument_source output argument | argument_source output argument |
@@ -1811,7 +1760,6 @@ subpaths
| complex.cpp:43:18:43:18 | call to b | complex.cpp:56:19:56:28 | call to user_input | complex.cpp:43:18:43:18 | call to b | call to b flows from $@ | complex.cpp:56:19:56:28 | call to user_input | call to user_input |
| conflated.cpp:11:8:11:12 | * ... | conflated.cpp:10:11:10:20 | call to user_input | conflated.cpp:11:8:11:12 | * ... | * ... flows from $@ | conflated.cpp:10:11:10:20 | call to user_input | call to user_input |
| conflated.cpp:20:8:20:10 | raw indirection | conflated.cpp:19:19:19:21 | argument_source output argument | conflated.cpp:20:8:20:10 | raw indirection | raw indirection flows from $@ | conflated.cpp:19:19:19:21 | argument_source output argument | argument_source output argument |
| conflated.cpp:20:8:20:10 | raw indirection | conflated.cpp:19:19:19:21 | argument_source output argument | conflated.cpp:20:8:20:10 | raw indirection | raw indirection flows from $@ | conflated.cpp:19:19:19:21 | argument_source output argument | argument_source output argument |
| conflated.cpp:30:12:30:12 | x | conflated.cpp:29:11:29:20 | call to user_input | conflated.cpp:30:12:30:12 | x | x flows from $@ | conflated.cpp:29:11:29:20 | call to user_input | call to user_input |
| conflated.cpp:37:12:37:12 | x | conflated.cpp:36:11:36:20 | call to user_input | conflated.cpp:37:12:37:12 | x | x flows from $@ | conflated.cpp:36:11:36:20 | call to user_input | call to user_input |
| conflated.cpp:55:18:55:18 | y | conflated.cpp:54:17:54:26 | call to user_input | conflated.cpp:55:18:55:18 | y | y flows from $@ | conflated.cpp:54:17:54:26 | call to user_input | call to user_input |
@@ -1827,9 +1775,6 @@ subpaths
| 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:14:61:55 | bufferLen | realistic.cpp:53:47:53:66 | call to user_input | realistic.cpp:61:14:61:55 | bufferLen | bufferLen flows from $@ | realistic.cpp:53:47:53:66 | call to user_input | call to user_input |
| realistic.cpp:61:14:61:55 | bufferLen | realistic.cpp:53:55:53:64 | call to user_input | realistic.cpp:61:14:61:55 | bufferLen | bufferLen flows from $@ | realistic.cpp:53:55:53:64 | call to user_input | call to user_input |
| realistic.cpp:61:47:61:55 | bufferLen | realistic.cpp:53:47:53:66 | call to user_input | realistic.cpp:61:47:61:55 | bufferLen | bufferLen flows from $@ | realistic.cpp:53:47:53:66 | 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 |

View File

@@ -58,7 +58,7 @@ int main(int argc, char** argv) {
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 ir=53:47 ir=53:55
sink((void*)foo.bar[i].baz->userInput.bufferLen); // $ ast 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.

View File

@@ -165,9 +165,9 @@ void test_map()
// array-like access
std::map<char *, char *> m10, m11, m12, m13;
sink(m10["abc"] = "def");
sink(m11["abc"] = source()); // $ ast,ir
sink(m11["abc"] = source()); // $ ast ir=168:7 ir=168:20
sink(m12.at("abc") = "def");
sink(m13.at("abc") = source()); // $ ast,ir
sink(m13.at("abc") = source()); // $ ast ir=170:7 ir=170:23
sink(m10["abc"]);
sink(m11["abc"]); // $ ast,ir
sink(m12["abc"]);
@@ -317,9 +317,9 @@ void test_unordered_map()
// array-like access
std::unordered_map<char *, char *> m10, m11, m12, m13;
sink(m10["abc"] = "def");
sink(m11["abc"] = source()); // $ ast,ir
sink(m11["abc"] = source()); // $ ast ir=320:7 ir=320:20
sink(m12.at("abc") = "def");
sink(m13.at("abc") = source()); // $ ast,ir
sink(m13.at("abc") = source()); // $ ast ir=322:7 ir=322:23
sink(m10["abc"]);
sink(m11["abc"]); // $ ast,ir
sink(m12["abc"]);

View File

@@ -13,8 +13,8 @@ void arithAssignments(int source1, int clean1) {
source1++;
++source1;
source1 += 1;
sink(source1); // $ ast,ir
sink(++source1); // $ ast,ir
sink(source1); // $ ast ir=12:13 ir=12:22
sink(++source1); // $ ast ir=12:13 ir=12:22
}
// --- globals ---

View File

@@ -15740,6 +15740,201 @@ ir.cpp:
# 2072| Value = [VariableAccess] 116
# 2072| ValueCategory = prvalue(load)
# 2073| getStmt(2): [ReturnStmt] return ...
# 2075| [TopLevelFunction] void exit(int)
# 2075| <params>:
# 2075| getParameter(0): [Parameter] code
# 2075| Type = [IntType] int
# 2077| [TopLevelFunction] int NonExit()
# 2077| <params>:
# 2077| getEntryPoint(): [BlockStmt] { ... }
# 2078| getStmt(0): [DeclStmt] declaration
# 2078| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
# 2078| Type = [IntType] int
# 2078| getVariable().getInitializer(): [Initializer] initializer for x
# 2078| getExpr(): [FunctionCall] call to Add
# 2078| Type = [IntType] int
# 2078| ValueCategory = prvalue
# 2078| getArgument(0): [Literal] 3
# 2078| Type = [IntType] int
# 2078| Value = [Literal] 3
# 2078| ValueCategory = prvalue
# 2078| getArgument(1): [Literal] 4
# 2078| Type = [IntType] int
# 2078| Value = [Literal] 4
# 2078| ValueCategory = prvalue
# 2079| getStmt(1): [IfStmt] if (...) ...
# 2079| getCondition(): [EQExpr] ... == ...
# 2079| Type = [BoolType] bool
# 2079| ValueCategory = prvalue
# 2079| getLeftOperand(): [VariableAccess] x
# 2079| Type = [IntType] int
# 2079| ValueCategory = prvalue(load)
# 2079| getRightOperand(): [Literal] 7
# 2079| Type = [IntType] int
# 2079| Value = [Literal] 7
# 2079| ValueCategory = prvalue
# 2080| getThen(): [ExprStmt] ExprStmt
# 2080| getExpr(): [FunctionCall] call to exit
# 2080| Type = [VoidType] void
# 2080| ValueCategory = prvalue
# 2080| getArgument(0): [Literal] 3
# 2080| Type = [IntType] int
# 2080| Value = [Literal] 3
# 2080| ValueCategory = prvalue
# 2081| getStmt(2): [ExprStmt] ExprStmt
# 2081| getExpr(): [FunctionCall] call to VoidFunc
# 2081| Type = [VoidType] void
# 2081| ValueCategory = prvalue
# 2082| getStmt(3): [ReturnStmt] return ...
# 2082| getExpr(): [VariableAccess] x
# 2082| Type = [IntType] int
# 2082| ValueCategory = prvalue(load)
# 2085| [TopLevelFunction] void CallsNonExit()
# 2085| <params>:
# 2085| getEntryPoint(): [BlockStmt] { ... }
# 2086| getStmt(0): [ExprStmt] ExprStmt
# 2086| getExpr(): [FunctionCall] call to VoidFunc
# 2086| Type = [VoidType] void
# 2086| ValueCategory = prvalue
# 2087| getStmt(1): [ExprStmt] ExprStmt
# 2087| getExpr(): [FunctionCall] call to exit
# 2087| Type = [VoidType] void
# 2087| ValueCategory = prvalue
# 2087| getArgument(0): [Literal] 3
# 2087| Type = [IntType] int
# 2087| Value = [Literal] 3
# 2087| ValueCategory = prvalue
# 2088| getStmt(2): [ReturnStmt] return ...
# 2090| [TopLevelFunction] int TransNonExit()
# 2090| <params>:
# 2090| getEntryPoint(): [BlockStmt] { ... }
# 2091| getStmt(0): [DeclStmt] declaration
# 2091| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
# 2091| Type = [IntType] int
# 2091| getVariable().getInitializer(): [Initializer] initializer for x
# 2091| getExpr(): [FunctionCall] call to Add
# 2091| Type = [IntType] int
# 2091| ValueCategory = prvalue
# 2091| getArgument(0): [Literal] 3
# 2091| Type = [IntType] int
# 2091| Value = [Literal] 3
# 2091| ValueCategory = prvalue
# 2091| getArgument(1): [Literal] 4
# 2091| Type = [IntType] int
# 2091| Value = [Literal] 4
# 2091| ValueCategory = prvalue
# 2092| getStmt(1): [IfStmt] if (...) ...
# 2092| getCondition(): [EQExpr] ... == ...
# 2092| Type = [BoolType] bool
# 2092| ValueCategory = prvalue
# 2092| getLeftOperand(): [VariableAccess] x
# 2092| Type = [IntType] int
# 2092| ValueCategory = prvalue(load)
# 2092| getRightOperand(): [Literal] 7
# 2092| Type = [IntType] int
# 2092| Value = [Literal] 7
# 2092| ValueCategory = prvalue
# 2093| getThen(): [ExprStmt] ExprStmt
# 2093| getExpr(): [FunctionCall] call to CallsNonExit
# 2093| Type = [VoidType] void
# 2093| ValueCategory = prvalue
# 2094| getStmt(2): [ExprStmt] ExprStmt
# 2094| getExpr(): [FunctionCall] call to VoidFunc
# 2094| Type = [VoidType] void
# 2094| ValueCategory = prvalue
# 2095| getStmt(3): [ReturnStmt] return ...
# 2095| getExpr(): [VariableAccess] x
# 2095| Type = [IntType] int
# 2095| ValueCategory = prvalue(load)
# 2098| [TopLevelFunction] void newArrayCorrectType(size_t)
# 2098| <params>:
# 2098| getParameter(0): [Parameter] n
# 2098| Type = [CTypedefType,Size_t] size_t
# 2098| getEntryPoint(): [BlockStmt] { ... }
# 2099| getStmt(0): [ExprStmt] ExprStmt
# 2099| getExpr(): [NewArrayExpr] new[]
# 2099| Type = [IntPointerType] int *
# 2099| ValueCategory = prvalue
# 2099| getExtent(): [VariableAccess] n
# 2099| Type = [CTypedefType,Size_t] size_t
# 2099| ValueCategory = prvalue(load)
# 2100| getStmt(1): [ExprStmt] ExprStmt
# 2100| getExpr(): [NewArrayExpr] new[]
# 2100| Type = [IntPointerType] int *
# 2100| ValueCategory = prvalue
# 2100| getAllocatorCall(): [FunctionCall] call to operator new[]
# 2100| Type = [VoidPointerType] void *
# 2100| ValueCategory = prvalue
# 2100| getArgument(0): [ErrorExpr] <error expr>
# 2100| Type = [LongType] unsigned long
# 2100| ValueCategory = prvalue
# 2100| getArgument(1): [Literal] 1.0
# 2100| Type = [FloatType] float
# 2100| Value = [Literal] 1.0
# 2100| ValueCategory = prvalue
# 2100| getExtent(): [VariableAccess] n
# 2100| Type = [CTypedefType,Size_t] size_t
# 2100| ValueCategory = prvalue(load)
# 2101| getStmt(2): [ExprStmt] ExprStmt
# 2101| getExpr(): [NewArrayExpr] new[]
# 2101| Type = [PointerType] String *
# 2101| ValueCategory = prvalue
# 2101| getInitializer(): [ArrayAggregateLiteral] {...}
# 2101| Type = [ArrayType] String[]
# 2101| ValueCategory = prvalue
# 2101| getAnElementExpr(0): [ConstructorCall] call to String
# 2101| Type = [VoidType] void
# 2101| ValueCategory = prvalue
# 2101| getExtent(): [VariableAccess] n
# 2101| Type = [CTypedefType,Size_t] size_t
# 2101| ValueCategory = prvalue(load)
# 2102| getStmt(3): [ExprStmt] ExprStmt
# 2102| getExpr(): [NewArrayExpr] new[]
# 2102| Type = [PointerType] Overaligned *
# 2102| ValueCategory = prvalue
# 2102| getExtent(): [VariableAccess] n
# 2102| Type = [CTypedefType,Size_t] size_t
# 2102| ValueCategory = prvalue(load)
# 2102| getAlignmentArgument(): [Literal] 128
# 2102| Type = [ScopedEnum] align_val_t
# 2102| Value = [Literal] 128
# 2102| ValueCategory = prvalue
# 2103| getStmt(4): [ExprStmt] ExprStmt
# 2103| getExpr(): [NewArrayExpr] new[]
# 2103| Type = [PointerType] DefaultCtorWithDefaultParam *
# 2103| ValueCategory = prvalue
# 2103| getInitializer(): [ArrayAggregateLiteral] {...}
# 2103| Type = [ArrayType] DefaultCtorWithDefaultParam[]
# 2103| ValueCategory = prvalue
# 2103| getAnElementExpr(0): [ConstructorCall] call to DefaultCtorWithDefaultParam
# 2103| Type = [VoidType] void
# 2103| ValueCategory = prvalue
# 2103| getExtent(): [VariableAccess] n
# 2103| Type = [CTypedefType,Size_t] size_t
# 2103| ValueCategory = prvalue(load)
# 2104| getStmt(5): [ExprStmt] ExprStmt
# 2104| getExpr(): [NewArrayExpr] new[]
# 2104| Type = [IntPointerType] int *
# 2104| ValueCategory = prvalue
# 2104| getInitializer(): [ArrayAggregateLiteral] {...}
# 2104| Type = [ArrayType] int[3]
# 2104| ValueCategory = prvalue
# 2104| getAnElementExpr(0): [Literal] 0
# 2104| Type = [IntType] int
# 2104| Value = [Literal] 0
# 2104| ValueCategory = prvalue
# 2104| getAnElementExpr(1): [Literal] 1
# 2104| Type = [IntType] int
# 2104| Value = [Literal] 1
# 2104| ValueCategory = prvalue
# 2104| getAnElementExpr(2): [Literal] 2
# 2104| Type = [IntType] int
# 2104| Value = [Literal] 2
# 2104| ValueCategory = prvalue
# 2104| getExtent(): [VariableAccess] n
# 2104| Type = [CTypedefType,Size_t] size_t
# 2104| ValueCategory = prvalue(load)
# 2105| getStmt(6): [ReturnStmt] return ...
perf-regression.cpp:
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
# 4| <params>:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
/**
* @kind graph
*/
private import cpp
private import semmle.code.cpp.ir.implementation.aliased_ssa.PrintIR
private import PrintConfig
private class PrintConfig extends PrintIRConfiguration {
override predicate shouldPrintDeclaration(Declaration decl) { shouldDumpDeclaration(decl) }
}

View File

@@ -2072,4 +2072,36 @@ void test_constant_folding() {
test_constant_folding_use(x);
}
void exit(int code);
int NonExit() {
int x = Add(3,4);
if (x == 7)
exit(3);
VoidFunc();
return x;
}
void CallsNonExit() {
VoidFunc();
exit(3);
}
int TransNonExit() {
int x = Add(3,4);
if (x == 7)
CallsNonExit();
VoidFunc();
return x;
}
void newArrayCorrectType(size_t n) {
new int[n]; // No constructor
new(1.0f) int[n]; // Placement new, no constructor
new String[n]; // Constructor
new Overaligned[n]; // Aligned new
new DefaultCtorWithDefaultParam[n];
new int[n] { 0, 1, 2 };
}
// semmle-extractor-options: -std=c++17 --clang

View File

@@ -6207,10 +6207,12 @@
| ir.cpp:1286:25:1286:49 | ChiPartial | partial:m1286_7 |
| ir.cpp:1286:25:1286:49 | ChiTotal | total:m1286_4 |
| ir.cpp:1286:25:1286:49 | SideEffect | ~m1286_4 |
| ir.cpp:1289:5:1289:22 | Address | &:r1289_9 |
| ir.cpp:1289:5:1289:22 | Address | &:r1289_10 |
| ir.cpp:1289:5:1289:22 | ChiPartial | partial:m1289_3 |
| ir.cpp:1289:5:1289:22 | ChiTotal | total:m1289_2 |
| ir.cpp:1289:5:1289:22 | Load | m1291_4 |
| ir.cpp:1289:5:1289:22 | Load | m1289_9 |
| ir.cpp:1289:5:1289:22 | Phi | from 2:m1291_4 |
| ir.cpp:1289:5:1289:22 | Phi | from 3:m1293_2 |
| ir.cpp:1289:5:1289:22 | SideEffect | m1289_3 |
| ir.cpp:1289:29:1289:29 | Address | &:r1289_5 |
| ir.cpp:1289:36:1289:36 | Address | &:r1289_7 |
@@ -6221,6 +6223,7 @@
| ir.cpp:1291:16:1291:16 | Address | &:r1291_2 |
| ir.cpp:1291:16:1291:16 | Load | m1289_8 |
| ir.cpp:1291:16:1291:16 | StoreValue | r1291_3 |
| ir.cpp:1293:1:1293:1 | Address | &:r1293_1 |
| ir.cpp:1295:6:1295:15 | ChiPartial | partial:m1295_3 |
| ir.cpp:1295:6:1295:15 | ChiTotal | total:m1295_2 |
| ir.cpp:1295:6:1295:15 | SideEffect | ~m1296_8 |
@@ -8393,16 +8396,23 @@
| ir.cpp:1747:39:1747:39 | ChiTotal | total:m1747_20 |
| ir.cpp:1747:39:1747:39 | SideEffect | ~m1747_4 |
| ir.cpp:1747:39:1747:39 | SideEffect | ~m1747_15 |
| ir.cpp:1750:5:1750:34 | Address | &:r1750_5 |
| ir.cpp:1750:5:1750:34 | ChiPartial | partial:m1750_3 |
| ir.cpp:1750:5:1750:34 | ChiTotal | total:m1750_2 |
| ir.cpp:1750:5:1750:34 | Load | m1755_2 |
| ir.cpp:1750:5:1750:34 | SideEffect | ~m1754_10 |
| ir.cpp:1751:51:1751:51 | Address | &:r1751_1 |
| ir.cpp:1751:51:1751:51 | Address | &:r1751_1 |
| ir.cpp:1751:51:1751:51 | Address | &:r1751_3 |
| ir.cpp:1751:51:1751:51 | Address | &:r1751_3 |
| ir.cpp:1751:51:1751:51 | Load | m1751_2 |
| ir.cpp:1751:51:1751:51 | SideEffect | m1751_4 |
| ir.cpp:1752:48:1752:48 | Address | &:r1752_1 |
| ir.cpp:1752:48:1752:48 | Address | &:r1752_1 |
| ir.cpp:1752:48:1752:48 | Address | &:r1752_3 |
| ir.cpp:1752:48:1752:48 | Address | &:r1752_3 |
| ir.cpp:1752:48:1752:48 | Load | m1752_2 |
| ir.cpp:1752:48:1752:48 | SideEffect | m1752_4 |
| ir.cpp:1753:40:1753:41 | Address | &:r1753_1 |
| ir.cpp:1753:40:1753:41 | Address | &:r1753_1 |
| ir.cpp:1753:40:1753:41 | Arg(this) | this:r1753_1 |
@@ -8435,6 +8445,7 @@
| ir.cpp:1754:42:1754:42 | SideEffect | ~m1752_4 |
| ir.cpp:1754:42:1754:42 | Unary | r1754_5 |
| ir.cpp:1754:42:1754:42 | Unary | r1754_6 |
| ir.cpp:1755:1:1755:1 | Address | &:r1755_1 |
| ir.cpp:1757:6:1757:22 | ChiPartial | partial:m1757_3 |
| ir.cpp:1757:6:1757:22 | ChiTotal | total:m1757_2 |
| ir.cpp:1757:6:1757:22 | SideEffect | m1757_3 |
@@ -9588,22 +9599,27 @@
| ir.cpp:2021:23:2021:40 | SideEffect | ~m2021_27 |
| ir.cpp:2021:23:2021:40 | Unary | r2021_20 |
| ir.cpp:2021:23:2021:40 | Unary | r2021_28 |
| ir.cpp:2026:14:2026:22 | Address | &:r2026_7 |
| ir.cpp:2026:14:2026:22 | ChiPartial | partial:m2026_3 |
| ir.cpp:2026:14:2026:22 | ChiTotal | total:m2026_2 |
| ir.cpp:2026:14:2026:22 | Load | m2031_2 |
| ir.cpp:2026:14:2026:22 | SideEffect | ~m2028_6 |
| ir.cpp:2026:37:2026:37 | Address | &:r2026_5 |
| ir.cpp:2027:16:2027:16 | Address | &:r2027_1 |
| ir.cpp:2028:3:2028:3 | Address | &:r2028_9 |
| ir.cpp:2028:3:2028:3 | Address | &:r2028_10 |
| ir.cpp:2028:7:2028:7 | Address | &:r2028_1 |
| ir.cpp:2028:7:2028:7 | Left | r2028_2 |
| ir.cpp:2028:7:2028:7 | Load | m2026_6 |
| ir.cpp:2028:7:2028:13 | Condition | r2028_4 |
| ir.cpp:2028:7:2030:28 | Address | &:r2028_7 |
| ir.cpp:2028:7:2030:28 | Address | &:r2028_11 |
| ir.cpp:2028:7:2030:28 | Address | &:r2028_13 |
| ir.cpp:2028:7:2030:28 | Load | m2028_6 |
| ir.cpp:2028:7:2030:28 | Phi | from 2:m2028_12 |
| ir.cpp:2028:7:2030:28 | Phi | from 3:m2028_14 |
| ir.cpp:2028:7:2030:28 | StoreValue | r2028_8 |
| ir.cpp:2028:7:2030:28 | Address | &:r2028_8 |
| ir.cpp:2028:7:2030:28 | Address | &:r2028_12 |
| ir.cpp:2028:7:2030:28 | Address | &:r2028_14 |
| ir.cpp:2028:7:2030:28 | Load | m2028_7 |
| ir.cpp:2028:7:2030:28 | Phi | from 2:m2028_13 |
| ir.cpp:2028:7:2030:28 | Phi | from 2:~m2029_6 |
| ir.cpp:2028:7:2030:28 | Phi | from 3:m2028_15 |
| ir.cpp:2028:7:2030:28 | Phi | from 3:~m2030_6 |
| ir.cpp:2028:7:2030:28 | StoreValue | r2028_9 |
| ir.cpp:2028:11:2028:13 | Right | r2028_3 |
| ir.cpp:2029:6:2029:20 | CallTarget | func:r2029_1 |
| ir.cpp:2029:6:2029:20 | ChiPartial | partial:m2029_5 |
@@ -9626,6 +9642,7 @@
| ir.cpp:2030:22:2030:22 | Arg(0) | 0:r2030_3 |
| ir.cpp:2030:22:2030:22 | Load | m2026_6 |
| ir.cpp:2030:26:2030:27 | Unary | r2030_7 |
| ir.cpp:2031:1:2031:1 | Address | &:r2031_1 |
| ir.cpp:2033:6:2033:17 | ChiPartial | partial:m2033_3 |
| ir.cpp:2033:6:2033:17 | ChiTotal | total:m2033_2 |
| ir.cpp:2033:6:2033:17 | SideEffect | ~m2036_6 |
@@ -9721,8 +9738,11 @@
| ir.cpp:2051:32:2051:32 | Address | &:r2051_7 |
| ir.cpp:2051:32:2051:32 | Load | m2051_6 |
| ir.cpp:2051:32:2051:32 | SideEffect | m2051_8 |
| ir.cpp:2056:5:2056:18 | Address | &:r2056_5 |
| ir.cpp:2056:5:2056:18 | ChiPartial | partial:m2056_3 |
| ir.cpp:2056:5:2056:18 | ChiTotal | total:m2056_2 |
| ir.cpp:2056:5:2056:18 | Load | m2066_2 |
| ir.cpp:2056:5:2056:18 | SideEffect | ~m2065_6 |
| ir.cpp:2058:12:2058:13 | Address | &:r2058_1 |
| ir.cpp:2058:17:2058:27 | Address | &:r2058_4 |
| ir.cpp:2058:17:2058:27 | Address | &:r2058_8 |
@@ -9796,6 +9816,7 @@
| ir.cpp:2065:12:2065:12 | Address | &:r2065_2 |
| ir.cpp:2065:12:2065:12 | Arg(0) | 0:r2065_3 |
| ir.cpp:2065:12:2065:12 | Load | m2064_15 |
| ir.cpp:2066:1:2066:1 | Address | &:r2066_1 |
| ir.cpp:2070:6:2070:26 | ChiPartial | partial:m2070_3 |
| ir.cpp:2070:6:2070:26 | ChiTotal | total:m2070_2 |
| ir.cpp:2070:6:2070:26 | SideEffect | ~m2072_5 |
@@ -9806,6 +9827,147 @@
| ir.cpp:2072:3:2072:27 | ChiTotal | total:m2070_4 |
| ir.cpp:2072:3:2072:27 | SideEffect | ~m2070_4 |
| ir.cpp:2072:29:2072:29 | Arg(0) | 0:r2072_2 |
| ir.cpp:2077:5:2077:11 | Address | &:r2077_6 |
| ir.cpp:2077:5:2077:11 | ChiPartial | partial:m2077_3 |
| ir.cpp:2077:5:2077:11 | ChiTotal | total:m2077_2 |
| ir.cpp:2077:5:2077:11 | Load | m2082_4 |
| ir.cpp:2077:5:2077:11 | SideEffect | ~m2081_4 |
| ir.cpp:2078:9:2078:9 | Address | &:r2078_1 |
| ir.cpp:2078:13:2078:15 | CallTarget | func:r2078_2 |
| ir.cpp:2078:13:2078:15 | ChiPartial | partial:m2078_6 |
| ir.cpp:2078:13:2078:15 | ChiTotal | total:m2077_4 |
| ir.cpp:2078:13:2078:15 | SideEffect | ~m2077_4 |
| ir.cpp:2078:13:2078:15 | StoreValue | r2078_5 |
| ir.cpp:2078:17:2078:17 | Arg(0) | 0:r2078_3 |
| ir.cpp:2078:19:2078:19 | Arg(1) | 1:r2078_4 |
| ir.cpp:2079:9:2079:9 | Address | &:r2079_1 |
| ir.cpp:2079:9:2079:9 | Left | r2079_2 |
| ir.cpp:2079:9:2079:9 | Load | m2078_8 |
| ir.cpp:2079:9:2079:14 | Condition | r2079_4 |
| ir.cpp:2079:14:2079:14 | Right | r2079_3 |
| ir.cpp:2080:9:2080:12 | CallTarget | func:r2080_1 |
| ir.cpp:2080:9:2080:12 | ChiPartial | partial:m2080_4 |
| ir.cpp:2080:9:2080:12 | ChiTotal | total:m2078_7 |
| ir.cpp:2080:9:2080:12 | SideEffect | ~m2078_7 |
| ir.cpp:2080:14:2080:14 | Arg(0) | 0:r2080_2 |
| ir.cpp:2081:5:2081:12 | CallTarget | func:r2081_1 |
| ir.cpp:2081:5:2081:12 | ChiPartial | partial:m2081_3 |
| ir.cpp:2081:5:2081:12 | ChiTotal | total:m2078_7 |
| ir.cpp:2081:5:2081:12 | SideEffect | ~m2078_7 |
| ir.cpp:2082:5:2082:13 | Address | &:r2082_1 |
| ir.cpp:2082:12:2082:12 | Address | &:r2082_2 |
| ir.cpp:2082:12:2082:12 | Load | m2078_8 |
| ir.cpp:2082:12:2082:12 | StoreValue | r2082_3 |
| ir.cpp:2085:6:2085:17 | ChiPartial | partial:m2085_3 |
| ir.cpp:2085:6:2085:17 | ChiTotal | total:m2085_2 |
| ir.cpp:2086:5:2086:12 | CallTarget | func:r2086_1 |
| ir.cpp:2086:5:2086:12 | ChiPartial | partial:m2086_3 |
| ir.cpp:2086:5:2086:12 | ChiTotal | total:m2085_4 |
| ir.cpp:2086:5:2086:12 | SideEffect | ~m2085_4 |
| ir.cpp:2087:5:2087:8 | CallTarget | func:r2087_1 |
| ir.cpp:2087:5:2087:8 | ChiPartial | partial:m2087_4 |
| ir.cpp:2087:5:2087:8 | ChiTotal | total:m2086_4 |
| ir.cpp:2087:5:2087:8 | SideEffect | ~m2086_4 |
| ir.cpp:2087:10:2087:10 | Arg(0) | 0:r2087_2 |
| ir.cpp:2090:5:2090:16 | Address | &:r2090_6 |
| ir.cpp:2090:5:2090:16 | ChiPartial | partial:m2090_3 |
| ir.cpp:2090:5:2090:16 | ChiTotal | total:m2090_2 |
| ir.cpp:2090:5:2090:16 | Load | m2095_4 |
| ir.cpp:2090:5:2090:16 | SideEffect | ~m2094_4 |
| ir.cpp:2091:9:2091:9 | Address | &:r2091_1 |
| ir.cpp:2091:13:2091:15 | CallTarget | func:r2091_2 |
| ir.cpp:2091:13:2091:15 | ChiPartial | partial:m2091_6 |
| ir.cpp:2091:13:2091:15 | ChiTotal | total:m2090_4 |
| ir.cpp:2091:13:2091:15 | SideEffect | ~m2090_4 |
| ir.cpp:2091:13:2091:15 | StoreValue | r2091_5 |
| ir.cpp:2091:17:2091:17 | Arg(0) | 0:r2091_3 |
| ir.cpp:2091:19:2091:19 | Arg(1) | 1:r2091_4 |
| ir.cpp:2092:9:2092:9 | Address | &:r2092_1 |
| ir.cpp:2092:9:2092:9 | Left | r2092_2 |
| ir.cpp:2092:9:2092:9 | Load | m2091_8 |
| ir.cpp:2092:9:2092:14 | Condition | r2092_4 |
| ir.cpp:2092:14:2092:14 | Right | r2092_3 |
| ir.cpp:2093:9:2093:20 | CallTarget | func:r2093_1 |
| ir.cpp:2094:5:2094:12 | CallTarget | func:r2094_1 |
| ir.cpp:2094:5:2094:12 | ChiPartial | partial:m2094_3 |
| ir.cpp:2094:5:2094:12 | ChiTotal | total:m2091_7 |
| ir.cpp:2094:5:2094:12 | SideEffect | ~m2091_7 |
| ir.cpp:2095:5:2095:13 | Address | &:r2095_1 |
| ir.cpp:2095:12:2095:12 | Address | &:r2095_2 |
| ir.cpp:2095:12:2095:12 | Load | m2091_8 |
| ir.cpp:2095:12:2095:12 | StoreValue | r2095_3 |
| ir.cpp:2098:6:2098:24 | ChiPartial | partial:m2098_3 |
| ir.cpp:2098:6:2098:24 | ChiTotal | total:m2098_2 |
| ir.cpp:2098:6:2098:24 | SideEffect | ~m2104_8 |
| ir.cpp:2098:33:2098:33 | Address | &:r2098_5 |
| ir.cpp:2099:3:2099:12 | Address | &:r2099_6 |
| ir.cpp:2099:3:2099:12 | Arg(0) | 0:r2099_5 |
| ir.cpp:2099:3:2099:12 | CallTarget | func:r2099_1 |
| ir.cpp:2099:3:2099:12 | ChiPartial | partial:m2099_7 |
| ir.cpp:2099:3:2099:12 | ChiTotal | total:m2098_4 |
| ir.cpp:2099:3:2099:12 | Right | r2099_4 |
| ir.cpp:2099:3:2099:12 | SideEffect | ~m2098_4 |
| ir.cpp:2099:3:2099:12 | Unary | r2099_6 |
| ir.cpp:2099:11:2099:11 | Address | &:r2099_2 |
| ir.cpp:2099:11:2099:11 | Left | r2099_3 |
| ir.cpp:2099:11:2099:11 | Load | m2098_6 |
| ir.cpp:2100:3:2100:18 | Address | &:r2100_7 |
| ir.cpp:2100:3:2100:18 | Arg(0) | 0:r2100_5 |
| ir.cpp:2100:3:2100:18 | CallTarget | func:r2100_1 |
| ir.cpp:2100:3:2100:18 | ChiPartial | partial:m2100_8 |
| ir.cpp:2100:3:2100:18 | ChiTotal | total:m2099_8 |
| ir.cpp:2100:3:2100:18 | Right | r2100_4 |
| ir.cpp:2100:3:2100:18 | SideEffect | ~m2099_8 |
| ir.cpp:2100:3:2100:18 | Unary | r2100_7 |
| ir.cpp:2100:7:2100:10 | Arg(1) | 1:r2100_6 |
| ir.cpp:2100:17:2100:17 | Address | &:r2100_2 |
| ir.cpp:2100:17:2100:17 | Left | r2100_3 |
| ir.cpp:2100:17:2100:17 | Load | m2098_6 |
| ir.cpp:2101:3:2101:15 | Address | &:r2101_6 |
| ir.cpp:2101:3:2101:15 | Arg(0) | 0:r2101_5 |
| ir.cpp:2101:3:2101:15 | CallTarget | func:r2101_1 |
| ir.cpp:2101:3:2101:15 | ChiPartial | partial:m2101_7 |
| ir.cpp:2101:3:2101:15 | ChiTotal | total:m2100_9 |
| ir.cpp:2101:3:2101:15 | Right | r2101_4 |
| ir.cpp:2101:3:2101:15 | SideEffect | ~m2100_9 |
| ir.cpp:2101:3:2101:15 | Unary | r2101_6 |
| ir.cpp:2101:14:2101:14 | Address | &:r2101_2 |
| ir.cpp:2101:14:2101:14 | Left | r2101_3 |
| ir.cpp:2101:14:2101:14 | Load | m2098_6 |
| ir.cpp:2102:3:2102:20 | Address | &:r2102_7 |
| ir.cpp:2102:3:2102:20 | Arg(0) | 0:r2102_5 |
| ir.cpp:2102:3:2102:20 | CallTarget | func:r2102_1 |
| ir.cpp:2102:3:2102:20 | ChiPartial | partial:m2102_8 |
| ir.cpp:2102:3:2102:20 | ChiTotal | total:m2101_8 |
| ir.cpp:2102:3:2102:20 | Right | r2102_4 |
| ir.cpp:2102:3:2102:20 | SideEffect | ~m2101_8 |
| ir.cpp:2102:3:2102:20 | Unary | r2102_7 |
| ir.cpp:2102:19:2102:19 | Address | &:r2102_2 |
| ir.cpp:2102:19:2102:19 | Left | r2102_3 |
| ir.cpp:2102:19:2102:19 | Load | m2098_6 |
| ir.cpp:2102:21:2102:21 | Arg(1) | 1:r2102_6 |
| ir.cpp:2103:3:2103:36 | Address | &:r2103_6 |
| ir.cpp:2103:3:2103:36 | Arg(0) | 0:r2103_5 |
| ir.cpp:2103:3:2103:36 | CallTarget | func:r2103_1 |
| ir.cpp:2103:3:2103:36 | ChiPartial | partial:m2103_7 |
| ir.cpp:2103:3:2103:36 | ChiTotal | total:m2102_9 |
| ir.cpp:2103:3:2103:36 | Right | r2103_4 |
| ir.cpp:2103:3:2103:36 | SideEffect | ~m2102_9 |
| ir.cpp:2103:3:2103:36 | Unary | r2103_6 |
| ir.cpp:2103:35:2103:35 | Address | &:r2103_2 |
| ir.cpp:2103:35:2103:35 | Left | r2103_3 |
| ir.cpp:2103:35:2103:35 | Load | m2098_6 |
| ir.cpp:2104:3:2104:24 | Address | &:r2104_6 |
| ir.cpp:2104:3:2104:24 | Arg(0) | 0:r2104_5 |
| ir.cpp:2104:3:2104:24 | CallTarget | func:r2104_1 |
| ir.cpp:2104:3:2104:24 | ChiPartial | partial:m2104_7 |
| ir.cpp:2104:3:2104:24 | ChiTotal | total:m2103_8 |
| ir.cpp:2104:3:2104:24 | Right | r2104_4 |
| ir.cpp:2104:3:2104:24 | SideEffect | ~m2103_8 |
| ir.cpp:2104:3:2104:24 | Unary | r2104_6 |
| ir.cpp:2104:11:2104:11 | Address | &:r2104_2 |
| ir.cpp:2104:11:2104:11 | Left | r2104_3 |
| ir.cpp:2104:11:2104:11 | Load | m2098_6 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_7 |

View File

@@ -12,13 +12,15 @@ unnecessaryPhiInstruction
memoryOperandDefinitionIsUnmodeled
operandAcrossFunctions
instructionWithoutUniqueBlock
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
containsLoopOfForwardEdges
missingIRType
multipleIRTypes
lostReachability
backEdgeCountMismatch
useNotDominatedByDefinition
| ir.cpp:1486:8:1486:8 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | ir.cpp:1486:8:1486:8 | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() |
| ir.cpp:1751:51:1751:51 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | ir.cpp:1750:5:1750:34 | int implicit_copy_constructor_test(CopyConstructorTestNonVirtualClass const&, CopyConstructorTestVirtualClass const&) | int implicit_copy_constructor_test(CopyConstructorTestNonVirtualClass const&, CopyConstructorTestVirtualClass const&) |
| ir.cpp:1752:48:1752:48 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | ir.cpp:1750:5:1750:34 | int implicit_copy_constructor_test(CopyConstructorTestNonVirtualClass const&, CopyConstructorTestVirtualClass const&) | int implicit_copy_constructor_test(CopyConstructorTestNonVirtualClass const&, CopyConstructorTestVirtualClass const&) |
| try_except.c:13:13:13:13 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:6:6:6:6 | void f() | void f() |
| try_except.c:13:13:13:13 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:6:6:6:6 | void f() | void f() |
| try_except.c:39:15:39:15 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:32:6:32:6 | void h(int) | void h(int) |
@@ -35,8 +37,4 @@ nonUniqueEnclosingIRFunction
fieldAddressOnNonPointer
thisArgumentIsNonPointer
nonUniqueIRVariable
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
missingIRType
multipleIRTypes
missingCppType

View File

@@ -7201,21 +7201,26 @@ ir.cpp:
# 1290| r1290_1(glval<bool>) = VariableAddress[b] :
# 1290| r1290_2(bool) = Load[b] : &:r1290_1, ~m?
# 1290| v1290_3(void) = ConditionalBranch : r1290_2
#-----| False -> Block 2
#-----| True -> Block 1
#-----| False -> Block 3
#-----| True -> Block 2
# 1291| Block 1
# 1291| r1291_1(glval<int>) = VariableAddress[#return] :
# 1291| r1291_2(glval<int>) = VariableAddress[x] :
# 1291| r1291_3(int) = Load[x] : &:r1291_2, ~m?
# 1291| mu1291_4(int) = Store[#return] : &:r1291_1, r1291_3
# 1289| Block 1
# 1289| r1289_8(glval<int>) = VariableAddress[#return] :
# 1289| v1289_9(void) = ReturnValue : &:r1289_8, ~m?
# 1289| v1289_10(void) = AliasedUse : ~m?
# 1289| v1289_11(void) = ExitFunction :
# 1293| Block 2
# 1293| v1293_1(void) = Unreached :
# 1291| Block 2
# 1291| r1291_1(glval<int>) = VariableAddress[#return] :
# 1291| r1291_2(glval<int>) = VariableAddress[x] :
# 1291| r1291_3(int) = Load[x] : &:r1291_2, ~m?
# 1291| mu1291_4(int) = Store[#return] : &:r1291_1, r1291_3
#-----| Goto -> Block 1
# 1293| Block 3
# 1293| r1293_1(glval<int>) = VariableAddress[#return] :
# 1293| mu1293_2(int) = Uninitialized[#return] : &:r1293_1
#-----| Goto -> Block 1
# 1295| void returnVoid(int, int)
# 1295| Block 0
@@ -9526,15 +9531,14 @@ ir.cpp:
# 1754| mu1754_9(unknown) = ^CallSideEffect : ~m?
# 1754| v1754_10(void) = ^BufferReadSideEffect[0] : &:r1754_7, ~m?
# 1754| mu1754_11(CopyConstructorTestVirtualClass) = ^IndirectMayWriteSideEffect[-1] : &:r1754_1
# 1755| v1755_1(void) = Unreached :
# 1751| Block 1
# 1751| v1751_5(void) = ReturnIndirection[x] : &:r1751_3, ~m?
# 1752| v1752_5(void) = ReturnIndirection[y] : &:r1752_3, ~m?
# 1750| r1750_4(glval<int>) = VariableAddress[#return] :
# 1750| v1750_5(void) = ReturnValue : &:r1750_4, ~m?
# 1750| v1750_6(void) = AliasedUse : ~m?
# 1750| v1750_7(void) = ExitFunction :
# 1755| r1755_1(glval<int>) = VariableAddress[#return] :
# 1755| mu1755_2(int) = Uninitialized[#return] : &:r1755_1
# 1751| v1751_5(void) = ReturnIndirection[x] : &:r1751_3, ~m?
# 1752| v1752_5(void) = ReturnIndirection[y] : &:r1752_3, ~m?
# 1750| r1750_4(glval<int>) = VariableAddress[#return] :
# 1750| v1750_5(void) = ReturnValue : &:r1750_4, ~m?
# 1750| v1750_6(void) = AliasedUse : ~m?
# 1750| v1750_7(void) = ExitFunction :
# 1757| void if_initialization(int)
# 1757| Block 0
@@ -10199,24 +10203,32 @@ ir.cpp:
# 1900| r1900_3(int) = Constant[10] :
# 1900| r1900_4(bool) = CompareLT : r1900_2, r1900_3
# 1900| v1900_5(void) = ConditionalBranch : r1900_4
#-----| False -> Block 2
#-----| True -> Block 1
#-----| False -> Block 3
#-----| True -> Block 2
# 1901| Block 1
# 1901| r1901_1(glval<int>) = VariableAddress[#return] :
# 1901| r1901_2(glval<int>) = VariableAddress[x] :
# 1901| r1901_3(int) = Load[x] : &:r1901_2, ~m?
# 1901| mu1901_4(int) = Store[#return] : &:r1901_1, r1901_3
# 1899| Block 1
# 1899| r1899_6(glval<int>) = VariableAddress[#return] :
# 1899| v1899_7(void) = ReturnValue : &:r1899_6, ~m?
# 1899| v1899_8(void) = AliasedUse : ~m?
# 1899| v1899_9(void) = ExitFunction :
# 1903| Block 2
# 1901| Block 2
# 1901| r1901_1(glval<int>) = VariableAddress[#return] :
# 1901| r1901_2(glval<int>) = VariableAddress[x] :
# 1901| r1901_3(int) = Load[x] : &:r1901_2, ~m?
# 1901| mu1901_4(int) = Store[#return] : &:r1901_1, r1901_3
#-----| Goto -> Block 1
# 1903| Block 3
# 1903| r1903_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
# 1903| v1903_2(void) = Call[noreturnFunc] : func:r1903_1
# 1903| mu1903_3(unknown) = ^CallSideEffect : ~m?
# 1905| v1905_1(void) = Unreached :
# 1899| v1899_10(void) = Unreached :
# 1905| Block 4
# 1905| r1905_1(glval<int>) = VariableAddress[#return] :
# 1905| mu1905_2(int) = Uninitialized[#return] : &:r1905_1
#-----| Goto -> Block 1
# 1907| int noreturnTest2(int)
# 1907| Block 0
@@ -11069,23 +11081,22 @@ ir.cpp:
# 2028| r2028_3(unsigned int) = Constant[100] :
# 2028| r2028_4(bool) = CompareLT : r2028_2, r2028_3
# 2028| v2028_5(void) = ConditionalBranch : r2028_4
#-----| False -> Block 4
#-----| True -> Block 3
#-----| False -> Block 3
#-----| True -> Block 2
# 2026| Block 1
# 2026| r2026_6(glval<unsigned int>) = VariableAddress[#return] :
# 2026| v2026_7(void) = ReturnValue : &:r2026_6, ~m?
# 2026| v2026_8(void) = AliasedUse : ~m?
# 2026| v2026_9(void) = ExitFunction :
# 2028| Block 2
# 2028| Block 1
# 2028| r2028_6(glval<unsigned int>) = VariableAddress[#temp2028:7] :
# 2028| r2028_7(unsigned int) = Load[#temp2028:7] : &:r2028_6, ~m?
# 2028| r2028_8(glval<unsigned int>) = VariableAddress[y] :
# 2028| mu2028_9(unsigned int) = Store[y] : &:r2028_8, r2028_7
# 2031| v2031_1(void) = Unreached :
# 2031| r2031_1(glval<unsigned int>) = VariableAddress[#return] :
# 2031| mu2031_2(unsigned int) = Uninitialized[#return] : &:r2031_1
# 2026| r2026_6(glval<unsigned int>) = VariableAddress[#return] :
# 2026| v2026_7(void) = ReturnValue : &:r2026_6, ~m?
# 2026| v2026_8(void) = AliasedUse : ~m?
# 2026| v2026_9(void) = ExitFunction :
# 2029| Block 3
# 2029| Block 2
# 2029| r2029_1(glval<unknown>) = FunctionAddress[CommaTestHelper] :
# 2029| r2029_2(glval<unsigned int>) = VariableAddress[x] :
# 2029| r2029_3(unsigned int) = Load[x] : &:r2029_2, ~m?
@@ -11096,9 +11107,9 @@ ir.cpp:
# 2029| r2029_8(unsigned int) = CopyValue : r2029_7
# 2028| r2028_10(glval<unsigned int>) = VariableAddress[#temp2028:7] :
# 2028| mu2028_11(unsigned int) = Store[#temp2028:7] : &:r2028_10, r2029_8
#-----| Goto -> Block 2
#-----| Goto -> Block 1
# 2030| Block 4
# 2030| Block 3
# 2030| r2030_1(glval<unknown>) = FunctionAddress[CommaTestHelper] :
# 2030| r2030_2(glval<unsigned int>) = VariableAddress[x] :
# 2030| r2030_3(unsigned int) = Load[x] : &:r2030_2, ~m?
@@ -11109,7 +11120,7 @@ ir.cpp:
# 2030| r2030_8(unsigned int) = Convert : r2030_7
# 2028| r2028_12(glval<unsigned int>) = VariableAddress[#temp2028:7] :
# 2028| mu2028_13(unsigned int) = Store[#temp2028:7] : &:r2028_12, r2030_8
#-----| Goto -> Block 2
#-----| Goto -> Block 1
# 2033| void NewDeleteMem()
# 2033| Block 0
@@ -11295,13 +11306,12 @@ ir.cpp:
# 2065| r2065_3(Derived2 *) = Load[d] : &:r2065_2, ~m?
# 2065| v2065_4(void) = Call[?] : func:r2065_1, 0:r2065_3
# 2065| mu2065_5(unknown) = ^CallSideEffect : ~m?
# 2066| v2066_1(void) = Unreached :
# 2056| Block 1
# 2056| r2056_4(glval<int>) = VariableAddress[#return] :
# 2056| v2056_5(void) = ReturnValue : &:r2056_4, ~m?
# 2056| v2056_6(void) = AliasedUse : ~m?
# 2056| v2056_7(void) = ExitFunction :
# 2066| r2066_1(glval<int>) = VariableAddress[#return] :
# 2066| mu2066_2(int) = Uninitialized[#return] : &:r2066_1
# 2056| r2056_4(glval<int>) = VariableAddress[#return] :
# 2056| v2056_5(void) = ReturnValue : &:r2056_4, ~m?
# 2056| v2056_6(void) = AliasedUse : ~m?
# 2056| v2056_7(void) = ExitFunction :
# 2070| void test_constant_folding()
# 2070| Block 0
@@ -11320,6 +11330,173 @@ ir.cpp:
# 2070| v2070_5(void) = AliasedUse : ~m?
# 2070| v2070_6(void) = ExitFunction :
# 2077| int NonExit()
# 2077| Block 0
# 2077| v2077_1(void) = EnterFunction :
# 2077| mu2077_2(unknown) = AliasedDefinition :
# 2077| mu2077_3(unknown) = InitializeNonLocal :
# 2078| r2078_1(glval<int>) = VariableAddress[x] :
# 2078| r2078_2(glval<unknown>) = FunctionAddress[Add] :
# 2078| r2078_3(int) = Constant[3] :
# 2078| r2078_4(int) = Constant[4] :
# 2078| r2078_5(int) = Call[Add] : func:r2078_2, 0:r2078_3, 1:r2078_4
# 2078| mu2078_6(unknown) = ^CallSideEffect : ~m?
# 2078| mu2078_7(int) = Store[x] : &:r2078_1, r2078_5
# 2079| r2079_1(glval<int>) = VariableAddress[x] :
# 2079| r2079_2(int) = Load[x] : &:r2079_1, ~m?
# 2079| r2079_3(int) = Constant[7] :
# 2079| r2079_4(bool) = CompareEQ : r2079_2, r2079_3
# 2079| v2079_5(void) = ConditionalBranch : r2079_4
#-----| False -> Block 2
#-----| True -> Block 1
# 2080| Block 1
# 2080| r2080_1(glval<unknown>) = FunctionAddress[exit] :
# 2080| r2080_2(int) = Constant[3] :
# 2080| v2080_3(void) = Call[exit] : func:r2080_1, 0:r2080_2
# 2080| mu2080_4(unknown) = ^CallSideEffect : ~m?
# 2077| v2077_4(void) = Unreached :
# 2081| Block 2
# 2081| r2081_1(glval<unknown>) = FunctionAddress[VoidFunc] :
# 2081| v2081_2(void) = Call[VoidFunc] : func:r2081_1
# 2081| mu2081_3(unknown) = ^CallSideEffect : ~m?
# 2082| r2082_1(glval<int>) = VariableAddress[#return] :
# 2082| r2082_2(glval<int>) = VariableAddress[x] :
# 2082| r2082_3(int) = Load[x] : &:r2082_2, ~m?
# 2082| mu2082_4(int) = Store[#return] : &:r2082_1, r2082_3
# 2077| r2077_5(glval<int>) = VariableAddress[#return] :
# 2077| v2077_6(void) = ReturnValue : &:r2077_5, ~m?
# 2077| v2077_7(void) = AliasedUse : ~m?
# 2077| v2077_8(void) = ExitFunction :
# 2085| void CallsNonExit()
# 2085| Block 0
# 2085| v2085_1(void) = EnterFunction :
# 2085| mu2085_2(unknown) = AliasedDefinition :
# 2085| mu2085_3(unknown) = InitializeNonLocal :
# 2086| r2086_1(glval<unknown>) = FunctionAddress[VoidFunc] :
# 2086| v2086_2(void) = Call[VoidFunc] : func:r2086_1
# 2086| mu2086_3(unknown) = ^CallSideEffect : ~m?
# 2087| r2087_1(glval<unknown>) = FunctionAddress[exit] :
# 2087| r2087_2(int) = Constant[3] :
# 2087| v2087_3(void) = Call[exit] : func:r2087_1, 0:r2087_2
# 2087| mu2087_4(unknown) = ^CallSideEffect : ~m?
# 2085| v2085_4(void) = Unreached :
# 2088| Block 1
# 2088| v2088_1(void) = NoOp :
# 2085| v2085_5(void) = ReturnVoid :
# 2085| v2085_6(void) = AliasedUse : ~m?
# 2085| v2085_7(void) = ExitFunction :
# 2090| int TransNonExit()
# 2090| Block 0
# 2090| v2090_1(void) = EnterFunction :
# 2090| mu2090_2(unknown) = AliasedDefinition :
# 2090| mu2090_3(unknown) = InitializeNonLocal :
# 2091| r2091_1(glval<int>) = VariableAddress[x] :
# 2091| r2091_2(glval<unknown>) = FunctionAddress[Add] :
# 2091| r2091_3(int) = Constant[3] :
# 2091| r2091_4(int) = Constant[4] :
# 2091| r2091_5(int) = Call[Add] : func:r2091_2, 0:r2091_3, 1:r2091_4
# 2091| mu2091_6(unknown) = ^CallSideEffect : ~m?
# 2091| mu2091_7(int) = Store[x] : &:r2091_1, r2091_5
# 2092| r2092_1(glval<int>) = VariableAddress[x] :
# 2092| r2092_2(int) = Load[x] : &:r2092_1, ~m?
# 2092| r2092_3(int) = Constant[7] :
# 2092| r2092_4(bool) = CompareEQ : r2092_2, r2092_3
# 2092| v2092_5(void) = ConditionalBranch : r2092_4
#-----| False -> Block 2
#-----| True -> Block 1
# 2093| Block 1
# 2093| r2093_1(glval<unknown>) = FunctionAddress[CallsNonExit] :
# 2093| v2093_2(void) = Call[CallsNonExit] : func:r2093_1
# 2093| mu2093_3(unknown) = ^CallSideEffect : ~m?
#-----| Goto -> Block 2
# 2094| Block 2
# 2094| r2094_1(glval<unknown>) = FunctionAddress[VoidFunc] :
# 2094| v2094_2(void) = Call[VoidFunc] : func:r2094_1
# 2094| mu2094_3(unknown) = ^CallSideEffect : ~m?
# 2095| r2095_1(glval<int>) = VariableAddress[#return] :
# 2095| r2095_2(glval<int>) = VariableAddress[x] :
# 2095| r2095_3(int) = Load[x] : &:r2095_2, ~m?
# 2095| mu2095_4(int) = Store[#return] : &:r2095_1, r2095_3
# 2090| r2090_4(glval<int>) = VariableAddress[#return] :
# 2090| v2090_5(void) = ReturnValue : &:r2090_4, ~m?
# 2090| v2090_6(void) = AliasedUse : ~m?
# 2090| v2090_7(void) = ExitFunction :
# 2098| void newArrayCorrectType(size_t)
# 2098| Block 0
# 2098| v2098_1(void) = EnterFunction :
# 2098| mu2098_2(unknown) = AliasedDefinition :
# 2098| mu2098_3(unknown) = InitializeNonLocal :
# 2098| r2098_4(glval<unsigned long>) = VariableAddress[n] :
# 2098| mu2098_5(unsigned long) = InitializeParameter[n] : &:r2098_4
# 2099| r2099_1(glval<unknown>) = FunctionAddress[operator new[]] :
# 2099| r2099_2(glval<unsigned long>) = VariableAddress[n] :
# 2099| r2099_3(unsigned long) = Load[n] : &:r2099_2, ~m?
# 2099| r2099_4(unsigned long) = Constant[4] :
# 2099| r2099_5(unsigned long) = Mul : r2099_3, r2099_4
# 2099| r2099_6(void *) = Call[operator new[]] : func:r2099_1, 0:r2099_5
# 2099| mu2099_7(unknown) = ^CallSideEffect : ~m?
# 2099| mu2099_8(unknown) = ^InitializeDynamicAllocation : &:r2099_6
# 2099| r2099_9(int *) = Convert : r2099_6
# 2100| r2100_1(glval<unknown>) = FunctionAddress[operator new[]] :
# 2100| r2100_2(glval<unsigned long>) = VariableAddress[n] :
# 2100| r2100_3(unsigned long) = Load[n] : &:r2100_2, ~m?
# 2100| r2100_4(unsigned long) = Constant[4] :
# 2100| r2100_5(unsigned long) = Mul : r2100_3, r2100_4
# 2100| r2100_6(float) = Constant[1.0] :
# 2100| r2100_7(void *) = Call[operator new[]] : func:r2100_1, 0:r2100_5, 1:r2100_6
# 2100| mu2100_8(unknown) = ^CallSideEffect : ~m?
# 2100| mu2100_9(unknown) = ^InitializeDynamicAllocation : &:r2100_7
# 2100| r2100_10(int *) = Convert : r2100_7
# 2101| r2101_1(glval<unknown>) = FunctionAddress[operator new[]] :
# 2101| r2101_2(glval<unsigned long>) = VariableAddress[n] :
# 2101| r2101_3(unsigned long) = Load[n] : &:r2101_2, ~m?
# 2101| r2101_4(unsigned long) = Constant[8] :
# 2101| r2101_5(unsigned long) = Mul : r2101_3, r2101_4
# 2101| r2101_6(void *) = Call[operator new[]] : func:r2101_1, 0:r2101_5
# 2101| mu2101_7(unknown) = ^CallSideEffect : ~m?
# 2101| mu2101_8(unknown) = ^InitializeDynamicAllocation : &:r2101_6
# 2101| r2101_9(String *) = Convert : r2101_6
# 2102| r2102_1(glval<unknown>) = FunctionAddress[operator new[]] :
# 2102| r2102_2(glval<unsigned long>) = VariableAddress[n] :
# 2102| r2102_3(unsigned long) = Load[n] : &:r2102_2, ~m?
# 2102| r2102_4(unsigned long) = Constant[256] :
# 2102| r2102_5(unsigned long) = Mul : r2102_3, r2102_4
# 2102| r2102_6(align_val_t) = Constant[128] :
# 2102| r2102_7(void *) = Call[operator new[]] : func:r2102_1, 0:r2102_5, 1:r2102_6
# 2102| mu2102_8(unknown) = ^CallSideEffect : ~m?
# 2102| mu2102_9(unknown) = ^InitializeDynamicAllocation : &:r2102_7
# 2102| r2102_10(Overaligned *) = Convert : r2102_7
# 2103| r2103_1(glval<unknown>) = FunctionAddress[operator new[]] :
# 2103| r2103_2(glval<unsigned long>) = VariableAddress[n] :
# 2103| r2103_3(unsigned long) = Load[n] : &:r2103_2, ~m?
# 2103| r2103_4(unsigned long) = Constant[1] :
# 2103| r2103_5(unsigned long) = Mul : r2103_3, r2103_4
# 2103| r2103_6(void *) = Call[operator new[]] : func:r2103_1, 0:r2103_5
# 2103| mu2103_7(unknown) = ^CallSideEffect : ~m?
# 2103| mu2103_8(unknown) = ^InitializeDynamicAllocation : &:r2103_6
# 2103| r2103_9(DefaultCtorWithDefaultParam *) = Convert : r2103_6
# 2104| r2104_1(glval<unknown>) = FunctionAddress[operator new[]] :
# 2104| r2104_2(glval<unsigned long>) = VariableAddress[n] :
# 2104| r2104_3(unsigned long) = Load[n] : &:r2104_2, ~m?
# 2104| r2104_4(unsigned long) = Constant[4] :
# 2104| r2104_5(unsigned long) = Mul : r2104_3, r2104_4
# 2104| r2104_6(void *) = Call[operator new[]] : func:r2104_1, 0:r2104_5
# 2104| mu2104_7(unknown) = ^CallSideEffect : ~m?
# 2104| mu2104_8(unknown) = ^InitializeDynamicAllocation : &:r2104_6
# 2104| r2104_9(int *) = Convert : r2104_6
# 2105| v2105_1(void) = NoOp :
# 2098| v2098_6(void) = ReturnVoid :
# 2098| v2098_7(void) = AliasedUse : ~m?
# 2098| v2098_8(void) = ExitFunction :
perf-regression.cpp:
# 6| void Big::Big()
# 6| Block 0

View File

@@ -16,7 +16,6 @@ uniqueNodeLocation
missingLocation
| Nodes without location: 2 |
uniqueNodeToString
missingToString
parameterCallable
localFlowIsLocal
readStepIsLocal
@@ -98,3 +97,5 @@ uniqueParameterNodeAtPosition
uniqueParameterNodePosition
uniqueContentApprox
identityLocalStep
missingArgumentCall
multipleArgumentCall

View File

@@ -5,8 +5,6 @@ uniqueNodeLocation
missingLocation
uniqueNodeToString
| cpp11.cpp:50:15:50:16 | (no string representation) | Node should have one toString but has 0. |
missingToString
| Nodes without toString: 1 |
parameterCallable
localFlowIsLocal
readStepIsLocal
@@ -54,3 +52,5 @@ uniqueParameterNodeAtPosition
uniqueParameterNodePosition
uniqueContentApprox
identityLocalStep
missingArgumentCall
multipleArgumentCall

View File

@@ -34,13 +34,15 @@ unnecessaryPhiInstruction
memoryOperandDefinitionIsUnmodeled
operandAcrossFunctions
instructionWithoutUniqueBlock
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
containsLoopOfForwardEdges
missingIRType
multipleIRTypes
lostReachability
backEdgeCountMismatch
useNotDominatedByDefinition
| VacuousDestructorCall.cpp:2:29:2:29 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | void CallDestructor<int>(int, int*) | void CallDestructor<int>(int, int*) |
| misc.c:219:47:219:48 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | misc.c:219:5:219:26 | int assign_designated_init(someStruct*) | int assign_designated_init(someStruct*) |
| ms_assume.cpp:11:30:11:33 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | ms_assume.cpp:11:12:11:12 | int f(int, char*[]) | int f(int, char*[]) |
| ms_try_except.cpp:9:19:9:19 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) |
| ms_try_except.cpp:9:19:9:19 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) |
| ms_try_except.cpp:19:17:19:21 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) |
@@ -58,8 +60,4 @@ thisArgumentIsNonPointer
| pointer_to_member.cpp:23:5:23:54 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pointer_to_member.cpp:14:5:14:9 | int usePM(int PM::*) | int usePM(int PM::*) |
| pointer_to_member.cpp:24:5:24:49 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pointer_to_member.cpp:14:5:14:9 | int usePM(int PM::*) | int usePM(int PM::*) |
nonUniqueIRVariable
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
missingIRType
multipleIRTypes
missingCppType

View File

@@ -1,58 +1,30 @@
edges
| test_free.cpp:11:10:11:10 | a | test_free.cpp:14:10:14:10 | a |
| test_free.cpp:11:10:11:10 | a | test_free.cpp:14:10:14:10 | a |
| test_free.cpp:11:10:11:10 | a | test_free.cpp:14:10:14:10 | a |
| test_free.cpp:11:10:11:10 | a | test_free.cpp:14:10:14:10 | a |
| test_free.cpp:30:10:30:10 | a | test_free.cpp:31:27:31:27 | a |
| test_free.cpp:35:10:35:10 | a | test_free.cpp:37:27:37:27 | a |
| test_free.cpp:42:27:42:27 | a | test_free.cpp:46:10:46:10 | a |
| test_free.cpp:42:27:42:27 | a | test_free.cpp:46:10:46:10 | a |
| test_free.cpp:42:27:42:27 | a | test_free.cpp:46:10:46:10 | a |
| test_free.cpp:42:27:42:27 | a | test_free.cpp:46:10:46:10 | a |
| test_free.cpp:44:27:44:27 | a | test_free.cpp:46:10:46:10 | a |
| test_free.cpp:44:27:44:27 | a | test_free.cpp:46:10:46:10 | a |
| test_free.cpp:44:27:44:27 | a | test_free.cpp:46:10:46:10 | a |
| test_free.cpp:44:27:44:27 | a | test_free.cpp:46:10:46:10 | a |
| test_free.cpp:50:27:50:27 | a | test_free.cpp:51:10:51:10 | a |
| test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a |
| test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a |
| test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a |
| test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a |
| test_free.cpp:83:12:83:12 | a | test_free.cpp:85:12:85:12 | a |
| test_free.cpp:101:10:101:10 | a | test_free.cpp:103:10:103:10 | a |
| test_free.cpp:128:10:128:11 | * ... | test_free.cpp:129:10:129:11 | * ... |
| test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a |
| test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a |
| test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a |
| test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a |
| test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a |
| test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a |
| test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a |
| test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a |
| test_free.cpp:252:7:252:7 | p | test_free.cpp:255:10:255:10 | p |
| test_free.cpp:260:9:260:9 | p | test_free.cpp:263:12:263:12 | p |
nodes
| test_free.cpp:11:10:11:10 | a | semmle.label | a |
| test_free.cpp:11:10:11:10 | a | semmle.label | a |
| test_free.cpp:14:10:14:10 | a | semmle.label | a |
| test_free.cpp:14:10:14:10 | a | semmle.label | a |
| test_free.cpp:30:10:30:10 | a | semmle.label | a |
| test_free.cpp:31:27:31:27 | a | semmle.label | a |
| test_free.cpp:35:10:35:10 | a | semmle.label | a |
| test_free.cpp:37:27:37:27 | a | semmle.label | a |
| test_free.cpp:42:27:42:27 | a | semmle.label | a |
| test_free.cpp:42:27:42:27 | a | semmle.label | a |
| test_free.cpp:44:27:44:27 | a | semmle.label | a |
| test_free.cpp:44:27:44:27 | a | semmle.label | a |
| test_free.cpp:46:10:46:10 | a | semmle.label | a |
| test_free.cpp:46:10:46:10 | a | semmle.label | a |
| test_free.cpp:46:10:46:10 | a | semmle.label | a |
| test_free.cpp:46:10:46:10 | a | semmle.label | a |
| test_free.cpp:50:27:50:27 | a | semmle.label | a |
| test_free.cpp:51:10:51:10 | a | semmle.label | a |
| test_free.cpp:69:10:69:10 | a | semmle.label | a |
| test_free.cpp:69:10:69:10 | a | semmle.label | a |
| test_free.cpp:72:14:72:14 | a | semmle.label | a |
| test_free.cpp:72:14:72:14 | a | semmle.label | a |
| test_free.cpp:83:12:83:12 | a | semmle.label | a |
| test_free.cpp:85:12:85:12 | a | semmle.label | a |
@@ -61,48 +33,20 @@ nodes
| test_free.cpp:128:10:128:11 | * ... | semmle.label | * ... |
| test_free.cpp:129:10:129:11 | * ... | semmle.label | * ... |
| test_free.cpp:152:27:152:27 | a | semmle.label | a |
| test_free.cpp:152:27:152:27 | a | semmle.label | a |
| test_free.cpp:154:10:154:10 | a | semmle.label | a |
| test_free.cpp:154:10:154:10 | a | semmle.label | a |
| test_free.cpp:207:10:207:10 | a | semmle.label | a |
| test_free.cpp:207:10:207:10 | a | semmle.label | a |
| test_free.cpp:209:10:209:10 | a | semmle.label | a |
| test_free.cpp:209:10:209:10 | a | semmle.label | a |
| test_free.cpp:252:7:252:7 | p | semmle.label | p |
| test_free.cpp:255:10:255:10 | p | semmle.label | p |
| test_free.cpp:260:9:260:9 | p | semmle.label | p |
| test_free.cpp:263:12:263:12 | p | semmle.label | p |
subpaths
#select
| test_free.cpp:14:10:14:10 | a | test_free.cpp:11:10:11:10 | a | test_free.cpp:14:10:14:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
| test_free.cpp:14:10:14:10 | a | test_free.cpp:11:10:11:10 | a | test_free.cpp:14:10:14:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
| test_free.cpp:14:10:14:10 | a | test_free.cpp:11:10:11:10 | a | test_free.cpp:14:10:14:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
| test_free.cpp:14:10:14:10 | a | test_free.cpp:11:10:11:10 | a | test_free.cpp:14:10:14:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
| test_free.cpp:31:27:31:27 | a | test_free.cpp:30:10:30:10 | a | test_free.cpp:31:27:31:27 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:30:5:30:8 | call to free | call to free |
| test_free.cpp:37:27:37:27 | a | test_free.cpp:35:10:35:10 | a | test_free.cpp:37:27:37:27 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:35:5:35:8 | call to free | call to free |
| test_free.cpp:46:10:46:10 | a | test_free.cpp:42:27:42:27 | a | test_free.cpp:46:10:46:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:42:22:42:25 | call to free | call to free |
| test_free.cpp:46:10:46:10 | a | test_free.cpp:42:27:42:27 | a | test_free.cpp:46:10:46:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:42:22:42:25 | call to free | call to free |
| test_free.cpp:46:10:46:10 | a | test_free.cpp:42:27:42:27 | a | test_free.cpp:46:10:46:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:42:22:42:25 | call to free | call to free |
| test_free.cpp:46:10:46:10 | a | test_free.cpp:42:27:42:27 | a | test_free.cpp:46:10:46:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:42:22:42:25 | call to free | call to free |
| test_free.cpp:46:10:46:10 | a | test_free.cpp:44:27:44:27 | a | test_free.cpp:46:10:46:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:44:22:44:25 | call to free | call to free |
| test_free.cpp:46:10:46:10 | a | test_free.cpp:44:27:44:27 | a | test_free.cpp:46:10:46:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:44:22:44:25 | call to free | call to free |
| test_free.cpp:46:10:46:10 | a | test_free.cpp:44:27:44:27 | a | test_free.cpp:46:10:46:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:44:22:44:25 | call to free | call to free |
| test_free.cpp:46:10:46:10 | a | test_free.cpp:44:27:44:27 | a | test_free.cpp:46:10:46:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:44:22:44:25 | call to free | call to free |
| test_free.cpp:51:10:51:10 | a | test_free.cpp:50:27:50:27 | a | test_free.cpp:51:10:51:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:50:22:50:25 | call to free | call to free |
| test_free.cpp:72:14:72:14 | a | test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:69:5:69:8 | call to free | call to free |
| test_free.cpp:72:14:72:14 | a | test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:69:5:69:8 | call to free | call to free |
| test_free.cpp:72:14:72:14 | a | test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:69:5:69:8 | call to free | call to free |
| test_free.cpp:72:14:72:14 | a | test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:69:5:69:8 | call to free | call to free |
| test_free.cpp:85:12:85:12 | a | test_free.cpp:83:12:83:12 | a | test_free.cpp:85:12:85:12 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:83:5:83:13 | delete | delete |
| test_free.cpp:103:10:103:10 | a | test_free.cpp:101:10:101:10 | a | test_free.cpp:103:10:103:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:101:5:101:8 | call to free | call to free |
| test_free.cpp:129:10:129:11 | * ... | test_free.cpp:128:10:128:11 | * ... | test_free.cpp:129:10:129:11 | * ... | Memory pointed to by '* ...' may already have been freed by $@. | test_free.cpp:128:5:128:8 | call to free | call to free |
| test_free.cpp:154:10:154:10 | a | test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:152:22:152:25 | call to free | call to free |
| test_free.cpp:154:10:154:10 | a | test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:152:22:152:25 | call to free | call to free |
| test_free.cpp:154:10:154:10 | a | test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:152:22:152:25 | call to free | call to free |
| test_free.cpp:154:10:154:10 | a | test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:152:22:152:25 | call to free | call to free |
| test_free.cpp:209:10:209:10 | a | test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:207:5:207:8 | call to free | call to free |
| test_free.cpp:209:10:209:10 | a | test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:207:5:207:8 | call to free | call to free |
| test_free.cpp:209:10:209:10 | a | test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:207:5:207:8 | call to free | call to free |
| test_free.cpp:209:10:209:10 | a | test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:207:5:207:8 | call to free | call to free |
| test_free.cpp:255:10:255:10 | p | test_free.cpp:252:7:252:7 | p | test_free.cpp:255:10:255:10 | p | Memory pointed to by 'p' may already have been freed by $@. | test_free.cpp:252:2:252:5 | call to free | call to free |
| test_free.cpp:263:12:263:12 | p | test_free.cpp:260:9:260:9 | p | test_free.cpp:263:12:263:12 | p | Memory pointed to by 'p' may already have been freed by $@. | test_free.cpp:260:2:260:9 | delete | delete |

View File

@@ -96,6 +96,7 @@
| test_free.cpp:255:10:255:10 | p |
| test_free.cpp:260:9:260:9 | p |
| test_free.cpp:263:12:263:12 | p |
| test_free.cpp:269:7:269:11 | ... = ... |
| virtual.cpp:18:10:18:10 | a |
| virtual.cpp:19:10:19:10 | c |
| virtual.cpp:38:10:38:10 | b |

View File

@@ -1 +1,2 @@
| test_free.cpp:36:22:36:35 | ... = ... | This memory allocation may not be released at $@. | test_free.cpp:38:1:38:1 | return ... | this exit point |
| test_free.cpp:267:12:267:17 | call to malloc | This memory allocation may not be released at $@. | test_free.cpp:270:1:270:1 | return ... | this exit point |

View File

@@ -1,107 +1,55 @@
edges
| test_free.cpp:11:10:11:10 | a | test_free.cpp:12:5:12:5 | a |
| test_free.cpp:11:10:11:10 | a | test_free.cpp:12:5:12:5 | a |
| test_free.cpp:11:10:11:10 | a | test_free.cpp:13:6:13:6 | a |
| test_free.cpp:11:10:11:10 | a | test_free.cpp:13:6:13:6 | a |
| test_free.cpp:42:27:42:27 | a | test_free.cpp:45:5:45:5 | a |
| test_free.cpp:11:10:11:10 | a | test_free.cpp:13:5:13:6 | * ... |
| test_free.cpp:42:27:42:27 | a | test_free.cpp:45:5:45:5 | a |
| test_free.cpp:44:27:44:27 | a | test_free.cpp:45:5:45:5 | a |
| test_free.cpp:44:27:44:27 | a | test_free.cpp:45:5:45:5 | a |
| test_free.cpp:69:10:69:10 | a | test_free.cpp:71:9:71:9 | a |
| test_free.cpp:69:10:69:10 | a | test_free.cpp:71:9:71:9 | a |
| test_free.cpp:83:12:83:12 | a | test_free.cpp:84:5:84:5 | a |
| test_free.cpp:90:10:90:10 | a | test_free.cpp:91:5:91:5 | a |
| test_free.cpp:90:10:90:10 | a | test_free.cpp:91:5:91:5 | a |
| test_free.cpp:95:10:95:10 | a | test_free.cpp:96:9:96:9 | a |
| test_free.cpp:101:10:101:10 | a | test_free.cpp:102:23:102:23 | a |
| test_free.cpp:152:27:152:27 | a | test_free.cpp:153:5:153:5 | a |
| test_free.cpp:152:27:152:27 | a | test_free.cpp:153:5:153:5 | a |
| test_free.cpp:233:14:233:15 | * ... | test_free.cpp:236:9:236:10 | * ... |
| test_free.cpp:233:14:233:15 | * ... | test_free.cpp:236:9:236:10 | * ... |
| test_free.cpp:233:14:233:15 | * ... | test_free.cpp:236:9:236:10 | * ... |
| test_free.cpp:233:14:233:15 | * ... | test_free.cpp:236:9:236:10 | * ... |
| test_free.cpp:239:14:239:15 | * ... | test_free.cpp:241:9:241:10 | * ... |
| test_free.cpp:239:14:239:15 | * ... | test_free.cpp:241:9:241:10 | * ... |
| test_free.cpp:239:14:239:15 | * ... | test_free.cpp:241:9:241:10 | * ... |
| test_free.cpp:239:14:239:15 | * ... | test_free.cpp:241:9:241:10 | * ... |
| test_free.cpp:245:10:245:11 | * ... | test_free.cpp:246:9:246:10 | * ... |
| test_free.cpp:245:10:245:11 | * ... | test_free.cpp:246:9:246:10 | * ... |
| test_free.cpp:245:10:245:11 | * ... | test_free.cpp:246:9:246:10 | * ... |
| test_free.cpp:245:10:245:11 | * ... | test_free.cpp:246:9:246:10 | * ... |
| test_free.cpp:252:7:252:7 | p | test_free.cpp:254:6:254:6 | p |
| test_free.cpp:260:9:260:9 | p | test_free.cpp:262:6:262:6 | p |
nodes
| test_free.cpp:11:10:11:10 | a | semmle.label | a |
| test_free.cpp:11:10:11:10 | a | semmle.label | a |
| test_free.cpp:12:5:12:5 | a | semmle.label | a |
| test_free.cpp:13:6:13:6 | a | semmle.label | a |
| test_free.cpp:13:5:13:6 | * ... | semmle.label | * ... |
| test_free.cpp:42:27:42:27 | a | semmle.label | a |
| test_free.cpp:42:27:42:27 | a | semmle.label | a |
| test_free.cpp:44:27:44:27 | a | semmle.label | a |
| test_free.cpp:44:27:44:27 | a | semmle.label | a |
| test_free.cpp:45:5:45:5 | a | semmle.label | a |
| test_free.cpp:45:5:45:5 | a | semmle.label | a |
| test_free.cpp:69:10:69:10 | a | semmle.label | a |
| test_free.cpp:69:10:69:10 | a | semmle.label | a |
| test_free.cpp:71:9:71:9 | a | semmle.label | a |
| test_free.cpp:83:12:83:12 | a | semmle.label | a |
| test_free.cpp:84:5:84:5 | a | semmle.label | a |
| test_free.cpp:90:10:90:10 | a | semmle.label | a |
| test_free.cpp:90:10:90:10 | a | semmle.label | a |
| test_free.cpp:91:5:91:5 | a | semmle.label | a |
| test_free.cpp:95:10:95:10 | a | semmle.label | a |
| test_free.cpp:96:9:96:9 | a | semmle.label | a |
| test_free.cpp:101:10:101:10 | a | semmle.label | a |
| test_free.cpp:102:23:102:23 | a | semmle.label | a |
| test_free.cpp:152:27:152:27 | a | semmle.label | a |
| test_free.cpp:152:27:152:27 | a | semmle.label | a |
| test_free.cpp:153:5:153:5 | a | semmle.label | a |
| test_free.cpp:233:14:233:15 | * ... | semmle.label | * ... |
| test_free.cpp:233:14:233:15 | * ... | semmle.label | * ... |
| test_free.cpp:236:9:236:10 | * ... | semmle.label | * ... |
| test_free.cpp:236:9:236:10 | * ... | semmle.label | * ... |
| test_free.cpp:239:14:239:15 | * ... | semmle.label | * ... |
| test_free.cpp:239:14:239:15 | * ... | semmle.label | * ... |
| test_free.cpp:241:9:241:10 | * ... | semmle.label | * ... |
| test_free.cpp:241:9:241:10 | * ... | semmle.label | * ... |
| test_free.cpp:245:10:245:11 | * ... | semmle.label | * ... |
| test_free.cpp:245:10:245:11 | * ... | semmle.label | * ... |
| test_free.cpp:246:9:246:10 | * ... | semmle.label | * ... |
| test_free.cpp:246:9:246:10 | * ... | semmle.label | * ... |
| test_free.cpp:252:7:252:7 | p | semmle.label | p |
| test_free.cpp:254:6:254:6 | p | semmle.label | p |
| test_free.cpp:260:9:260:9 | p | semmle.label | p |
| test_free.cpp:262:6:262:6 | p | semmle.label | p |
subpaths
#select
| test_free.cpp:12:5:12:5 | a | test_free.cpp:11:10:11:10 | a | test_free.cpp:12:5:12:5 | a | Memory may have been previously freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
| test_free.cpp:12:5:12:5 | a | test_free.cpp:11:10:11:10 | a | test_free.cpp:12:5:12:5 | a | Memory may have been previously freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
| test_free.cpp:13:6:13:6 | a | test_free.cpp:11:10:11:10 | a | test_free.cpp:13:6:13:6 | a | Memory may have been previously freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
| test_free.cpp:13:6:13:6 | a | test_free.cpp:11:10:11:10 | a | test_free.cpp:13:6:13:6 | a | Memory may have been previously freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
| test_free.cpp:45:5:45:5 | a | test_free.cpp:42:27:42:27 | a | test_free.cpp:45:5:45:5 | a | Memory may have been previously freed by $@. | test_free.cpp:42:22:42:25 | call to free | call to free |
| test_free.cpp:13:5:13:6 | * ... | test_free.cpp:11:10:11:10 | a | test_free.cpp:13:5:13:6 | * ... | Memory may have been previously freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
| test_free.cpp:45:5:45:5 | a | test_free.cpp:42:27:42:27 | a | test_free.cpp:45:5:45:5 | a | Memory may have been previously freed by $@. | test_free.cpp:42:22:42:25 | call to free | call to free |
| test_free.cpp:45:5:45:5 | a | test_free.cpp:44:27:44:27 | a | test_free.cpp:45:5:45:5 | a | Memory may have been previously freed by $@. | test_free.cpp:44:22:44:25 | call to free | call to free |
| test_free.cpp:45:5:45:5 | a | test_free.cpp:44:27:44:27 | a | test_free.cpp:45:5:45:5 | a | Memory may have been previously freed by $@. | test_free.cpp:44:22:44:25 | call to free | call to free |
| test_free.cpp:71:9:71:9 | a | test_free.cpp:69:10:69:10 | a | test_free.cpp:71:9:71:9 | a | Memory may have been previously freed by $@. | test_free.cpp:69:5:69:8 | call to free | call to free |
| test_free.cpp:71:9:71:9 | a | test_free.cpp:69:10:69:10 | a | test_free.cpp:71:9:71:9 | a | Memory may have been previously freed by $@. | test_free.cpp:69:5:69:8 | call to free | call to free |
| test_free.cpp:84:5:84:5 | a | test_free.cpp:83:12:83:12 | a | test_free.cpp:84:5:84:5 | a | Memory may have been previously freed by $@. | test_free.cpp:83:5:83:13 | delete | delete |
| test_free.cpp:91:5:91:5 | a | test_free.cpp:90:10:90:10 | a | test_free.cpp:91:5:91:5 | a | Memory may have been previously freed by $@. | test_free.cpp:90:5:90:8 | call to free | call to free |
| test_free.cpp:91:5:91:5 | a | test_free.cpp:90:10:90:10 | a | test_free.cpp:91:5:91:5 | a | Memory may have been previously freed by $@. | test_free.cpp:90:5:90:8 | call to free | call to free |
| test_free.cpp:96:9:96:9 | a | test_free.cpp:95:10:95:10 | a | test_free.cpp:96:9:96:9 | a | Memory may have been previously freed by $@. | test_free.cpp:95:5:95:8 | call to free | call to free |
| test_free.cpp:102:23:102:23 | a | test_free.cpp:101:10:101:10 | a | test_free.cpp:102:23:102:23 | a | Memory may have been previously freed by $@. | test_free.cpp:101:5:101:8 | call to free | call to free |
| test_free.cpp:153:5:153:5 | a | test_free.cpp:152:27:152:27 | a | test_free.cpp:153:5:153:5 | a | Memory may have been previously freed by $@. | test_free.cpp:152:22:152:25 | call to free | call to free |
| test_free.cpp:153:5:153:5 | a | test_free.cpp:152:27:152:27 | a | test_free.cpp:153:5:153:5 | a | Memory may have been previously freed by $@. | test_free.cpp:152:22:152:25 | call to free | call to free |
| test_free.cpp:236:9:236:10 | * ... | test_free.cpp:233:14:233:15 | * ... | test_free.cpp:236:9:236:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:233:9:233:12 | call to free | call to free |
| test_free.cpp:236:9:236:10 | * ... | test_free.cpp:233:14:233:15 | * ... | test_free.cpp:236:9:236:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:233:9:233:12 | call to free | call to free |
| test_free.cpp:236:9:236:10 | * ... | test_free.cpp:233:14:233:15 | * ... | test_free.cpp:236:9:236:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:233:9:233:12 | call to free | call to free |
| test_free.cpp:236:9:236:10 | * ... | test_free.cpp:233:14:233:15 | * ... | test_free.cpp:236:9:236:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:233:9:233:12 | call to free | call to free |
| test_free.cpp:241:9:241:10 | * ... | test_free.cpp:239:14:239:15 | * ... | test_free.cpp:241:9:241:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:239:9:239:12 | call to free | call to free |
| test_free.cpp:241:9:241:10 | * ... | test_free.cpp:239:14:239:15 | * ... | test_free.cpp:241:9:241:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:239:9:239:12 | call to free | call to free |
| test_free.cpp:241:9:241:10 | * ... | test_free.cpp:239:14:239:15 | * ... | test_free.cpp:241:9:241:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:239:9:239:12 | call to free | call to free |
| test_free.cpp:241:9:241:10 | * ... | test_free.cpp:239:14:239:15 | * ... | test_free.cpp:241:9:241:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:239:9:239:12 | call to free | call to free |
| test_free.cpp:246:9:246:10 | * ... | test_free.cpp:245:10:245:11 | * ... | test_free.cpp:246:9:246:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:245:5:245:8 | call to free | call to free |
| test_free.cpp:246:9:246:10 | * ... | test_free.cpp:245:10:245:11 | * ... | test_free.cpp:246:9:246:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:245:5:245:8 | call to free | call to free |
| test_free.cpp:246:9:246:10 | * ... | test_free.cpp:245:10:245:11 | * ... | test_free.cpp:246:9:246:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:245:5:245:8 | call to free | call to free |
| test_free.cpp:246:9:246:10 | * ... | test_free.cpp:245:10:245:11 | * ... | test_free.cpp:246:9:246:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:245:5:245:8 | call to free | call to free |
| test_free.cpp:254:6:254:6 | p | test_free.cpp:252:7:252:7 | p | test_free.cpp:254:6:254:6 | p | Memory may have been previously freed by $@. | test_free.cpp:252:2:252:5 | call to free | call to free |
| test_free.cpp:262:6:262:6 | p | test_free.cpp:260:9:260:9 | p | test_free.cpp:262:6:262:6 | p | Memory may have been previously freed by $@. | test_free.cpp:260:2:260:9 | delete | delete |

View File

@@ -251,14 +251,20 @@ void test_deref(char **a) {
void test_ref(char *&p) {
free(p);
p = (char *)malloc(sizeof(char)*10);
use(p); // GOOD [FALSE POSITIVE]
free(p); // GOOD [FALSE POSITIVE]
use(p); // GOOD
free(p); // GOOD
}
void test_ref_delete(int *&p) {
delete p;
p = new int;
use(p); // GOOD [FALSE POSITIVE]
delete p; // GOOD [FALSE POSITIVE]
use(p); // GOOD
delete p; // GOOD
}
void test_free_assign() {
void *a = malloc(10);
void *b;
free(b = a); // GOOD
}

View File

@@ -3,65 +3,23 @@ edges
| test.cpp:30:34:30:34 | b | test.cpp:31:2:31:2 | b |
| test.cpp:34:31:34:31 | b | test.cpp:35:2:35:2 | b |
| test.cpp:57:19:57:19 | d | test.cpp:26:29:26:29 | b |
| test.cpp:57:19:57:19 | d | test.cpp:57:19:57:19 | d |
| test.cpp:57:19:57:19 | d | test.cpp:57:19:57:19 | d |
| test.cpp:57:19:57:19 | d | test.cpp:58:25:58:25 | d |
| test.cpp:57:19:57:19 | d | test.cpp:58:25:58:25 | d |
| test.cpp:57:19:57:19 | d | test.cpp:58:25:58:25 | d |
| test.cpp:57:19:57:19 | d | test.cpp:59:21:59:21 | d |
| test.cpp:57:19:57:19 | d | test.cpp:59:21:59:21 | d |
| test.cpp:57:19:57:19 | d | test.cpp:59:21:59:21 | d |
| test.cpp:58:25:58:25 | d | test.cpp:30:34:30:34 | b |
| test.cpp:58:25:58:25 | d | test.cpp:58:25:58:25 | d |
| test.cpp:58:25:58:25 | d | test.cpp:58:25:58:25 | d |
| test.cpp:58:25:58:25 | d | test.cpp:59:21:59:21 | d |
| test.cpp:58:25:58:25 | d | test.cpp:59:21:59:21 | d |
| test.cpp:58:25:58:25 | d | test.cpp:59:21:59:21 | d |
| test.cpp:59:21:59:21 | d | test.cpp:34:31:34:31 | b |
| test.cpp:59:21:59:21 | d | test.cpp:59:21:59:21 | d |
| test.cpp:59:21:59:21 | d | test.cpp:59:21:59:21 | d |
| test.cpp:74:19:74:21 | dss | test.cpp:26:29:26:29 | b |
| test.cpp:74:19:74:21 | dss | test.cpp:74:19:74:21 | dss |
| test.cpp:74:19:74:21 | dss | test.cpp:74:19:74:21 | dss |
| test.cpp:74:19:74:21 | dss | test.cpp:75:25:75:27 | dss |
| test.cpp:74:19:74:21 | dss | test.cpp:75:25:75:27 | dss |
| test.cpp:74:19:74:21 | dss | test.cpp:75:25:75:27 | dss |
| test.cpp:74:19:74:21 | dss | test.cpp:76:21:76:23 | dss |
| test.cpp:74:19:74:21 | dss | test.cpp:76:21:76:23 | dss |
| test.cpp:74:19:74:21 | dss | test.cpp:76:21:76:23 | dss |
| test.cpp:75:25:75:27 | dss | test.cpp:30:34:30:34 | b |
| test.cpp:75:25:75:27 | dss | test.cpp:75:25:75:27 | dss |
| test.cpp:75:25:75:27 | dss | test.cpp:75:25:75:27 | dss |
| test.cpp:75:25:75:27 | dss | test.cpp:76:21:76:23 | dss |
| test.cpp:75:25:75:27 | dss | test.cpp:76:21:76:23 | dss |
| test.cpp:75:25:75:27 | dss | test.cpp:76:21:76:23 | dss |
| test.cpp:76:21:76:23 | dss | test.cpp:34:31:34:31 | b |
| test.cpp:76:21:76:23 | dss | test.cpp:76:21:76:23 | dss |
| test.cpp:76:21:76:23 | dss | test.cpp:76:21:76:23 | dss |
| test.cpp:86:19:86:20 | d2 | test.cpp:26:29:26:29 | b |
| test.cpp:86:19:86:20 | d2 | test.cpp:86:19:86:20 | d2 |
| test.cpp:86:19:86:20 | d2 | test.cpp:86:19:86:20 | d2 |
| test.cpp:86:19:86:20 | d2 | test.cpp:86:19:86:20 | d2 |
| test.cpp:86:19:86:20 | d2 | test.cpp:87:25:87:26 | d2 |
| test.cpp:86:19:86:20 | d2 | test.cpp:87:25:87:26 | d2 |
| test.cpp:86:19:86:20 | d2 | test.cpp:87:25:87:26 | d2 |
| test.cpp:86:19:86:20 | d2 | test.cpp:87:25:87:26 | d2 |
| test.cpp:86:19:86:20 | d2 | test.cpp:88:21:88:22 | d2 |
| test.cpp:86:19:86:20 | d2 | test.cpp:88:21:88:22 | d2 |
| test.cpp:86:19:86:20 | d2 | test.cpp:88:21:88:22 | d2 |
| test.cpp:86:19:86:20 | d2 | test.cpp:88:21:88:22 | d2 |
| test.cpp:87:25:87:26 | d2 | test.cpp:30:34:30:34 | b |
| test.cpp:87:25:87:26 | d2 | test.cpp:87:25:87:26 | d2 |
| test.cpp:87:25:87:26 | d2 | test.cpp:87:25:87:26 | d2 |
| test.cpp:87:25:87:26 | d2 | test.cpp:87:25:87:26 | d2 |
| test.cpp:87:25:87:26 | d2 | test.cpp:88:21:88:22 | d2 |
| test.cpp:87:25:87:26 | d2 | test.cpp:88:21:88:22 | d2 |
| test.cpp:87:25:87:26 | d2 | test.cpp:88:21:88:22 | d2 |
| test.cpp:87:25:87:26 | d2 | test.cpp:88:21:88:22 | d2 |
| test.cpp:88:21:88:22 | d2 | test.cpp:34:31:34:31 | b |
| test.cpp:88:21:88:22 | d2 | test.cpp:88:21:88:22 | d2 |
| test.cpp:88:21:88:22 | d2 | test.cpp:88:21:88:22 | d2 |
| test.cpp:88:21:88:22 | d2 | test.cpp:88:21:88:22 | d2 |
nodes
| test.cpp:26:29:26:29 | b | semmle.label | b |
| test.cpp:27:2:27:2 | b | semmle.label | b |
@@ -70,94 +28,31 @@ nodes
| test.cpp:34:31:34:31 | b | semmle.label | b |
| test.cpp:35:2:35:2 | b | semmle.label | b |
| test.cpp:57:19:57:19 | d | semmle.label | d |
| test.cpp:57:19:57:19 | d | semmle.label | d |
| test.cpp:57:19:57:19 | d | semmle.label | d |
| test.cpp:58:25:58:25 | d | semmle.label | d |
| test.cpp:58:25:58:25 | d | semmle.label | d |
| test.cpp:58:25:58:25 | d | semmle.label | d |
| test.cpp:59:21:59:21 | d | semmle.label | d |
| test.cpp:59:21:59:21 | d | semmle.label | d |
| test.cpp:59:21:59:21 | d | semmle.label | d |
| test.cpp:74:19:74:21 | dss | semmle.label | dss |
| test.cpp:74:19:74:21 | dss | semmle.label | dss |
| test.cpp:74:19:74:21 | dss | semmle.label | dss |
| test.cpp:75:25:75:27 | dss | semmle.label | dss |
| test.cpp:75:25:75:27 | dss | semmle.label | dss |
| test.cpp:75:25:75:27 | dss | semmle.label | dss |
| test.cpp:76:21:76:23 | dss | semmle.label | dss |
| test.cpp:76:21:76:23 | dss | semmle.label | dss |
| test.cpp:76:21:76:23 | dss | semmle.label | dss |
| test.cpp:86:19:86:20 | d2 | semmle.label | d2 |
| test.cpp:86:19:86:20 | d2 | semmle.label | d2 |
| test.cpp:86:19:86:20 | d2 | semmle.label | d2 |
| test.cpp:86:19:86:20 | d2 | semmle.label | d2 |
| test.cpp:87:25:87:26 | d2 | semmle.label | d2 |
| test.cpp:87:25:87:26 | d2 | semmle.label | d2 |
| test.cpp:87:25:87:26 | d2 | semmle.label | d2 |
| test.cpp:87:25:87:26 | d2 | semmle.label | d2 |
| test.cpp:88:21:88:22 | d2 | semmle.label | d2 |
| test.cpp:88:21:88:22 | d2 | semmle.label | d2 |
| test.cpp:88:21:88:22 | d2 | semmle.label | d2 |
| test.cpp:88:21:88:22 | d2 | semmle.label | d2 |
subpaths
#select
| test.cpp:27:2:27:2 | b | test.cpp:57:19:57:19 | d | test.cpp:27:2:27:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:57:19:57:19 | d | this cast |
| test.cpp:27:2:27:2 | b | test.cpp:57:19:57:19 | d | test.cpp:27:2:27:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:57:19:57:19 | d | this cast |
| test.cpp:27:2:27:2 | b | test.cpp:57:19:57:19 | d | test.cpp:27:2:27:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:57:19:57:19 | d | this cast |
| test.cpp:27:2:27:2 | b | test.cpp:74:19:74:21 | dss | test.cpp:27:2:27:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:74:19:74:21 | dss | this cast |
| test.cpp:27:2:27:2 | b | test.cpp:74:19:74:21 | dss | test.cpp:27:2:27:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:74:19:74:21 | dss | this cast |
| test.cpp:27:2:27:2 | b | test.cpp:74:19:74:21 | dss | test.cpp:27:2:27:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:74:19:74:21 | dss | this cast |
| test.cpp:27:2:27:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:27:2:27:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast |
| test.cpp:27:2:27:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:27:2:27:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast |
| test.cpp:27:2:27:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:27:2:27:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast |
| test.cpp:27:2:27:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:27:2:27:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast |
| test.cpp:31:2:31:2 | b | test.cpp:57:19:57:19 | d | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:57:19:57:19 | d | this cast |
| test.cpp:31:2:31:2 | b | test.cpp:57:19:57:19 | d | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:57:19:57:19 | d | this cast |
| test.cpp:31:2:31:2 | b | test.cpp:57:19:57:19 | d | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:57:19:57:19 | d | this cast |
| test.cpp:31:2:31:2 | b | test.cpp:58:25:58:25 | d | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:58:25:58:25 | d | this cast |
| test.cpp:31:2:31:2 | b | test.cpp:58:25:58:25 | d | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:58:25:58:25 | d | this cast |
| test.cpp:31:2:31:2 | b | test.cpp:58:25:58:25 | d | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:58:25:58:25 | d | this cast |
| test.cpp:31:2:31:2 | b | test.cpp:74:19:74:21 | dss | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:74:19:74:21 | dss | this cast |
| test.cpp:31:2:31:2 | b | test.cpp:74:19:74:21 | dss | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:74:19:74:21 | dss | this cast |
| test.cpp:31:2:31:2 | b | test.cpp:74:19:74:21 | dss | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:74:19:74:21 | dss | this cast |
| test.cpp:31:2:31:2 | b | test.cpp:75:25:75:27 | dss | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:75:25:75:27 | dss | this cast |
| test.cpp:31:2:31:2 | b | test.cpp:75:25:75:27 | dss | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:75:25:75:27 | dss | this cast |
| test.cpp:31:2:31:2 | b | test.cpp:75:25:75:27 | dss | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:75:25:75:27 | dss | this cast |
| test.cpp:31:2:31:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast |
| test.cpp:31:2:31:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast |
| test.cpp:31:2:31:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast |
| test.cpp:31:2:31:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast |
| test.cpp:31:2:31:2 | b | test.cpp:87:25:87:26 | d2 | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:87:25:87:26 | d2 | this cast |
| test.cpp:31:2:31:2 | b | test.cpp:87:25:87:26 | d2 | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:87:25:87:26 | d2 | this cast |
| test.cpp:31:2:31:2 | b | test.cpp:87:25:87:26 | d2 | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:87:25:87:26 | d2 | this cast |
| test.cpp:31:2:31:2 | b | test.cpp:87:25:87:26 | d2 | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:87:25:87:26 | d2 | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:57:19:57:19 | d | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:57:19:57:19 | d | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:57:19:57:19 | d | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:57:19:57:19 | d | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:57:19:57:19 | d | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:57:19:57:19 | d | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:58:25:58:25 | d | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:58:25:58:25 | d | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:58:25:58:25 | d | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:58:25:58:25 | d | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:58:25:58:25 | d | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:58:25:58:25 | d | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:59:21:59:21 | d | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:59:21:59:21 | d | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:59:21:59:21 | d | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:59:21:59:21 | d | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:59:21:59:21 | d | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:59:21:59:21 | d | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:74:19:74:21 | dss | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:74:19:74:21 | dss | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:74:19:74:21 | dss | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:74:19:74:21 | dss | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:74:19:74:21 | dss | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:74:19:74:21 | dss | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:75:25:75:27 | dss | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:75:25:75:27 | dss | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:75:25:75:27 | dss | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:75:25:75:27 | dss | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:75:25:75:27 | dss | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:75:25:75:27 | dss | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:76:21:76:23 | dss | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:76:21:76:23 | dss | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:76:21:76:23 | dss | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:76:21:76:23 | dss | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:76:21:76:23 | dss | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:76:21:76:23 | dss | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:87:25:87:26 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:87:25:87:26 | d2 | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:87:25:87:26 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:87:25:87:26 | d2 | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:87:25:87:26 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:87:25:87:26 | d2 | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:87:25:87:26 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:87:25:87:26 | d2 | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:88:21:88:22 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:88:21:88:22 | d2 | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:88:21:88:22 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:88:21:88:22 | d2 | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:88:21:88:22 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:88:21:88:22 | d2 | this cast |
| test.cpp:35:2:35:2 | b | test.cpp:88:21:88:22 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:88:21:88:22 | d2 | this cast |

View File

@@ -1,17 +1,8 @@
| test.cpp:12:25:12:29 | call to ntohl | Unchecked use of data from network function $@. | test.cpp:12:25:12:29 | call to ntohl | call to ntohl |
| test.cpp:12:25:12:34 | call to ntohl | Unchecked use of data from network function $@. | test.cpp:12:25:12:29 | call to ntohl | call to ntohl |
| test.cpp:12:25:12:34 | call to ntohl | Unchecked use of data from network function $@. | test.cpp:12:25:12:34 | call to ntohl | call to ntohl |
| test.cpp:21:26:21:29 | len2 | Unchecked use of data from network function $@. | test.cpp:10:16:10:20 | call to ntohl | call to ntohl |
| test.cpp:21:26:21:29 | len2 | Unchecked use of data from network function $@. | test.cpp:10:16:10:25 | call to ntohl | call to ntohl |
| test.cpp:31:26:31:29 | len2 | Unchecked use of data from network function $@. | test.cpp:10:16:10:20 | call to ntohl | call to ntohl |
| test.cpp:31:26:31:29 | len2 | Unchecked use of data from network function $@. | test.cpp:10:16:10:25 | call to ntohl | call to ntohl |
| test.cpp:61:26:61:29 | len2 | Unchecked use of data from network function $@. | test.cpp:10:16:10:20 | call to ntohl | call to ntohl |
| test.cpp:61:26:61:29 | len2 | Unchecked use of data from network function $@. | test.cpp:10:16:10:25 | call to ntohl | call to ntohl |
| test.cpp:64:9:64:12 | len2 | Unchecked use of data from network function $@. | test.cpp:10:16:10:20 | call to ntohl | call to ntohl |
| test.cpp:64:9:64:12 | len2 | Unchecked use of data from network function $@. | test.cpp:10:16:10:25 | call to ntohl | call to ntohl |
| test.cpp:73:10:73:13 | lens | Unchecked use of data from network function $@. | test.cpp:10:16:10:20 | call to ntohl | call to ntohl |
| test.cpp:73:10:73:13 | lens | Unchecked use of data from network function $@. | test.cpp:10:16:10:25 | call to ntohl | call to ntohl |
| test.cpp:86:10:86:13 | len3 | Unchecked use of data from network function $@. | test.cpp:85:10:85:14 | call to ntohl | call to ntohl |
| test.cpp:86:10:86:13 | len3 | Unchecked use of data from network function $@. | test.cpp:85:10:85:19 | call to ntohl | call to ntohl |
| test.cpp:94:9:94:11 | len | Unchecked use of data from network function $@. | test.cpp:99:8:99:12 | call to ntohl | call to ntohl |
| test.cpp:94:9:94:11 | len | Unchecked use of data from network function $@. | test.cpp:99:8:99:17 | call to ntohl | call to ntohl |

View File

@@ -1,7 +1,6 @@
edges
| search.c:14:24:14:28 | query | search.c:17:8:17:12 | query |
| search.c:14:24:14:28 | query | search.c:17:8:17:12 | query |
| search.c:14:24:14:28 | query | search.c:17:8:17:12 | query |
| search.c:22:24:22:28 | query | search.c:23:39:23:43 | query |
| search.c:22:24:22:28 | query | search.c:23:39:23:43 | query |
| search.c:51:21:51:26 | call to getenv | search.c:55:17:55:25 | raw_query |
@@ -15,7 +14,6 @@ nodes
| search.c:14:24:14:28 | query | semmle.label | query |
| search.c:17:8:17:12 | query | semmle.label | query |
| search.c:17:8:17:12 | query | semmle.label | query |
| search.c:17:8:17:12 | query | semmle.label | query |
| search.c:22:24:22:28 | query | semmle.label | query |
| search.c:23:39:23:43 | query | semmle.label | query |
| search.c:23:39:23:43 | query | semmle.label | query |

View File

@@ -1,12 +1,21 @@
edges
| test.c:14:27:14:30 | argv indirection | test.c:21:18:21:23 | query1 indirection |
| test.c:14:27:14:30 | argv indirection | test.c:35:16:35:23 | userName indirection |
| test.c:35:16:35:23 | userName indirection | test.c:40:25:40:32 | username indirection |
| test.c:38:7:38:20 | globalUsername indirection | test.c:51:18:51:23 | query1 indirection |
| test.c:40:25:40:32 | username indirection | test.c:38:7:38:20 | globalUsername indirection |
| test.cpp:39:27:39:30 | argv indirection | test.cpp:43:27:43:33 | access to array indirection |
nodes
| test.c:14:27:14:30 | argv indirection | semmle.label | argv indirection |
| test.c:21:18:21:23 | query1 indirection | semmle.label | query1 indirection |
| test.c:35:16:35:23 | userName indirection | semmle.label | userName indirection |
| test.c:38:7:38:20 | globalUsername indirection | semmle.label | globalUsername indirection |
| test.c:40:25:40:32 | username indirection | semmle.label | username indirection |
| test.c:51:18:51:23 | query1 indirection | semmle.label | query1 indirection |
| test.cpp:39:27:39:30 | argv indirection | semmle.label | argv indirection |
| test.cpp:43:27:43:33 | access to array indirection | semmle.label | access to array indirection |
subpaths
#select
| test.c:21:18:21:23 | query1 | test.c:14:27:14:30 | argv indirection | test.c:21:18:21:23 | query1 indirection | This argument to a SQL query function is derived from $@ and then passed to mysql_query(sqlArg). | test.c:14:27:14:30 | argv indirection | user input (a command-line argument) |
| test.c:51:18:51:23 | query1 | test.c:14:27:14:30 | argv indirection | test.c:51:18:51:23 | query1 indirection | This argument to a SQL query function is derived from $@ and then passed to mysql_query(sqlArg). | test.c:14:27:14:30 | argv indirection | user input (a command-line argument) |
| test.cpp:43:27:43:33 | access to array | test.cpp:39:27:39:30 | argv indirection | test.cpp:43:27:43:33 | access to array indirection | This argument to a SQL query function is derived from $@ and then passed to pqxx::work::exec1((unnamed parameter 0)). | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) |

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