mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
Merge tag 'codeql-cli/latest'
Compatible with the latest released version of the CodeQL CLI
This commit is contained in:
2213
cpp/downgrades/dbe9c8eb5fc6f54b7ae08c7317d0795b24961564/old.dbscheme
Normal file
2213
cpp/downgrades/dbe9c8eb5fc6f54b7ae08c7317d0795b24961564/old.dbscheme
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Make __is_trivial a builtin operation
|
||||
compatibility: full
|
||||
@@ -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.
|
||||
|
||||
9
cpp/ql/lib/change-notes/released/0.10.0.md
Normal file
9
cpp/ql/lib/change-notes/released/0.10.0.md
Normal 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.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.9.3
|
||||
lastReleaseVersion: 0.10.0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.9.3
|
||||
version: 0.10.0
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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)))
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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() }
|
||||
|
||||
@@ -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" }
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -18,4 +18,6 @@ module CppDataFlow implements InputSig {
|
||||
import Public
|
||||
|
||||
Node exprNode(DataFlowExpr e) { result = Public::exprNode(e) }
|
||||
|
||||
predicate getAdditionalFlowIntoCallNodeTerm = Private::getAdditionalFlowIntoCallNodeTerm/2;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
)
|
||||
)
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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() }
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Make __is_trivial a builtin operation
|
||||
compatibility: full
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
18
cpp/ql/src/Metrics/Internal/ASTConsistency.ql
Normal file
18
cpp/ql/src/Metrics/Internal/ASTConsistency.ql
Normal 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
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
12
cpp/ql/src/change-notes/released/0.8.0.md
Normal file
12
cpp/ql/src/change-notes/released/0.8.0.md
Normal 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.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.7.5
|
||||
lastReleaseVersion: 0.8.0
|
||||
|
||||
@@ -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<T></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>
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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. |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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. |
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
uniqueNodeToString
|
||||
missingToString
|
||||
parameterCallable
|
||||
localFlowIsLocal
|
||||
readStepIsLocal
|
||||
@@ -139,3 +138,5 @@ uniqueParameterNodeAtPosition
|
||||
uniqueParameterNodePosition
|
||||
uniqueContentApprox
|
||||
identityLocalStep
|
||||
missingArgumentCall
|
||||
multipleArgumentCall
|
||||
|
||||
@@ -4,7 +4,6 @@ uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
uniqueNodeToString
|
||||
missingToString
|
||||
parameterCallable
|
||||
localFlowIsLocal
|
||||
readStepIsLocal
|
||||
@@ -32,3 +31,5 @@ uniqueParameterNodeAtPosition
|
||||
uniqueParameterNodePosition
|
||||
uniqueContentApprox
|
||||
identityLocalStep
|
||||
missingArgumentCall
|
||||
multipleArgumentCall
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
testFailures
|
||||
failures
|
||||
@@ -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>
|
||||
@@ -10,7 +10,6 @@ uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
uniqueNodeToString
|
||||
missingToString
|
||||
parameterCallable
|
||||
localFlowIsLocal
|
||||
readStepIsLocal
|
||||
@@ -192,3 +191,5 @@ uniqueParameterNodeAtPosition
|
||||
uniqueParameterNodePosition
|
||||
uniqueContentApprox
|
||||
identityLocalStep
|
||||
missingArgumentCall
|
||||
multipleArgumentCall
|
||||
|
||||
@@ -4,7 +4,6 @@ uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
uniqueNodeToString
|
||||
missingToString
|
||||
parameterCallable
|
||||
localFlowIsLocal
|
||||
readStepIsLocal
|
||||
@@ -53,3 +52,5 @@ uniqueParameterNodeAtPosition
|
||||
uniqueParameterNodePosition
|
||||
uniqueContentApprox
|
||||
identityLocalStep
|
||||
missingArgumentCall
|
||||
multipleArgumentCall
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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"]);
|
||||
|
||||
@@ -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 ---
|
||||
|
||||
@@ -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>:
|
||||
|
||||
13031
cpp/ql/test/library-tests/ir/ir/aliased_ir.expected
Normal file
13031
cpp/ql/test/library-tests/ir/ir/aliased_ir.expected
Normal file
File diff suppressed because it is too large
Load Diff
11
cpp/ql/test/library-tests/ir/ir/aliased_ir.ql
Normal file
11
cpp/ql/test/library-tests/ir/ir/aliased_ir.ql
Normal 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) }
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user